www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - But... I don't want my delegates to be lazy - breeding advice

reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter, if you *really* want to keep lazy expression evaluation in its 
current form, then please *at least* don't force everyone to use it.

Adopting delegate function parameters for lazy expressions is a mistake. 
At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
please. The syntax could look like:

void foo(int expression() foo) {
}

or

void foo(lazy int foo) {
}

or just some other variant. Delegates would then be delegates and 
wouldn't accept lazy expressions. But lazy expressions could accept 
delegates.


The above approach has three significant advantages over the current 
state of things:

1. When the coder doesn't intend to use lazy expression evaluation, 
his/her functions that take delegates as params won't silently accept 
lazily evaluated expressions
2. Less existing code will be broken or the changes will be easier to 
fix - renaming the keyword to some other variable name compared to the 
nontrivial fixes that have to be done now.
3. In future, the 'expression' or 'lazy' types might provide meta-data 
allowing advanced metaprogramming techniques

The third point is important because lazy expressions in their current 
form simply can't replace expression templates. Even by looking at the 
first resource available on google...

http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html

... it's clear that one of the most important points behind expression 
templates is the ability to deconstruct expressions and basing on their 
internal structure, generate highly optimized code. At least that's what 
game developers use to make their linear algebra libraries as fast as 
possible.
This is only possible by knowing the structure of the expression and 
applying localized and specialized optimizations.

The 'expression' or 'lazy' types might work in a similar way. They would 
allow the programmer to inspect parse trees at compile-time and generate 
specially tailored code.

Currently the only performance advantage that can be accomplished with 
lazy expression evaluation is when the compiler determines the delegate 
might be inlined, which currently doesn't happen at all.


--
Tomasz Stachowiak
Aug 22 2006
next sibling parent kris <foo bar.com> writes:
Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.
 
 
 -- 
 Tomasz Stachowiak

Amen
Aug 22 2006
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Tom S wrote:

 Walter, if you *really* want to keep lazy expression evaluation in its
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake.
 At least consider adding a new keyword, e.g. 'lazy' or 'expression',
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and
 wouldn't accept lazy expressions. But lazy expressions could accept
 delegates.
 
 
 The above approach has three significant advantages over the current
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation,
 his/her functions that take delegates as params won't silently accept
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to
 fix - renaming the keyword to some other variable name compared to the
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current
 form simply can't replace expression templates. Even by looking at the
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression
 templates is the ability to deconstruct expressions and basing on their
 internal structure, generate highly optimized code. At least that's what
 game developers use to make their linear algebra libraries as fast as
 possible.
 This is only possible by knowing the structure of the expression and
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would
 allow the programmer to inspect parse trees at compile-time and generate
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with
 lazy expression evaluation is when the compiler determines the delegate
 might be inlined, which currently doesn't happen at all.
 
 
 --
 Tomasz Stachowiak

Yes, I agree. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Aug 22 2006
prev sibling next sibling parent Gregor Richards <Richards codu.org> writes:
Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.
 
 
 -- 
 Tomasz Stachowiak

Hear hear, I agree 100%. - Gregor Richards
Aug 22 2006
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.

What he said :-p Sean
Aug 22 2006
prev sibling next sibling parent reply David Medlock <noone nowhere.com> writes:
Tom S wrote:

 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.
 
 
 -- 
 Tomasz Stachowiak

I agree a keyword might be appropriate here, so as to ease the pain of current C/C++ programmers moving to the Light side. While I am shooting my mouth off, let me chime in with those who think the *auto* keyword should be *var* for automatic type inferencing. I know keywords should be used sparingly but these are fairly big features. -DavidM
Aug 22 2006
parent Gregor Richards <Richards codu.org> writes:
David Medlock wrote:
 I agree a keyword might be appropriate here, so as to ease the pain of 
 current C/C++ programmers moving to the Light side.
 

