digitalmars.D - Using "cast(enum)" for explicit request of ctfe
- monarch_dodra (44/44) Dec 04 2013 I love D's ctfe capabilities. They allow using complex values,
- Jakob Ovrum (3/5) Dec 04 2013 alias eval(alias exp) = exp;
- monarch_dodra (8/13) Dec 04 2013 Nice :D
- Jakob Ovrum (16/32) Dec 04 2013 Right, maybe it should be (substitute the name `eval`):
- monarch_dodra (7/21) Dec 04 2013 Problem is that doing this returns an immutable type, which isn't
- Jakob Ovrum (11/14) Dec 04 2013 Immutable "global" variables with initializers are readable at
- monarch_dodra (23/35) Dec 04 2013 I mean that:
- luka8088 (4/48) Dec 04 2013 I don't think so. With type inference a is immutable.
- monarch_dodra (13/24) Dec 04 2013 Right, but that's my point. If you use an enum, as opposed to a
- luka8088 (2/17) Dec 04 2013 Eval comes from examples of http://dlang.org/function.html#interpretatio...
- Jakob Ovrum (9/11) Dec 04 2013 A couple of notes:
- luka8088 (3/15) Dec 04 2013 Oh, I didn't know that. Thanks!
- monarch_dodra (2/26) Dec 04 2013 Alright, then eval is fine.
- luka8088 (8/63) Dec 04 2013 You can use Eval template:
I love D's ctfe capabilities. They allow using complex values, with no run-time cost, and at a very low "code" cost. One thing that does kind of get on my nerves is how you *always* have to declare an actual enum to do that. You can't do CTFE on the fly. This ranges from mildly annoying, typically: //Declare a CTFE message enum message = format("Some message: %s", some_static_args); //Use the CTFE message enforce(pointer, message); Or, also, enum fib5 = fib(5); //CTFE calculate writeln(fib5); //use To, sometimes, downright *impossible*. If you ever need to do CTFE inside the body of a static foreach, dmd will block you due to "redeclaration": foreach(T; Types) { enum message = format("This type is %s.", T.stringof); //Error! Redaclaration writeln(message); } Fixing this one requies an external template that will create your enum on the fly. ---------------- I'm thinking: While this is all surmountable, I'm pretty sure the language could give us a easier time of this. We have the possibility to declare and call a lambda both in one line. Why not be able to declare a ctfe value as a 1-liner too? I'm thinking, a simple cast: A cast to the "enum" type, which explicitly means "this value needs to be compile time known". Usage would look like: enforce(pointer, cast(enum)format("Some message: %s", some_static_args)); writeln(cast(enum)fib(5)); foreach(T; Types) writeln(cast(enum)format("This type is %s.", T.stringof)); Here, we have some very simple code, no redundant variables, and no run-time overhead. I'm just throwing this out there to get some quick feedback before filling an ER, or maybe a DIP. Or, if somebody has an idea of how to do this via a library solution? Thoughts?
Dec 04 2013
On Wednesday, 4 December 2013 at 11:12:54 UTC, monarch_dodra wrote:Or, if somebody has an idea of how to do this via a library solution?alias eval(alias exp) = exp;
Dec 04 2013
On Wednesday, 4 December 2013 at 11:32:40 UTC, Jakob Ovrum wrote:On Wednesday, 4 December 2013 at 11:12:54 UTC, monarch_dodra wrote:Nice :D Very very nice. Though that should be "enum" I think. I think having this somewhere in Phobos would be a great addition. Not sure "eval" would be correct though, as "eval" tends to imply parsing. I'll just file a simple ER then. Where would we put such an addition?Or, if somebody has an idea of how to do this via a library solution?alias eval(alias exp) = exp;
Dec 04 2013
On Wednesday, 4 December 2013 at 11:41:53 UTC, monarch_dodra wrote:On Wednesday, 4 December 2013 at 11:32:40 UTC, Jakob Ovrum wrote:Right, maybe it should be (substitute the name `eval`): --- template eval(alias exp) if(isExpressionTuple!exp) { static immutable eval = exp; } --- Which might make it avoid the pitfalls of using enum. Not sure if the `static` actually does something in this context, IIRC it does not. No idea where to put it. I've experimented with such a template before but I haven't used it in any real code. object.d and std.typecons come to mind, but I don't particularly like the prospect of putting it in either.On Wednesday, 4 December 2013 at 11:12:54 UTC, monarch_dodra wrote:Nice :D Very very nice. Though that should be "enum" I think. I think having this somewhere in Phobos would be a great addition. Not sure "eval" would be correct though, as "eval" tends to imply parsing. I'll just file a simple ER then. Where would we put such an addition?Or, if somebody has an idea of how to do this via a library solution?alias eval(alias exp) = exp;
Dec 04 2013
On Wednesday, 4 December 2013 at 11:51:11 UTC, Jakob Ovrum wrote:Right, maybe it should be (substitute the name `eval`): --- template eval(alias exp) if(isExpressionTuple!exp) { static immutable eval = exp; } --- Which might make it avoid the pitfalls of using enum. Not sure if the `static` actually does something in this context, IIRC it does not.Problem is that doing this returns an immutable type, which isn't quite the same as a ctfe variable (which was the initial goal, as far as I'm concerned)No idea where to put it. I've experimented with such a template before but I haven't used it in any real code. object.d and std.typecons come to mind, but I don't particularly like the prospect of putting it in either.Yeah... I wouldn't want to import all of typecons just for this, but if we split it into packages, it would perfectly fit in its own little package (IMO).
Dec 04 2013
On Wednesday, 4 December 2013 at 13:16:35 UTC, monarch_dodra wrote:Problem is that doing this returns an immutable type, which isn't quite the same as a ctfe variable (which was the initial goal, as far as I'm concerned)Immutable "global" variables with initializers are readable at compile-time (as the initializers are required to be readable at compile-time). I don't know what you mean by "CTFE variable". It's probably better to use const over immutable though, so that it can accept values of a type with mutable indirection. Using enum has issues, as elaborated upon by Don in this enhancement request[1] (for reference; I'm sure you remember them). [1] http://d.puremagic.com/issues/show_bug.cgi?id=10950
Dec 04 2013
On Wednesday, 4 December 2013 at 13:45:35 UTC, Jakob Ovrum wrote:On Wednesday, 4 December 2013 at 13:16:35 UTC, monarch_dodra wrote:I mean that: auto a = eval!(1 + 2); a += 1; // <= cannot modify immutable expression 3 Should work. Or that: auto arr = eval!(iota(0, 10).array()); //arr is expected to be int[] //NOT immutable(int[]) arr[0] = 10; //Error: cannot modify immutable expression arr[0] Long story short, just because something is pre-calculated with CTFE doesn't mean it can't be mutable. For example: enum a10 = iota(0, 10).array(); auto arr1 = a10; auto arr2 = a10; assert(arr1 !is arr2); assert(arr1 == arr2); arr1[0] = 10; assert(arr1 != arr2);Problem is that doing this returns an immutable type, which isn't quite the same as a ctfe variable (which was the initial goal, as far as I'm concerned)Immutable "global" variables with initializers are readable at compile-time (as the initializers are required to be readable at compile-time). I don't know what you mean by "CTFE variable".Using enum has issues, as elaborated upon by Don in this enhancement request[1] (for reference; I'm sure you remember them). [1] http://d.puremagic.com/issues/show_bug.cgi?id=10950I absolutely remember that. But I still believe that is a *bug*, and not an enhancement request. Buggy behavior should not dictate our design.
Dec 04 2013
On 4.12.2013. 16:28, monarch_dodra wrote:On Wednesday, 4 December 2013 at 13:45:35 UTC, Jakob Ovrum wrote:I don't think so. With type inference a is immutable. int a = eval!(1 + 2); Works.On Wednesday, 4 December 2013 at 13:16:35 UTC, monarch_dodra wrote:I mean that: auto a = eval!(1 + 2); a += 1; // <= cannot modify immutable expression 3 Should work.Problem is that doing this returns an immutable type, which isn't quite the same as a ctfe variable (which was the initial goal, as far as I'm concerned)Immutable "global" variables with initializers are readable at compile-time (as the initializers are required to be readable at compile-time). I don't know what you mean by "CTFE variable".Or that: auto arr = eval!(iota(0, 10).array()); //arr is expected to be int[] //NOT immutable(int[]) arr[0] = 10; //Error: cannot modify immutable expression arr[0] Long story short, just because something is pre-calculated with CTFE doesn't mean it can't be mutable. For example: enum a10 = iota(0, 10).array(); auto arr1 = a10; auto arr2 = a10; assert(arr1 !is arr2); assert(arr1 == arr2); arr1[0] = 10; assert(arr1 != arr2);Using enum has issues, as elaborated upon by Don in this enhancement request[1] (for reference; I'm sure you remember them). [1] http://d.puremagic.com/issues/show_bug.cgi?id=10950I absolutely remember that. But I still believe that is a *bug*, and not an enhancement request. Buggy behavior should not dictate our design.
Dec 04 2013
On Thursday, 5 December 2013 at 07:36:30 UTC, luka8088 wrote:On 4.12.2013. 16:28, monarch_dodra wrote:Right, but that's my point. If you use an enum, as opposed to a global immutable, it *does* work. Also, your rebuke works for the trivial int type, but not for a more complicated type with indirection, such as a dynamic array, and even less so a struct with a complex structure. -------- Having a template that stores a single global-static-immutable value also has its uses (which I have *also* used in phobos, more than once. But: a) It's for a different use case. b) The use cases where specific enough that not having "on-the-fly" template to do it.I mean that: auto a = eval!(1 + 2); a += 1; // <= cannot modify immutable expression 3 Should work.I don't think so. With type inference a is immutable. int a = eval!(1 + 2); Works.
Dec 04 2013
On 4.12.2013. 12:41, monarch_dodra wrote:On Wednesday, 4 December 2013 at 11:32:40 UTC, Jakob Ovrum wrote:Eval comes from examples of http://dlang.org/function.html#interpretationOn Wednesday, 4 December 2013 at 11:12:54 UTC, monarch_dodra wrote:Nice :D Very very nice. Though that should be "enum" I think. I think having this somewhere in Phobos would be a great addition. Not sure "eval" would be correct though, as "eval" tends to imply parsing. I'll just file a simple ER then. Where would we put such an addition?Or, if somebody has an idea of how to do this via a library solution?alias eval(alias exp) = exp;
Dec 04 2013
On Wednesday, 4 December 2013 at 11:54:08 UTC, luka8088 wrote:Eval comes from examples of http://dlang.org/function.html#interpretationA couple of notes: The use of a variadic template parameter instead of an alias parameter is misleading because the template does not need to support types in the first place (and the proposed implementation would fail when given a type). The name used on dlang.org is correctly using a lowercase `e`, according to the naming convention for templates that always evaluate to values/variables as opposed to types.
Dec 04 2013
On 4.12.2013. 13:08, Jakob Ovrum wrote:On Wednesday, 4 December 2013 at 11:54:08 UTC, luka8088 wrote:Yeah. I guess it is a documentation (example) issue.Eval comes from examples of http://dlang.org/function.html#interpretationA couple of notes: The use of a variadic template parameter instead of an alias parameter is misleading because the template does not need to support types in the first place (and the proposed implementation would fail when given a type).The name used on dlang.org is correctly using a lowercase `e`, according to the naming convention for templates that always evaluate to values/variables as opposed to types.Oh, I didn't know that. Thanks!
Dec 04 2013
On Wednesday, 4 December 2013 at 11:54:08 UTC, luka8088 wrote:On 4.12.2013. 12:41, monarch_dodra wrote:Alright, then eval is fine.On Wednesday, 4 December 2013 at 11:32:40 UTC, Jakob Ovrum wrote:Eval comes from examples of http://dlang.org/function.html#interpretationOn Wednesday, 4 December 2013 at 11:12:54 UTC, monarch_dodra wrote:Nice :D Very very nice. Though that should be "enum" I think. I think having this somewhere in Phobos would be a great addition. Not sure "eval" would be correct though, as "eval" tends to imply parsing. I'll just file a simple ER then. Where would we put such an addition?Or, if somebody has an idea of how to do this via a library solution?alias eval(alias exp) = exp;
Dec 04 2013
On 4.12.2013. 12:12, monarch_dodra wrote:I love D's ctfe capabilities. They allow using complex values, with no run-time cost, and at a very low "code" cost. One thing that does kind of get on my nerves is how you *always* have to declare an actual enum to do that. You can't do CTFE on the fly. This ranges from mildly annoying, typically: //Declare a CTFE message enum message = format("Some message: %s", some_static_args); //Use the CTFE message enforce(pointer, message); Or, also, enum fib5 = fib(5); //CTFE calculate writeln(fib5); //use To, sometimes, downright *impossible*. If you ever need to do CTFE inside the body of a static foreach, dmd will block you due to "redeclaration": foreach(T; Types) { enum message = format("This type is %s.", T.stringof); //Error! Redaclaration writeln(message); } Fixing this one requies an external template that will create your enum on the fly. ---------------- I'm thinking: While this is all surmountable, I'm pretty sure the language could give us a easier time of this. We have the possibility to declare and call a lambda both in one line. Why not be able to declare a ctfe value as a 1-liner too? I'm thinking, a simple cast: A cast to the "enum" type, which explicitly means "this value needs to be compile time known". Usage would look like: enforce(pointer, cast(enum)format("Some message: %s", some_static_args)); writeln(cast(enum)fib(5)); foreach(T; Types) writeln(cast(enum)format("This type is %s.", T.stringof)); Here, we have some very simple code, no redundant variables, and no run-time overhead. I'm just throwing this out there to get some quick feedback before filling an ER, or maybe a DIP. Or, if somebody has an idea of how to do this via a library solution? Thoughts?You can use Eval template: template Eval (alias value) { alias value Eval; } writeln(Eval!(1 + 1)); enforce(pointer, Eval!(format("Some message: %s", some_static_args))); Does this answer your question?
Dec 04 2013