www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why not move cast to the standard library?

reply downs <default_357-line yahoo.de> writes:
With all the neat template tricks we have in 2.0, and since we're widely
redefining the syntax anyway, why not deprecate the current cast syntax and
move it into object.d as a library function?

So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a keyword
and demonstrate language power at the same time.

What sez ye?
Sep 24 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Sep 24, 2009 at 12:35 PM, downs <default_357-line yahoo.de> wrote:
 With all the neat template tricks we have in 2.0, and since we're widely
redefining the syntax anyway, why not deprecate the current cast syntax and
move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a keyword
and demonstrate language power at the same time.

 What sez ye?

std.conv.to is more or less a proof-of-concept of this already. :>
Sep 24 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
downs wrote:
 With all the neat template tricks we have in 2.0, and since we're widely
redefining the syntax anyway, why not deprecate the current cast syntax and
move it into object.d as a library function?
 
 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a keyword
and demonstrate language power at the same time.
 
 What sez ye?

What would the implementation look like? Andrei
Sep 24 2009
parent reply downs <default_357-line yahoo.de> writes:
Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a
 keyword and demonstrate language power at the same time.

 What sez ye?

What would the implementation look like? Andrei

Unions, and LOTS of static ifs. :)
Sep 24 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei

Unions, and LOTS of static ifs. :)

Unions won't work for casting class objects and interfaces because those do pointer adjustments. I think cast must be a primitive. Andrei
Sep 24 2009
parent reply grauzone <none example.net> writes:
Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei

Unions, and LOTS of static ifs. :)

Unions won't work for casting class objects and interfaces because those do pointer adjustments. I think cast must be a primitive.

When casting interfaces and objects, the primitive cast just calls into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei

Sep 24 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei

Unions, and LOTS of static ifs. :)

Unions won't work for casting class objects and interfaces because those do pointer adjustments. I think cast must be a primitive.

When casting interfaces and objects, the primitive cast just calls into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


What about cast(int) or cast(string) and whatnot then? You'd have cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie
Sep 24 2009
parent reply downs <default_357-line yahoo.de> writes:
Jeremie Pelletier wrote:
 grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save
 on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei

Unions, and LOTS of static ifs. :)

Unions won't work for casting class objects and interfaces because those do pointer adjustments. I think cast must be a primitive.

When casting interfaces and objects, the primitive cast just calls into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


What about cast(int) or cast(string) and whatnot then? You'd have cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie

What about cast!int could _not_ be done as a function?
Sep 24 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
downs wrote:
 Jeremie Pelletier wrote:
 grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save
 on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei


those do pointer adjustments. I think cast must be a primitive.

into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie

What about cast!int could _not_ be done as a function?

I don't want to call into functions for simple value casts. If I want safe casts I use to!int. It may get inlined in release code, but think of the debug overhead it would generate. The current way is great as it is, cast() for straightforward unsafe casting and to!(T)() for safe casting. This is exactly what makes D attractive to me, the choice between safe and unsafe alternatives.
Sep 24 2009
parent reply downs <default_357-line yahoo.de> writes:
Jeremie Pelletier wrote:
 downs wrote:
 Jeremie Pelletier wrote:
 grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save
 on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei


those do pointer adjustments. I think cast must be a primitive.

into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie

What about cast!int could _not_ be done as a function?

I don't want to call into functions for simple value casts. If I want safe casts I use to!int. It may get inlined in release code, but think of the debug overhead it would generate. The current way is great as it is, cast() for straightforward unsafe casting and to!(T)() for safe casting. This is exactly what makes D attractive to me, the choice between safe and unsafe alternatives.

What debug overhead? With current casts, all the logic is in the compiler - where you can't get at it. Moving it into the library can only make this better. There is nothing about cast that I can see that requires dedicated compiler assistance. Furthermore, consider it a testcase - if a trivial function like that isn't inlined, _something_ is wrong :)
Sep 24 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
downs wrote:
 Jeremie Pelletier wrote:
 downs wrote:
 Jeremie Pelletier wrote:
 grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save
 on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei


those do pointer adjustments. I think cast must be a primitive.

into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie


safe casts I use to!int. It may get inlined in release code, but think of the debug overhead it would generate. The current way is great as it is, cast() for straightforward unsafe casting and to!(T)() for safe casting. This is exactly what makes D attractive to me, the choice between safe and unsafe alternatives.

What debug overhead? With current casts, all the logic is in the compiler - where you can't get at it. Moving it into the library can only make this better. There is nothing about cast that I can see that requires dedicated compiler assistance. Furthermore, consider it a testcase - if a trivial function like that isn't inlined, _something_ is wrong :)