IMHO it has nothing to do with C/C++ programmers moving over. It's bad because: 1) It's not intuitive to cast expressions into anonymous delegates. 2) It causes ridiculous overload issues: class A {...} class B : A {...} void q(A a); void q(void delegate() a); void whatever() { B b = new B(); q(b); // this should not be ambiguous, but is } 3) If I understand, the expression will be evaluated multiple times, once every time you use it in the function, unless you copy it into a different value, which is just painful. - Gregor Richards
Aug 22 2006
prev sibling next sibling parent Wim Vander Schelden <wim.vanderschelden+spam gmail.com> writes:
On Tue, 22 Aug 2006 18:39:57 +0100, Tom S wrote:

 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.

I agree completely.
Aug 22 2006
prev sibling next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.

I think this is probably the most sensible proposal yet. Let me think about it a bit.
Aug 22 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Ok, I've thought about it a bit:

	void foo(int x);	// same as before 0.165
	void foo(int delegate() x)	// same as before 0.165

and now:

	void foo(lazy int x);

In other words, 'lazy' is now a parameter storage class. This means that:

	void foo(int x);
	void foo(lazy int x);

cannot be distinguished based on overloading, but:

	void foo(lazy int x);
	void foo(int delegate() x);

can be. The implicit conversion of a value to a delegate returning that 
value would be removed. The conversion happens always (not implicitly) 
if the parameter storage class is 'lazy'.
Aug 23 2006
next sibling parent Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 23 Aug 2006 22:54:35 -0700, Walter Bright wrote:

 Ok, I've thought about it a bit:
 
 	void foo(int x);	// same as before 0.165
 	void foo(int delegate() x)	// same as before 0.165
 
 and now:
 
 	void foo(lazy int x);
 
 In other words, 'lazy' is now a parameter storage class. This means that:
 
 	void foo(int x);
 	void foo(lazy int x);
 
 cannot be distinguished based on overloading, but:
 
 	void foo(lazy int x);
 	void foo(int delegate() x);
 
 can be. The implicit conversion of a value to a delegate returning that 
 value would be removed. The conversion happens always (not implicitly) 
 if the parameter storage class is 'lazy'.

Thanks for do this Walter. The idea of converting expressions to delegates is a good one, and with these changes proposed here it removes a lot of the 'gotchas' that come with implicit conversions. (uint --> int --> uint, and long --> int --> short are still sore points, BTW). I also assume that the mutability of lazy parameters is identical to the 'in' parameter storage class. That is, any changes to the actual value passed to the function are never passed back to the caller, but that doesn't stop one modifying data passed as references. import std.stdio; void foo(lazy char[] x) { x[0..2] = x[1..2] ~ x[0..1]; x ~= "k"; writefln("%s", x); // --> "back"; } void main() { char[] d = "abc"; foo( d ); writefln("%s", d); // --> "bac"; } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 24/08/2006 4:45:03 PM
Aug 24 2006
prev sibling next sibling parent reply Andy Knowles <andy.knowles gmail.com> writes:
Walter Bright wrote:
 Ok, I've thought about it a bit:
 
     void foo(int x);    // same as before 0.165
     void foo(int delegate() x)    // same as before 0.165
 
 and now:
 
     void foo(lazy int x);
 
 In other words, 'lazy' is now a parameter storage class. This means that:
 
     void foo(int x);
     void foo(lazy int x);
 
 cannot be distinguished based on overloading, but:
 
     void foo(lazy int x);
     void foo(int delegate() x);
 
 can be. The implicit conversion of a value to a delegate returning that 
 value would be removed. The conversion happens always (not implicitly) 
 if the parameter storage class is 'lazy'.

I think that is definitely a step in the right direction, and I think it will make people a lot more comfortable. Some questions: 1) While in void foo(lazy int x) will x be evaluated using x() or just x? Either one could lead to confusion. 2) What are your thoughts on allowing {2*x} as a shortcut for { return 2*x; }? This would only apply to delegates of course, but may still be useful in places. 3) Any thoughts on a shortcut syntax for arguments to delegates? It would be nice to be able to write: int[] map(int[] arr, int delegate(int) func); int[] b = map(a, (x){ 2*x }); or something similar. At the moment we must write either: int[] map(int[] arr, int delegate(int) func); int[] b = map(a, (int x){ return 2*x; }); or: int[] map(int[] arr, out int arg, lazy int func); int x; int[] b = map(a, x, 2*x); Andy
Aug 24 2006
parent reply BCS <BCS pathlink.com> writes:
Andy Knowles wrote:
 Walter Bright wrote:
 
 Ok, I've thought about it a bit:

     void foo(int x);    // same as before 0.165
     void foo(int delegate() x)    // same as before 0.165

 and now:

     void foo(lazy int x);

 In other words, 'lazy' is now a parameter storage class. This means that:

     void foo(int x);
     void foo(lazy int x);

 cannot be distinguished based on overloading, but:

     void foo(lazy int x);
     void foo(int delegate() x);

 can be. The implicit conversion of a value to a delegate returning 
 that value would be removed. The conversion happens always (not 
 implicitly) if the parameter storage class is 'lazy'.


