www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Lazy evaluation of function arguments in D

reply Walter Bright <newshound2 digitalmars.com> writes:
http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/
May 19 2012
next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/c4pwvyp

+1 ^
May 19 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/21/2012 11:07 AM, renoX wrote:
 On Sunday, 20 May 2012 at 00:26:14 UTC, Mehrdad wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/c4pwvyp


 +1 ^

+1 too: 'f(x++)' what's the value of x after executing this function call? If f is a function with a normal argument, the new value is x + 1, if f is a function with a lazy argument, the new value can be anything (depends on how many time the expression is evaluated).

int x; void f(int){x=anything;} void main(){ f(x++); }
 So the lazy keyword hurts maintainability:
 you need an IDE which color differently the callsite to be usable, really
ugly..

Have you actually encountered this problem in practice?
 How about improving 'f({ return x ++ })' to either f({^x++})' (^ is
 return in Smalltalk) or 'f({x++})'?

f(()=>x++) is already short enough.
May 21 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/21/12 8:48 AM, jerro wrote:
 The whole point of it is to have nice syntax at the call site.
 Delegate syntax is, however, conscise enough already.

I agree with that completely. I have also never used lazy, nor have I seen it used in a public API.

enforce() uses lazy. Andrei
May 21 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Sunday, 20 May 2012 at 00:26:14 UTC, Mehrdad wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/c4pwvyp

 +1 ^

Yeah, I'd like both "lazy" and "ref" to be forced to be used 
from the call site >and not just in the declaration. I don't use 
lazy that often but I would use >'ref' more often if I could 
tell from the call site that my arguments might be >modified.

programs more robust and easier to understand. And it is clearly much easier, than, for example, would be repeating pure, nothrow, safe, or even contracts at each call (any of these would not make sence for me because they are enforced by the compiler). Sorry if the above is confusing, I have difficulties to explain it more clearly.
May 19 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Saturday, 19 May 2012 at 23:03:50 UTC, Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

Lazy evaluation has been discussed previously, but this topic is important and the problems have not been solved yet. Functional languages, like Haskel, Scala or F#, have the semantics of lazy evaluation which is to evaluate things at most once. Evaluating many times is accomplished via a function or delegate. Thus lazy in D is (IMO): * confusing, because it doesn't take into account lazy semantics * close to useless, because functions or delegates could do the same job and not confuse the users * somehow hiding the need to have the functionality of evaluating an expression at most once. For example, I need this to work with immutable data, but it is not possible conceptually at this moment (clearly, evaluating and storing the result would mutate the data). I understand that designing this would mean there is the need for synchronization for immutable data. But at least this functionality could exist for pure functions.
May 19 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 20/05/2012 01:03, Walter Bright a crit :
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

This feature break pure/ safe/nothrow . I don't think this is a good idea to promote it right now, as it WILL have to change.
May 20 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/20/2012 04:09 PM, deadalnix wrote:
 Le 20/05/2012 01:03, Walter Bright a crit :
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

This feature break pure/ safe/nothrow .

It does not break them. lazy currently makes it impossible to have some guarantees that might be desirable to have inside the function with the lazy parameter, but the call site has all the information needed in order to establish them again.
 I don't think this is a good idea to promote it right now, as it WILL
 have to change.

May 20 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 20/05/2012 16:17, Timon Gehr a crit :
 On 05/20/2012 04:09 PM, deadalnix wrote:
 Le 20/05/2012 01:03, Walter Bright a crit :
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

This feature break pure/ safe/nothrow .

It does not break them. lazy currently makes it impossible to have some guarantees that might be desirable to have inside the function with the lazy parameter, but the call site has all the information needed in order to establish them again.

