Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions std/functional.d
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ $(TR $(TH Function Name) $(TH Description)
$(TR $(TD $(LREF bind))
$(TD Passes the fields of a struct as arguments to a function.
))
$(TR $(TD $(LREF ctEval))
$(TD Enforces the execution of a function during compile-time.
))
))

Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
Expand Down Expand Up @@ -2167,3 +2170,50 @@ template bind(alias fun)
static assert(!__traits(isRef, x));
});
}

/**
* Enforces the execution of a function during compile-time.
*
* Computes the return value of a function call during compilation (CTFE).
*
* This is useful for call chains in functional programming
* where no explicit `enum` can be placed inline and would require splitting
* the pipeline.
*
* Params:
* fun = callable to evaluate
* See_also:
* $(LINK https://dlang.org/spec/function.html#interpretation)
*/
enum ctEval(alias fun) = fun;

///
@safe unittest
{
import std.math : abs;

// No explicit `enum` needed.
float result = ctEval!(abs(-3));
assert(result == 3);

// Can be statically asserted.
static assert(ctEval!(abs(-4)) == 4);
static assert(ctEval!(abs( 9)) == 9);
}

///
@safe unittest
{
import core.stdc.math : round;
import std.conv : to;
import std.math : abs, PI, sin;

// `round` from the C standard library cannot be interpreted at compile
// time, because it has no available source code. However the function
// calls preceding `round` can be evaluated during compile time.
int result = ctEval!(abs(sin(1.0)) * 180 / PI)
.round()
.to!int();

assert(result == 48);
}
Loading