Compile with -debug -unittest -g and you get no inlines whatsoever, even const values aren't inlined, when I run such an executable in windbg the code cursor actually goes to the declaration of enums and other constants. A lot of casts are just type reinterpretations, with a few semantics behind float to int conversions. I wouldn't give away the convenience of cast() to force everything through to!(T)(). I use cast() for most cases where I don't need anything special, and to!(T)() when I need some specific semantics. It also makes such cases much easier to notice when reading code.
Sep 24 2009
parent downs <default_357-line yahoo.de> writes:
Jeremie Pelletier wrote:
 downs wrote:
 Jeremie Pelletier wrote:
 downs wrote:
 Jeremie Pelletier wrote:
 grauzone wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 Andrei Alexandrescu wrote:
 downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the
 current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save
 on a
 keyword and demonstrate language power at the same time.

 What sez ye?

Andrei


those do pointer adjustments. I think cast must be a primitive.

into runtime (functions like _d_dynamic_cast etc.). I don't see a reason why cast implemented as templated function couldn't call those runtime functions directly.
 Andrei


cast!A(B) for classes and cast(int) for values, that would be backwards. Jeremie


safe casts I use to!int. It may get inlined in release code, but think of the debug overhead it would generate. The current way is great as it is, cast() for straightforward unsafe casting and to!(T)() for safe casting. This is exactly what makes D attractive to me, the choice between safe and unsafe alternatives.

What debug overhead? With current casts, all the logic is in the compiler - where you can't get at it. Moving it into the library can only make this better. There is nothing about cast that I can see that requires dedicated compiler assistance. Furthermore, consider it a testcase - if a trivial function like that isn't inlined, _something_ is wrong :)

Compile with -debug -unittest -g and you get no inlines whatsoever, even const values aren't inlined, when I run such an executable in windbg the code cursor actually goes to the declaration of enums and other constants. A lot of casts are just type reinterpretations, with a few semantics behind float to int conversions. I wouldn't give away the convenience of cast() to force everything through to!(T)(). I use cast() for most cases where I don't need anything special, and to!(T)() when I need some specific semantics. It also makes such cases much easier to notice when reading code.

Good argument. Thanks.
Sep 24 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 24 Sep 2009 12:35:22 -0400, downs <default_357-line yahoo.de>  
wrote:

 With all the neat template tricks we have in 2.0, and since we're widely  
 redefining the syntax anyway, why not deprecate the current cast syntax  
 and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on a  
 keyword and demonstrate language power at the same time.

 What sez ye?

What is the benefit? Does it allow anything that isn't possible today (aside from using cast as a member, which I find not that worthy)? What I'd much rather have is directed casts, even if they are supported by the compiler, such as the casting features of C++ (i.e. const_cast and static_cast). I actually prefer the compiler to handle the casting versus templates to cut down on template instantiation bloat. -Steve
Sep 24 2009
next sibling parent reply downs <default_357-line yahoo.de> writes:
language_fan wrote:
 Thu, 24 Sep 2009 13:47:21 -0400, Steven Schveighoffer thusly wrote:
 
 I actually prefer the compiler to handle the casting versus templates to
 cut down on template instantiation bloat.

I wonder how D scales to 100 MLOC programs as the template instantiations can be troublesome already in < 1000 LOC programs.

We write templates in < 1000 LOC programs to avoid having to write 100 MLOC :) Also, let me categorically state: if you're writing 100MLOC programs, you're doing it horribly, horribly wrong. No conceivable program possibly requires that much logic.
Sep 24 2009
parent reply Don <nospam nospam.com> writes:
language_fan wrote:
 Thu, 24 Sep 2009 21:13:48 +0200, downs thusly wrote:
 
 language_fan wrote:
 Thu, 24 Sep 2009 13:47:21 -0400, Steven Schveighoffer thusly wrote:

 I actually prefer the compiler to handle the casting versus templates
 to cut down on template instantiation bloat.

instantiations can be troublesome already in < 1000 LOC programs.

MLOC :) Also, let me categorically state: if you're writing 100MLOC programs, you're doing it horribly, horribly wrong. No conceivable program possibly requires that much logic.

I agree, usually there is *something* wrong with your program if it gets that large. I personally do not consider programs of that size very reliable. But the thing is, you probably know that people fear template instantiations. Not only can they cause really weird linking bugs, the more templates you have, the larger the executables get. Also as dmd does not use garbage collection (yet?) during compilation, the instantiations can easily kill the compilation process. Sometimes templates are abused to do what macros were supposed to by used for. I can imagine that templates can cause problems much sooner, you do not even need 1 MLOC of code to do that. Apparently D will never get a powerful macro system since the focus is on other features and templates seem to work just fine on the small scale.