I like that a lot better.
 I think that is definitely a step in the right direction, and I think it 
 will make people a lot more comfortable.

(I'm one of the above mentioned people)
 
 Some questions:
 
 1) While in void foo(lazy int x) will x be evaluated using x() or just 
 x?  Either one could lead to confusion.
 

I'd go for "x()", because 1> it more closely reflects what is actually happening. 2> it allows x to be used to refer to the delegate 3> it is semantically different than a value parameter. This will force you to look at each use while converting a function to lazy use. This is coming from the "when its easy, broken code shouldn't compile" school of thought. OTOH pros for the "x" version 1> the compiler could handle the code to detect the first usage and evaluate it once and use the evaluated version thereafter. This would automate the generation and optimization of a lot of "hard to follow code". However that would be to much to trust the compiler in if you ask me. But it would make for some neat code. void foo(Person[] people, lazy char[] here) { foreach(man;people) if(man.IsHere) writef(man.name ~" is at "~here~\n); } becomes void foo(Person[] people, lazy char[] here) { int __j; foreach(__i, man;people) if(man.IsHere) { __j = __i; goto __eval; } return; __eval: char[] __here = EVAL(here); // sudo code writef(people[__j].name ~" is at "~__here~\n); foreach(man;people[__j+1..$) if(man.IsHere) writef(man.name ~" is at "~__here~\n); } Vary tight code. Now, try writhing that by hand with three lazy argument and 6 places each that they could get evaluated for the first time. That would be a cake walk for a code generator and a nightmare for a programmer.
Aug 24 2006
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
BCS wrote:
 Andy Knowles wrote:
 Walter Bright wrote:

 Ok, I've thought about it a bit:

     void foo(int x);    // same as before 0.165
     void foo(int delegate() x)    // same as before 0.165

 and now:

     void foo(lazy int x);

 In other words, 'lazy' is now a parameter storage class. This means 
 that:

     void foo(int x);
     void foo(lazy int x);

 cannot be distinguished based on overloading, but:

     void foo(lazy int x);
     void foo(int delegate() x);

 can be. The implicit conversion of a value to a delegate returning 
 that value would be removed. The conversion happens always (not 
 implicitly) if the parameter storage class is 'lazy'.


I like that a lot better.
 I think that is definitely a step in the right direction, and I think 
 it will make people a lot more comfortable.

(I'm one of the above mentioned people)
 Some questions:

 1) While in void foo(lazy int x) will x be evaluated using x() or just 
 x?  Either one could lead to confusion.

I'd go for "x()", because 1> it more closely reflects what is actually happening. 2> it allows x to be used to refer to the delegate