How would you create a nothrow function with a lazy parameter ? This will depend both on the callee and the caller, for instance : nothrow void foo(lazy int i) { try { // Do something with i. } catch(Exception e) {} } This function is nothrow even if the parameter isn't. Without the try catch, the function can be nothrow depending on what is passed as argument. The article state that the whole point is : The only trouble is that few are going to want to wrap expressions with { return exp; }. If so, this isn't complicated, just do some rewrite magic on the expression if it is given and expression where a delegate is expected. lazy prevent expressing the attribute needed. And extending lazy would ends up to the point where you remove the delegate keyword and replace it with lazy.
May 20 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 20/05/2012 17:59, David Nadlinger a écrit :
 On Sunday, 20 May 2012 at 15:41:05 UTC, deadalnix wrote:
 If so, this isn't complicated, just do some rewrite magic on the
 expression if it is given and expression where a delegate is expected.

Lazy parameters once used to work like this (back in the D1 times, before there even was a »lazy« storage class), but not everybody was happy with it – among other discussions, you should be able to find a thread named something along the lines of »But I don't want my delegates to be lazy« in the NG archives. David

Thank for the information. I think this thread have some good point but : 1/ Nobody is even considering pure/nothrow/ safe . 2/ Many problems are not solved with lazy. lazy in itself isn't bad, but it don't play well with other features of the language. A language that have many feature that don't integrate nicely with one another already exists. It is called C++, it is a reason that lead to D. We can do the same mistake again and again, but it seems that E already exists.
May 20 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 20 May 2012 at 15:41:05 UTC, deadalnix wrote:
 If so, this isn't complicated, just do some rewrite magic on 
 the expression if it is given and expression where a delegate 
 is expected.

Lazy parameters once used to work like this (back in the D1 times, before there even was a »lazy« storage class), but not everybody was happy with it – among other discussions, you should be able to find a thread named something along the lines of »But I don't want my delegates to be lazy« in the NG archives. David
May 20 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Sunday, 20 May 2012 at 14:02:52 UTC, deadalnix wrote:
 Le 20/05/2012 01:03, Walter Bright a écrit :
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

This feature break pure/ safe/nothrow . I don't think this is a good idea to promote it right now, as it WILL have to change.

What I would like is to have community agree on the topic, not necessarily change anything. Agreement would mean that the issues are either fixed, or some workaround proposed, or it is stated that this is impossible to have due to some other design decision, or not important for some reason. For me the most important would be to understand how to implement functionality "evaluate expression at most once and store result for subsequent calls", even if this would be restricted to pure nothrow. And if we claim that immutabilily is the advantage of D, IMO, we need to be able to have lazy evaluation possible for immutable data structures. (AFAIK, Haskell has immutability and lazy evaluation by default.) But I don't know how to avoid synchronization for both evaluating and storing the result.
May 20 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Sunday, 20 May 2012 at 18:59:22 UTC, deadalnix wrote:
 Le 20/05/2012 17:59, David Nadlinger a écrit :
 On Sunday, 20 May 2012 at 15:41:05 UTC, deadalnix wrote:
 If so, this isn't complicated, just do some rewrite magic on 
 the
 expression if it is given and expression where a delegate is 
 expected.

Lazy parameters once used to work like this (back in the D1 times, before there even was a »lazy« storage class), but not everybody was happy with it – among other discussions, you should be able to find a thread named something along the lines of »But I don't want my delegates to be lazy« in the NG archives. David

Thank for the information. I think this thread have some good point but : 1/ Nobody is even considering pure/nothrow/ safe . 2/ Many problems are not solved with lazy. lazy in itself isn't bad, but it don't play well with other features of the language. A language that have many feature that don't integrate nicely with one another already exists. It is called C++, it is a reason that lead to D. We can do the same mistake again and again, but it seems that E already exists.

I rather agree. However, if the language doesn't provide some feature it doesn't mean there is no way to accomplish the task. I would be interested to know how to do it.
May 20 2012
prev sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Sunday, 20 May 2012 at 18:59:22 UTC, deadalnix wrote:
 Le 20/05/2012 17:59, David Nadlinger a écrit :
 On Sunday, 20 May 2012 at 15:41:05 UTC, deadalnix wrote:
 If so, this isn't complicated, just do some rewrite magic on 
 the
 expression if it is given and expression where a delegate is 
 expected.

Lazy parameters once used to work like this (back in the D1 times, before there even was a »lazy« storage class), but not everybody was happy with it – among other discussions, you should be able to find a thread named something along the lines of »But I don't want my delegates to be lazy« in the NG archives. David

Thank for the information. I think this thread have some good point but : 1/ Nobody is even considering pure/nothrow/ safe . 2/ Many problems are not solved with lazy. lazy in itself isn't bad, but it don't play well with other features of the language. A language that have many feature that don't integrate nicely with one another already exists. It is called C++, it is a reason that lead to D. We can do the same mistake again and again, but it seems that E already exists.

I rather agree. However, if the language doesn't provide some feature it doesn't mean there is no way to accomplish the task. I would be interested to know how to do it.
May 20 2012
prev sibling next sibling parent "F i L" <witte2008 gmail.com> writes:
On Saturday, 19 May 2012 at 23:03:50 UTC, Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

Didn't know this was new. Stumbled upon it a day-or-so ago and (while searching for something else) and thought it was a cool little "hidden gem" of dlang.org Guess I just got and early showing ;)
May 20 2012
prev sibling next sibling parent "Roman D. Boiko" <rb d-coding.com> writes:
On Sunday, 20 May 2012 at 18:22:16 UTC, F i L wrote:
 On Saturday, 19 May 2012 at 23:03:50 UTC, Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/

Didn't know this was new. Stumbled upon it a day-or-so ago and (while searching for something else) and thought it was a cool little "hidden gem" of dlang.org Guess I just got and early showing ;)

I saw it earlier, too.
May 20 2012
prev sibling next sibling parent "renoX" <renozyx gmail.com> writes:
On Sunday, 20 May 2012 at 00:26:14 UTC, Mehrdad wrote:
 http://www.reddit.com/r/programming/comments/tui75/lazy_evaluation_of_function_arguments_in_d/c4pwvyp

 +1 ^

+1 too: 'f(x++)' what's the value of x after executing this function call? If f is a function with a normal argument, the new value is x + 1, if f is a function with a lazy argument, the new value can be anything (depends on how many time the expression is evaluated). So the lazy keyword hurts maintainability: you need an IDE which color differently the callsite to be usable, really ugly.. How about improving 'f({ return x ++ })' to either f({^x++})' (^ is return in Smalltalk) or 'f({x++})'?
May 21 2012
prev sibling next sibling parent "Matej Nanut" <matejnanut gmail.com> writes:
I either think lazy should remain as it is, or that delegate 
syntax should be explicit.  But if delegate syntax is explicit, 
»lazy« isn't needed anymore.  The whole point of it is to have 
nice syntax at the call site.  Delegate syntax is, however, 
conscise enough already.

Bugs due to lazy might happen, although its use is extremely rare 
anyway.

I'm not sure what to say about "i" versus "i()" when using lazy 
parameter "i" in a function.  I'm leaning towards explicit "i()" 
(DMD allows both on my machine), because just using "i" is kind 
of misleading.  EXCEPT if using plain "i" would only evaluate the 
expression once, and "i()" for every time we use it.  (And only 
one notation would be permitted per function).

(This obviously doesn't change any confusion from the call site.)

What do you think?
May 21 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
 The whole point of it is to have nice syntax at the call site.  
 Delegate syntax is, however, conscise enough already.

I agree with that completely. I have also never used lazy, nor have I seen it used in a public API.
May 21 2012
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.net> writes:
On Monday, 21 May 2012 at 14:26:31 UTC, Andrei Alexandrescu wrote:
 On 5/21/12 8:48 AM, jerro wrote:
 The whole point of it is to have nice syntax at the call site.
 Delegate syntax is, however, conscise enough already.

I agree with that completely. I have also never used lazy, nor have I seen it used in a public API.

enforce() uses lazy.

So will absolutePath() and relativePath(), starting next release: https://github.com/D-Programming-Language/phobos/pull/522 -Lars
May 21 2012
prev sibling parent "renoX" <renozyx gmail.com> writes:
On Monday, 21 May 2012 at 09:35:30 UTC, Timon Gehr wrote:
[cut]
 int x;

 void f(int){x=anything;}

 void main(){ f(x++); }

Yes, and that's why you're supposed to *avoid* the use of global variables as much as possible.. Thanks for showing that "lazy" has the same issue as global variables.. [cut]
 f(()=>x++) is already short enough.

I would prefer f({x++}) instead but that may be bikeshedding.. renoX
May 22 2012