That's not the reason. A bit of history: A macro system was planned for D2, and 'macro' was made a reserved word. But in discussions at the end of the first D conference, I demonstrated that the combination of CTFE + string mixins, even in D1, was dramatically more powerful than the proposed macros. It became clear that we didn't have a macro design that was anywhere near powerful enough, and macros were postponed to D3. We don't know how they should work. By all means make a proposal.
Sep 25 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 macro max(int a, int b) {
 	return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b;
 }

In std.metastrings there's Format that allows to use a basic form of string templating, that I find a little more readable than many string concats: return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b; ==> Format!("return %s > %s ? %s : %s;", a, b, a, b); Or safer: Format!("return %d > %d ? %d : %d;", a, b, a, b); Or more readable, something like: return "{a} > {b} ? {a} : {b};" % (a, b, a, b); Bye, bearophile
Sep 25 2009
prev sibling next sibling parent Yigal Chripun <yigal100 gmail.com> writes:
On 25/09/2009 18:32, Robert Jacques wrote:
 On Fri, 25 Sep 2009 03:29:21 -0400, Don <nospam nospam.com> wrote:
 [snip]
 A bit of history: A macro system was planned for D2, and 'macro' was
 made a reserved word. But in discussions at the end of the first D
 conference, I demonstrated that the combination of CTFE + string
 mixins, even in D1, was dramatically more powerful than the proposed
 macros. It became clear that we didn't have a macro design that was
 anywhere near powerful enough, and macros were postponed to D3. We
 don't know how they should work.
 By all means make a proposal.

About the only thing I find lacking today is the ability to do zero weight expression templates. I think fleshing out the alias keyword might do the trick (i.e. alias tuples + alias function parameters) but I haven't though it all through.

My preferred design, which I can't imagine implemented in the near future, would be something in these lines: (disclaimer: heavily influenced by Nemerle) 1. macro definitions are separate from regular code. Macros are compiled into libs that are loaded by the compiler: something like: dmd --load-macro=my_macro.dll mysource.d (can be implemented as DDLs for portability) 2. macros contain regular D code and can use facilities from the stdlib to manipulate their input (examples will follow) 3. macros can either be called from regular code with function call syntax or by using an attribute system to specify hook points. e.g. int result = max_macro(50, 90); // transformed to: "int result = 90;" [macro(params)] // some imaginary attribute/annotations syntax class Class { .... } examples of macro definitions: a) CTFE replacement: macro max(int a, int b) { return (a > b) ? a : b; } b) operate on the current AST node: /// stdlib provided utilities to work with the AST import Compiler.AST; import Compiler.parser; macro (AST input) { // input is set by compiler to the current AST sub-tree return some_ast_transform(input); // can call regular functions to implement macros } c) compile-time vs. run-time : macro () { Stdout("Compile time").newline; //printed at compile-time return AST("Stdout(\"Run time\").newline;"); //printed at run-time } The Compiler package above provides facilities for the programmer to directly manipulate the AST in a standard way with API calls instead of string manipulations.
Sep 26 2009
prev sibling next sibling parent Don <nospam nospam.com> writes:
Adam D. Ruppe wrote:
 On Fri, Sep 25, 2009 at 09:29:21AM +0200, Don wrote:
 I demonstrated that the combination of CTFE + string mixins, 
 even in D1, was dramatically more powerful than the proposed macros. It 
 became clear that we didn't have a macro design that was anywhere near 
 powerful enough, and macros were postponed to D3. We don't know how they 
 should work.
 By all means make a proposal.