Indeed, "x()" is a better usage, however, if x is a delegate, then the "x" usage will still be allowed, due to the implicit call syntax (aka property syntax).
Aug 24 2006
parent reply BCS <BCS pathlink.com> writes:
Bruno Medeiros wrote:
 BCS wrote:
 
 Andy Knowles wrote:
 1) While in void foo(lazy int x) will x be evaluated using x() or 
 just x?  Either one could lead to confusion.

I'd go for "x()", because 1> it more closely reflects what is actually happening. 2> it allows x to be used to refer to the delegate

Indeed, "x()" is a better usage, however, if x is a delegate, then the "x" usage will still be allowed, due to the implicit call syntax (aka property syntax).

Delegates can't be used with implicit call syntax. You get a "can't convert T delegate() to T" error. void main() { int dg() { return 1; } int i = dg; int delegate() t = &dg; i = t; } d.d(7): cannot implicitly convert expression (t) of type int delegate() to int
Aug 24 2006
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
BCS wrote:
 Bruno Medeiros wrote:
 BCS wrote:

 Andy Knowles wrote:
 1) While in void foo(lazy int x) will x be evaluated using x() or 
 just x?  Either one could lead to confusion.

I'd go for "x()", because 1> it more closely reflects what is actually happening. 2> it allows x to be used to refer to the delegate

Indeed, "x()" is a better usage, however, if x is a delegate, then the "x" usage will still be allowed, due to the implicit call syntax (aka property syntax).

Delegates can't be used with implicit call syntax. You get a "can't convert T delegate() to T" error. void main() { int dg() { return 1; } int i = dg; int delegate() t = &dg; i = t; } d.d(7): cannot implicitly convert expression (t) of type int delegate() to int

Hum, you're right. I was quite under the impression of the otherwise, I wonder where I got that from. :7 -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 25 2006
prev sibling parent Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Ok, I've thought about it a bit:
 
     void foo(int x);    // same as before 0.165
     void foo(int delegate() x)    // same as before 0.165
 
 and now:
 
     void foo(lazy int x);
 
 In other words, 'lazy' is now a parameter storage class. This means that:
 
     void foo(int x);
     void foo(lazy int x);
 
 cannot be distinguished based on overloading, but:
 
     void foo(lazy int x);
     void foo(int delegate() x);
 
 can be. The implicit conversion of a value to a delegate returning that 
 value would be removed. The conversion happens always (not implicitly) 
 if the parameter storage class is 'lazy'.

Fantastic! This will even allow lazy values to be pre-constructed, which is a nice perk. Sean
Aug 24 2006
prev sibling next sibling parent Carlos Santander <csantander619 gmail.com> writes:
Tom S escribió:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 .... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.
 
 
 -- 
 Tomasz Stachowiak

I think some things are over my head, but I have the feeling this makes sense. Besides, everyone else has agreed :D -- Carlos Santander Bernal
Aug 22 2006
prev sibling next sibling parent Derek Parnell <derek nomail.afraid.org> writes:
On Tue, 22 Aug 2006 18:39:57 +0100, Tom S wrote:

 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.

Amen to that!
 Adopting delegate function parameters for lazy expressions is a mistake. 

Well ... its the implicit conversion of expressions to delegates that concerns me. I can see that most of the time it should be harmless, but it still opens the window of opportunity for seriously long debugging sessions.
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }

or ... void foo( delegate int () foo) {} void foo( expression int () foo) {}
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions

A big plus, in the manner of "least surprise".
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.

This also enhances understanding when reading someone else's code. It allows better understanding of the coder's intentions.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques

