digitalmars.D.learn - How does laziness and UFCS interact?
- Logan Capaldo (18/18) Mar 09 2015 I just became aware of
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/21) Mar 09 2015 You are right. I had the same observation at minute 11:27 below, where I...
- Logan Capaldo (11/15) Mar 10 2015 Sorry, which is right? I know ifThrown is lazy, I'm curious about
- John Colvin (3/21) Mar 10 2015 a.b().c().assumeWontThrow is rewritten as
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (35/59) Mar 10 2015 You are right that it is confusing. :)
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (9/13) Mar 10 2015 "lazy" aka "named parameters" semantically works just like macros
I just became aware of but it seems non-obvious to me how lazy + UFCS should work in general. consider void lazily(T)(lazy T expression) { expression(); } It's clear when saying lazily(a.b().c()); that the whole of "a.b().c()" is going to be evaluated lazily. With UFCS though, I'm more unsure: is a.b().c().lazily() -> lazily(a.b().c()) or is it more akin to auto tmp = a.b(); lazily(tmp.c()); If the later is it possible to force the former while still using UFCS, ie is (a.b().c()).lazily() different than a.b().c().lazily()?
Mar 09 2015
On 03/09/2015 03:03 PM, Logan Capaldo wrote:I just became aware of seems non-obvious to me how lazy + UFCS should work in general. consider void lazily(T)(lazy T expression) { expression(); } It's clear when saying lazily(a.b().c()); that the whole of "a.b().c()" is going to be evaluated lazily. With UFCS though, I'm more unsure: is a.b().c().lazily() -> lazily(a.b().c()) or is it more akin to auto tmp = a.b(); lazily(tmp.c()); If the later is it possible to force the former while still using UFCS, ie is (a.b().c()).lazily() different than a.b().c().lazily()?You are right. I had the same observation at minute 11:27 below, where I warn against UFCS with assumeWontThrow: http://www.youtube.com/watch?feature=player_detailpage&v=oF8K4-bieaw#t=687 Ali
Mar 09 2015
On Monday, 9 March 2015 at 22:15:43 UTC, Ali Çehreli wrote:You are right. I had the same observation at minute 11:27 below, where I warn against UFCS with assumeWontThrow: http://www.youtube.com/watch?feature=player_detailpage&v=oF8K4-bieaw#t=687 AliSorry, which is right? I know ifThrown is lazy, I'm curious about the "amount" of the expression that is evaluated lazily. a.b().c().assumeWontThrow vs. a.b().c().assumeWontThrow ^--+----^ ^-^ | | +- lazy? +- lazy? The video seems to say "don't use lazy functions with UFCS because you might think the lazy part gets evaluated first, when it does not". Seems reasonable, although I don't know it's any different than assumeWontThrow(f()).
Mar 10 2015
On Tuesday, 10 March 2015 at 14:41:00 UTC, Logan Capaldo wrote:On Monday, 9 March 2015 at 22:15:43 UTC, Ali Çehreli wrote:a.b().c().assumeWontThrow is rewritten as assumeWontThrow(a.b().c()) and therefore the whole chain is lazy.You are right. I had the same observation at minute 11:27 below, where I warn against UFCS with assumeWontThrow: http://www.youtube.com/watch?feature=player_detailpage&v=oF8K4-bieaw#t=687 AliSorry, which is right? I know ifThrown is lazy, I'm curious about the "amount" of the expression that is evaluated lazily. a.b().c().assumeWontThrow vs. a.b().c().assumeWontThrow ^--+----^ ^-^ | | +- lazy? +- lazy? The video seems to say "don't use lazy functions with UFCS because you might think the lazy part gets evaluated first, when it does not". Seems reasonable, although I don't know it's any different than assumeWontThrow(f()).
Mar 10 2015
On 03/10/2015 08:00 AM, John Colvin wrote:On Tuesday, 10 March 2015 at 14:41:00 UTC, Logan Capaldo wrote:http://www.youtube.com/watch?feature=player_detailpage&v=oF8K4-bieaw#t=687On Monday, 9 March 2015 at 22:15:43 UTC, Ali Çehreli wrote:You are right. I had the same observation at minute 11:27 below, where I warn against UFCS with assumeWontThrow:You are right that it is confusing. :)AliSorry, which is right?As John Colvin said, the first one is right. A test: import std.stdio; struct S {} S a(S s) { writeln("entered a"); return s; } S b(S s) { writeln("entered b"); return s; } void lazily(T)(lazy T expression) { writeln("entered lazily"); expression(); } void main() { S().a.b.lazily; } Outputs entered lazily entered a entered bI know ifThrown is lazy, I'm curious about the "amount" of the expression that is evaluated lazily. a.b().c().assumeWontThrow vs. a.b().c().assumeWontThrow ^--+----^ ^-^ | | +- lazy? +- lazy?You are right again. :) However, putting the lazy-taking function "outside" the whole expression makes it visible right away, making easy for me to realize that the execution order may be different from common chains. AliThe video seems to say "don't use lazy functions with UFCS because you might think the lazy part gets evaluated first, when it does not". Seems reasonable, although I don't know it's any different than assumeWontThrow(f()).
Mar 10 2015
On Tuesday, 10 March 2015 at 17:42:37 UTC, Ali Çehreli wrote:You are right again. :) However, putting the lazy-taking function "outside" the whole expression makes it visible right away, making easy for me to realize that the execution order may be different from common chains."lazy" aka "named parameters" semantically works just like macros using textual substitution. Just imagine that it is inlined in situ and it becomes clear what is happening. I believe it was the common parameter transfer mode in Algol, but programmers found it terribly confusing, so just about all languages that followed have avoided it. So if anyone gets confused, then find some comfort in knowing that people found it confusing 50 years ago too. :^)
Mar 10 2015