I was thinking of a simple one for D2 a while back, but canceled my post since it is basically just sugar for what it does now. But, on the other hand, that is a bit simpler to implement, so let me throw it out. I propose that a macro (in D2; I don't know about a more elegant D3 design) is merely a CTFE function that is mixed in, and takes symbols as strings. Let me give an example: ==== macro max(int a, int b) { return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b; } void main() { auto num1 = 10; auto num2 = 20; auto result = max(num1, num2); } ==== This would be the same as: ==== string max(string a, string b) { return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b; } void main() { auto num1 = 10; auto num2 = 20; auto result = mixin(max("num1", "num2")); } =============== So: a) A macro function always returns a string, which is mixed in at the point where you used it b) Its arguments are actually strings. (I don't know if I'm happy with what I did in the above example, using int when they are actually string, but having some type checking seems more sane than actually going all string. All string feels too C preprocessor like.) c) All the arguments are the name of the variable as a string. It basically just tosses quotes around whatever you literally wrote on the line when you used it. (So passing a string literal would actually send "\"what you wrote\"" to the macro.) This doesn't do anything we can't already do with the language, but I think it looks a little prettier, which might make the functions a bit easier for the user. Though it would still be the same for the lib writer, of course.

I agree, for a user that'd give you all the syntax sugar you'd hope for from a macro. You haven't said what happens with arguments which are expressions rather than symbols, though, and that's the interesting bit. I'd propose it just does a .stringof on them. Basically the same as what my BLADE library did manually. It'd actually be interesting to see how much ugliness is left after doing that. Further refinement of macro proposals might be aimed at removing whatever hackiness is left.
Sep 29 2009
prev sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Fri, 25 Sep 2009 15:35:11 -0400, Adam D. Ruppe wrote:
 ====
 macro max(int a, int b) {
 	return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b;
 }
 
 void main() {
 	auto num1 = 10;
 	auto num2 = 20;
 
 	auto result = max(num1, num2);
 }
 ====

While I like and support the idea, I think that hijacking the "macro" keyword now will make it very hard to re-design later. It would be much better to reuse the "mixin" keyword for this since it's exactly what's happening: defining a function for mixing in: mixin max(int a, int b) {...} It could be problematic from the grammar perspective though.
Oct 03 2009
parent Sergey Gromov <snake.scaly gmail.com> writes:
Sat, 3 Oct 2009 21:33:37 -0400, Jarrett Billingsley wrote:

 On Sat, Oct 3, 2009 at 9:22 PM, Sergey Gromov <snake.scaly gmail.com> wrote:
 
 While I like and support the idea, I think that hijacking the "macro"
 keyword now will make it very hard to re-design later.  It would be much
 better to reuse the "mixin" keyword for this since it's exactly what's
 happening: defining a function for mixing in:

 mixin max(int a, int b) {...}

 It could be problematic from the grammar perspective though.

Newp. 'mixin' could be followed by one of four things: - '(', it's a string mixin. - 'ident' '!', it's a template mixin. - 'ident' ';' it's also a template mixin. - 'ident' '(', it's a mixin declaration. Not tough. But then you're really overloading the keyword by using it for three very different purposes.

I cannot see how this is "very different" from what it does currently. I'm declaring a function intended specifically for mixing in. That's what you usually do. I'm just moving the "mixin" keyword from every single function invocation to its declaration, reducing the unnecessary typing and ugliness. I can see a problem with this approach though, that something that looks lke a function call can be actually a mixin with full access to the container function scope. Explicit mixins are, well, explicit in this respect.
Oct 04 2009
prev sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
language_fan wrote:
 Thu, 24 Sep 2009 13:47:21 -0400, Steven Schveighoffer thusly wrote:
 
 I actually prefer the compiler to handle the casting versus templates to
 cut down on template instantiation bloat.

I wonder how D scales to 100 MLOC programs as the template instantiations can be troublesome already in < 1000 LOC programs.

It scales to a few hundred kLoC if you don't abuse templates (too much) and sacrifice your firstborn to OPTLINK. I don't know what's further, perhaps a hecatomb would do. On a more serious note, the number of template instantiations will probably be more of the logarithmic kind with respect to LoC count. Unless you do everything in a generic way. But writing this sort of code is a major PITA and often a waste of time. -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Sep 24 2009
prev sibling next sibling parent Yigal Chripun <yigal100 gmail.com> writes:
On 24/09/2009 19:35, downs wrote:
 With all the neat template tricks we have in 2.0, and since we're
 widely redefining the syntax anyway, why not deprecate the current
 cast syntax and move it into object.d as a library function?

 So instead of cast(Foo) bar; you would say cast!Foo(bar); .. save on
 a keyword and demonstrate language power at the same time.

 What sez ye?

vote++; casts and especially implicit casts are evil. The programmer should always prefer calling a conversion function instead of relying on casts. for example, for FP -> integer conversion the user may need to change the rounding/truncation behavior.
Sep 24 2009
prev sibling next sibling parent language_fan <foo bar.com.invalid> writes:
Thu, 24 Sep 2009 13:47:21 -0400, Steven Schveighoffer thusly wrote:

 I actually prefer the compiler to handle the casting versus templates to
 cut down on template instantiation bloat.

I wonder how D scales to 100 MLOC programs as the template instantiations can be troublesome already in < 1000 LOC programs.
Sep 24 2009
prev sibling next sibling parent language_fan <foo bar.com.invalid> writes:
Thu, 24 Sep 2009 21:13:48 +0200, downs thusly wrote:

 language_fan wrote:
 Thu, 24 Sep 2009 13:47:21 -0400, Steven Schveighoffer thusly wrote:
 
 I actually prefer the compiler to handle the casting versus templates
 to cut down on template instantiation bloat.

I wonder how D scales to 100 MLOC programs as the template instantiations can be troublesome already in < 1000 LOC programs.

We write templates in < 1000 LOC programs to avoid having to write 100 MLOC :) Also, let me categorically state: if you're writing 100MLOC programs, you're doing it horribly, horribly wrong. No conceivable program possibly requires that much logic.

I agree, usually there is *something* wrong with your program if it gets that large. I personally do not consider programs of that size very reliable. But the thing is, you probably know that people fear template instantiations. Not only can they cause really weird linking bugs, the more templates you have, the larger the executables get. Also as dmd does not use garbage collection (yet?) during compilation, the instantiations can easily kill the compilation process. Sometimes templates are abused to do what macros were supposed to by used for. I can imagine that templates can cause problems much sooner, you do not even need 1 MLOC of code to do that. Apparently D will never get a powerful macro system since the focus is on other features and templates seem to work just fine on the small scale.
Sep 24 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Fri, 25 Sep 2009 03:29:21 -0400, Don <nospam nospam.com> wrote:
[snip]
 A bit of history: A macro system was planned for D2, and 'macro' was  
 made a reserved word. But in discussions at the end of the first D  
 conference, I demonstrated that the combination of CTFE + string mixins,  
 even in D1, was dramatically more powerful than the proposed macros. It  
 became clear that we didn't have a macro design that was anywhere near  
 powerful enough, and macros were postponed to D3. We don't know how they  
 should work.
 By all means make a proposal.

About the only thing I find lacking today is the ability to do zero weight expression templates. I think fleshing out the alias keyword might do the trick (i.e. alias tuples + alias function parameters) but I haven't though it all through.
Sep 25 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Fri, Sep 25, 2009 at 09:29:21AM +0200, Don wrote:
 I demonstrated that the combination of CTFE + string mixins, 
 even in D1, was dramatically more powerful than the proposed macros. It 
 became clear that we didn't have a macro design that was anywhere near 
 powerful enough, and macros were postponed to D3. We don't know how they 
 should work.
 By all means make a proposal.

I was thinking of a simple one for D2 a while back, but canceled my post since it is basically just sugar for what it does now. But, on the other hand, that is a bit simpler to implement, so let me throw it out. I propose that a macro (in D2; I don't know about a more elegant D3 design) is merely a CTFE function that is mixed in, and takes symbols as strings. Let me give an example: ==== macro max(int a, int b) { return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b; } void main() { auto num1 = 10; auto num2 = 20; auto result = max(num1, num2); } ==== This would be the same as: ==== string max(string a, string b) { return a ~ " > " ~ b ~ " ? " ~ a ~ " : " ~ b; } void main() { auto num1 = 10; auto num2 = 20; auto result = mixin(max("num1", "num2")); } =============== So: a) A macro function always returns a string, which is mixed in at the point where you used it b) Its arguments are actually strings. (I don't know if I'm happy with what I did in the above example, using int when they are actually string, but having some type checking seems more sane than actually going all string. All string feels too C preprocessor like.) c) All the arguments are the name of the variable as a string. It basically just tosses quotes around whatever you literally wrote on the line when you used it. (So passing a string literal would actually send "\"what you wrote\"" to the macro.) This doesn't do anything we can't already do with the language, but I think it looks a little prettier, which might make the functions a bit easier for the user. Though it would still be the same for the lib writer, of course. -- Adam D. Ruppe http://arsdnet.net
Sep 25 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Oct 3, 2009 at 9:22 PM, Sergey Gromov <snake.scaly gmail.com> wrote=
:

 While I like and support the idea, I think that hijacking the "macro"
 keyword now will make it very hard to re-design later. =A0It would be muc=

 better to reuse the "mixin" keyword for this since it's exactly what's
 happening: defining a function for mixing in:

 mixin max(int a, int b) {...}

 It could be problematic from the grammar perspective though.

Newp. 'mixin' could be followed by one of four things: - '(', it's a string mixin. - 'ident' '!', it's a template mixin. - 'ident' ';' it's also a template mixin. - 'ident' '(', it's a mixin declaration. Not tough. But then you're really overloading the keyword by using it for three very different purposes.
Oct 03 2009