Hmmm ... interesting. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 23/08/2006 2:30:50 PM
Aug 22 2006
prev sibling parent reply Andy Knowles <andy.knowles gmail.com> writes:
Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.
 
 Adopting delegate function parameters for lazy expressions is a mistake. 
 At least consider adding a new keyword, e.g. 'lazy' or 'expression', 
 please. The syntax could look like:
 
 void foo(int expression() foo) {
 }
 
 or
 
 void foo(lazy int foo) {
 }
 
 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.
 
 
 The above approach has three significant advantages over the current 
 state of things:
 
 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques
 
 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...
 
 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
 
 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on their 
 internal structure, generate highly optimized code. At least that's what 
 game developers use to make their linear algebra libraries as fast as 
 possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.
 
 The 'expression' or 'lazy' types might work in a similar way. They would 
 allow the programmer to inspect parse trees at compile-time and generate 
 specially tailored code.
 
 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the delegate 
 might be inlined, which currently doesn't happen at all.
 
 
 -- 
 Tomasz Stachowiak

I agree, there should be some difference between a delegate and a lazy expression. Besides fixing an overload ambiguity, this would leave the door open to extensions to lazy expressions that won't necessarily make sense for delegates. The reason people tout LISP (not that I have used it more than I absolutely had to) as having power that other languages do not is not the lazy evaluation of expressions but the ability to decompose, examine and alter the expression tree using the same code as for any other LISP data structure (since they're all the same anyway). The reason people think Expression templates in C++ are so impressive is not lazy evaluation - it's compile-time inline insertion of user code into library functions. So when I write math::integrate(x*x + 2*x + 1, x, 0, 3) I know that my quadratic expression is inserted directly into the inner-most loop of the integral function and incurs no overhead per iteration. One of C# 3.0's big new features is Expression templates, which is much more than syntactic sugar for anonymous delegates (which it already has and is improving). The point is that an expression template is not compiled into code but into a data structure that can be explored at run-time. Thus one can write OO-style C# code that gets turned directly into an efficient SQL query. Having said all that, the syntax does open some functional-programming doors to D. I knocked this up while experimenting. Note the need to pass in the expression argument as a separate parameter - something a => a * 2 could fix (or some other syntax). http://www.members.iinet.net.au/~melkesjokolade/functional.d Andy
Aug 23 2006
next sibling parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Andy Knowles wrote:

 http://www.members.iinet.net.au/~melkesjokolade/functional.d
 
 Andy

I have to ask ... why is your username (melkesjokolade) on this site the norwegian word for milk chocolate? :D -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Aug 23 2006
parent Andy Knowles <andy.knowles gmail.com> writes:
Lars Ivar Igesund wrote:
 Andy Knowles wrote:
 
 http://www.members.iinet.net.au/~melkesjokolade/functional.d

 Andy

I have to ask ... why is your username (melkesjokolade) on this site the norwegian word for milk chocolate? :D

lol :P my gf is norwegian and we needed a username that was valid for us both and guaranteed not to be taken. melkesjokolade came to mind, and we both thought it would be suitably confusing to anyone who noticed :D Andy
Aug 23 2006
prev sibling parent reply =?ISO-8859-1?Q?=22R=E9my_J=2E_A=2E_Mou=EBza=22?= writes:
Andy, is there a particular reason why you don't use the array 
concatenation operator in your select ( and others ) function(s) ?
Like this one :
# ArrayT [] select ( ArrayT ) ( ArrayT [] array, bool delegate ( ArrayT 
) predicate )
# {
#     ArrayT [] result ;
#
#     foreach ( item ; array )
#         if ( predicate ( item ))
#             result ~= item ;
#
#     return result ;
# }


