From 2631a8b145985bec06f9b2bc44479bc54590c3a1 Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Sun, 19 Jan 2025 07:08:37 +0100 Subject: [PATCH 1/2] Fix #10023 - Add `ctEval` to Phobos --- std/functional.d | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/std/functional.d b/std/functional.d index b1b1382280d..f9685e299ca 100644 --- a/std/functional.d +++ b/std/functional.d @@ -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. @@ -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); +} From 4e2156110af126ec6cde182c52bd2651346ca2ac Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Mon, 3 Feb 2025 23:03:49 +0100 Subject: [PATCH 2/2] =?UTF-8?q?Address=20pbackus=E2=80=99=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paul Backus --- std/functional.d | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/std/functional.d b/std/functional.d index f9685e299ca..2ecf6a35ac6 100644 --- a/std/functional.d +++ b/std/functional.d @@ -52,7 +52,7 @@ $(TR $(TH Function Name) $(TH Description) $(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. + $(TD Enforces the evaluation of an expression during compile-time. )) )) @@ -2172,20 +2172,20 @@ template bind(alias fun) } /** - * Enforces the execution of a function during compile-time. + * Enforces the evaluation of an expression during compile-time. * - * Computes the return value of a function call during compilation (CTFE). + * Computes the value of an expression during compilation (CTFE). * * This is useful for call chains in functional programming - * where no explicit `enum` can be placed inline and would require splitting + * where declaring an `enum` constant would require splitting * the pipeline. * * Params: - * fun = callable to evaluate + * expr = expression to evaluate * See_also: * $(LINK https://dlang.org/spec/function.html#interpretation) */ -enum ctEval(alias fun) = fun; +enum ctEval(alias expr) = expr; /// @safe unittest