Andy Knowles a écrit :
 Tom S wrote:
 Walter, if you *really* want to keep lazy expression evaluation in its 
 current form, then please *at least* don't force everyone to use it.

 Adopting delegate function parameters for lazy expressions is a 
 mistake. At least consider adding a new keyword, e.g. 'lazy' or 
 'expression', please. The syntax could look like:

 void foo(int expression() foo) {
 }

 or

 void foo(lazy int foo) {
 }

 or just some other variant. Delegates would then be delegates and 
 wouldn't accept lazy expressions. But lazy expressions could accept 
 delegates.


 The above approach has three significant advantages over the current 
 state of things:

 1. When the coder doesn't intend to use lazy expression evaluation, 
 his/her functions that take delegates as params won't silently accept 
 lazily evaluated expressions
 2. Less existing code will be broken or the changes will be easier to 
 fix - renaming the keyword to some other variable name compared to the 
 nontrivial fixes that have to be done now.
 3. In future, the 'expression' or 'lazy' types might provide meta-data 
 allowing advanced metaprogramming techniques

 The third point is important because lazy expressions in their current 
 form simply can't replace expression templates. Even by looking at the 
 first resource available on google...

 http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html

 ... it's clear that one of the most important points behind expression 
 templates is the ability to deconstruct expressions and basing on 
 their internal structure, generate highly optimized code. At least 
 that's what game developers use to make their linear algebra libraries 
 as fast as possible.
 This is only possible by knowing the structure of the expression and 
 applying localized and specialized optimizations.

 The 'expression' or 'lazy' types might work in a similar way. They 
 would allow the programmer to inspect parse trees at compile-time and 
 generate specially tailored code.

 Currently the only performance advantage that can be accomplished with 
 lazy expression evaluation is when the compiler determines the 
 delegate might be inlined, which currently doesn't happen at all.


 -- 
 Tomasz Stachowiak

I agree, there should be some difference between a delegate and a lazy expression. Besides fixing an overload ambiguity, this would leave the door open to extensions to lazy expressions that won't necessarily make sense for delegates. The reason people tout LISP (not that I have used it more than I absolutely had to) as having power that other languages do not is not the lazy evaluation of expressions but the ability to decompose, examine and alter the expression tree using the same code as for any other LISP data structure (since they're all the same anyway). The reason people think Expression templates in C++ are so impressive is not lazy evaluation - it's compile-time inline insertion of user code into library functions. So when I write math::integrate(x*x + 2*x + 1, x, 0, 3) I know that my quadratic expression is inserted directly into the inner-most loop of the integral function and incurs no overhead per iteration. One of C# 3.0's big new features is Expression templates, which is much more than syntactic sugar for anonymous delegates (which it already has and is improving). The point is that an expression template is not compiled into code but into a data structure that can be explored at run-time. Thus one can write OO-style C# code that gets turned directly into an efficient SQL query. Having said all that, the syntax does open some functional-programming doors to D. I knocked this up while experimenting. Note the need to pass in the expression argument as a separate parameter - something a => a * 2 could fix (or some other syntax). http://www.members.iinet.net.au/~melkesjokolade/functional.d Andy

Aug 23 2006
parent Andy Knowles <andy.knowles gmail.com> writes:
Rémy J. A. Mouëza wrote:
 Andy, is there a particular reason why you don't use the array 
 concatenation operator in your select ( and others ) function(s) ?
 Like this one :
 # ArrayT [] select ( ArrayT ) ( ArrayT [] array, bool delegate ( ArrayT 
 ) predicate )
 # {
 #     ArrayT [] result ;
 #
 #     foreach ( item ; array )
 #         if ( predicate ( item ))
 #             result ~= item ;
 #
 #     return result ;
 # }

:) An excellent question! Frankly, I forgot about it. While I pay close attention to D's development and these news groups, I rarely get a chance to write D code. It *might* be better to (over)allocate only once (as I do) rather than realloc the array who knows how many times. Depends on usage really - wasted space on one hand, wasted cycles on the other. For the range function, it depends how Walter's realloc code works. I know it allocates more than it needs to, but I don't know what factor or constant it increase the size by. Depends again on usage which is the better option. I should probably just use the concat operator and leave the performance tuning for when it is really needed. And of course, you can't use a predicate with an argument if you want to use lazy evaluation, even though it makes the code more logical. Andy
Aug 23 2006