www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Discussion Thread: DIP 1033--Implicit Conversion of Expressions to

reply Mike Parker <aldacron gmail.com> writes:
This is the discussion thread for the Final Review of DIP 1033, 
"Implicit Conversion of Expressions to Delegates":

https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md

The review period will end at 11:59 PM ET on December 4, or when 
I make a post declaring it complete. Discussion in this thread 
may continue beyond that point.

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits, etc.

However, if you have any specific feedback on how to improve the 
proposal itself, then please post it in the feedback thread. The 
feedback thread will be the source for the review summary I write 
at the end of this review round. I will post a link to that 
thread immediately following this post. Just be sure to read and 
understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

And my blog post on the difference between the Discussion and 
Feedback threads:

https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

Please stay on topic here. I will delete posts that are 
completely off-topic.
Nov 19 2020
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Friday, 20 November 2020 at 07:29:21 UTC, Mike Parker wrote:

 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post.
The Feedback Thread is here: https://forum.dlang.org/post/tvwikrkcqqyeyprfdokg forum.dlang.org
Nov 19 2020
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Fri, Nov 20, 2020 at 6:06 PM Manu <turkeyman gmail.com> wrote:

 On Fri, Nov 20, 2020 at 5:30 PM Mike Parker via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 This is the discussion thread for the Final Review of DIP 1033,
 "Implicit Conversion of Expressions to Delegates":


 https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md

 The review period will end at 11:59 PM ET on December 4, or when
 I make a post declaring it complete. Discussion in this thread
 may continue beyond that point.

 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve the
 proposal itself, then please post it in the feedback thread. The
 feedback thread will be the source for the review summary I write
 at the end of this review round. I will post a link to that
 thread immediately following this post. Just be sure to read and
 understand the Reviewer Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are
 completely off-topic.
So, the thing that makes me nervous about this DIP, is that it may substantially proliferate allocated closures. I would want to have high confidence that people exclusively use `scope` delegates, such that the closure can (will?/must?) be stack allocated. In my experience, in the rare instance that I want to use a lazy parameter in the sorts of ways that might be affected by this DIP, it's usually in support of a fairly small optimisation, or a modest convenience in the API. Relative to that optimisation, if there's a risk of introducing a closure allocation, that would vastly out-weight the advantage by my judgement, and it's very easy for such allocations to go unnoticed. It's completely invisible. I would appeal that this DIP be changed such that auto-delegates must be `scope`, and non-scope delegates should require the user to specify a non-scope delegate argument using typical delegate syntax, so that you can plainly see it. Without requiring `scope` delegates, the risk of hidden allocations is extremely high, and it's almost certainly NOT what anybody would ever want from a lazy argument, which is virtually always an INPUT argument, and shouldn't be retained past the life of the call.
Another question that comes to mind, where the dip shows: int delegate() dg = () { return 3; }; becomes: int delegate() dg = () => 3; become simply: int delegate() dg = 3; <https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md#prior-work> This isn't an example of passing a lazy argument to a function that receives a delegate; this demonstrates initialising a delegate variable declaration. That seems off-topic to me, but it raises the question, does this now work for delegates that receive parameters: int delegate(int x) dg = x + 10; ?? Are the parameters in scope for the expression to the right of the `=`? This question doesn't really apply to the DIP, because a lazy argument delegate must necessarily have zero parameters... but the example shown here in the DIP raises questions along that associated path.
Nov 20 2020
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2020 12:18 AM, Manu wrote:
 [...]
I'd appreciate it if you would delete irrelevant quoting en masse of the entire message you're replying to, when it has nothing to do with your message. It's just noisy. Thanks! Or you could do like I do, and just replace it with [...]
Nov 22 2020
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2020 12:18 AM, Manu wrote:
 Another question that comes to mind, where the dip shows:
 
 int  delegate() dg = () {return  3; };
 
 becomes:
 
 int  delegate() dg = ()=>  3;
 
 become simply:
 
 int  delegate() dg =3;
 
 
     <https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md#prior-work>
 
 This isn't an example of passing a lazy argument to a function that receives a 
 delegate; this demonstrates initialising a delegate variable declaration. That 
 seems off-topic to me, but it raises the question, does this now work for 
 delegates that receive parameters:
 
      int delegate(int x) dg = x + 10;
 
 ??
 Are the parameters in scope for the expression to the right of the `=`?
No. Initializers are semantically analyzed before the initialized, hence the parameter x will be unknown. You'll have to declare it as: int delegate(int) dg = (int x) { return x + 10; };
Nov 22 2020
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
On Fri, Nov 20, 2020 at 6:18 PM Manu <turkeyman gmail.com> wrote:

 On Fri, Nov 20, 2020 at 6:06 PM Manu <turkeyman gmail.com> wrote:

 On Fri, Nov 20, 2020 at 5:30 PM Mike Parker via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 This is the discussion thread for the Final Review of DIP 1033,
 "Implicit Conversion of Expressions to Delegates":


 https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md

 The review period will end at 11:59 PM ET on December 4, or when
 I make a post declaring it complete. Discussion in this thread
 may continue beyond that point.

 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve the
 proposal itself, then please post it in the feedback thread. The
 feedback thread will be the source for the review summary I write
 at the end of this review round. I will post a link to that
 thread immediately following this post. Just be sure to read and
 understand the Reviewer Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are
 completely off-topic.
So, the thing that makes me nervous about this DIP, is that it may substantially proliferate allocated closures. I would want to have high confidence that people exclusively use `scope` delegates, such that the closure can (will?/must?) be stack allocated. In my experience, in the rare instance that I want to use a lazy parameter in the sorts of ways that might be affected by this DIP, it's usually in support of a fairly small optimisation, or a modest convenience in the API. Relative to that optimisation, if there's a risk of introducing a closure allocation, that would vastly out-weight the advantage by my judgement, and it's very easy for such allocations to go unnoticed. It's completely invisible. I would appeal that this DIP be changed such that auto-delegates must be `scope`, and non-scope delegates should require the user to specify a non-scope delegate argument using typical delegate syntax, so that you can plainly see it. Without requiring `scope` delegates, the risk of hidden allocations is extremely high, and it's almost certainly NOT what anybody would ever want from a lazy argument, which is virtually always an INPUT argument, and shouldn't be retained past the life of the call.
Another question that comes to mind, where the dip shows: int delegate() dg = () { return 3; }; becomes: int delegate() dg = () => 3; become simply: int delegate() dg = 3; <https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md#prior-work> This isn't an example of passing a lazy argument to a function that receives a delegate; this demonstrates initialising a delegate variable declaration. That seems off-topic to me, but it raises the question, does this now work for delegates that receive parameters: int delegate(int x) dg = x + 10; ?? Are the parameters in scope for the expression to the right of the `=`? This question doesn't really apply to the DIP, because a lazy argument delegate must necessarily have zero parameters... but the example shown here in the DIP raises questions along that associated path.
... I think both of those posts should have been in the feedback thread?
Nov 20 2020
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On Fri, Nov 20, 2020 at 5:30 PM Mike Parker via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 This is the discussion thread for the Final Review of DIP 1033,
 "Implicit Conversion of Expressions to Delegates":


 https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md

 The review period will end at 11:59 PM ET on December 4, or when
 I make a post declaring it complete. Discussion in this thread
 may continue beyond that point.

 Here in the discussion thread, you are free to discuss anything
 and everything related to the DIP. Express your support or
 opposition, debate alternatives, argue the merits, etc.

 However, if you have any specific feedback on how to improve the
 proposal itself, then please post it in the feedback thread. The
 feedback thread will be the source for the review summary I write
 at the end of this review round. I will post a link to that
 thread immediately following this post. Just be sure to read and
 understand the Reviewer Guidelines before posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 And my blog post on the difference between the Discussion and
 Feedback threads:

 https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

 Please stay on topic here. I will delete posts that are
 completely off-topic.
So, the thing that makes me nervous about this DIP, is that it may substantially proliferate allocated closures. I would want to have high confidence that people exclusively use `scope` delegates, such that the closure can (will?/must?) be stack allocated. In my experience, in the rare instance that I want to use a lazy parameter in the sorts of ways that might be affected by this DIP, it's usually in support of a fairly small optimisation, or a modest convenience in the API. Relative to that optimisation, if there's a risk of introducing a closure allocation, that would vastly out-weight the advantage by my judgement, and it's very easy for such allocations to go unnoticed. It's completely invisible. I would appeal that this DIP be changed such that auto-delegates must be `scope`, and non-scope delegates should require the user to specify a non-scope delegate argument using typical delegate syntax, so that you can plainly see it. Without requiring `scope` delegates, the risk of hidden allocations is extremely high, and it's almost certainly NOT what anybody would ever want from a lazy argument, which is virtually always an INPUT argument, and shouldn't be retained past the life of the call.
Nov 20 2020
next sibling parent Sebastiaan Koppe <mail skoppe.eu> writes:
On Friday, 20 November 2020 at 08:06:07 UTC, Manu wrote:
 So, the thing that makes me nervous about this DIP, is that it 
 may
 substantially proliferate allocated closures.
 I would want to have high confidence that people exclusively 
 use `scope`
 delegates, such that the closure can (will?/must?) be stack 
 allocated.
I have similar concerns. At least `lazy` doesn't cause an delegate allocation, even on -O0; be a shame to give that up.
Nov 20 2020
prev sibling next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 20/11/2020 9:06 PM, Manu wrote:
 So, the thing that makes me nervous about this DIP, is that it may 
 substantially proliferate allocated closures.
 I would want to have high confidence that people exclusively use `scope` 
 delegates, such that the closure can (will?/must?) be stack allocated.
One way to do this would be to add a new compiler check: localnogc (can call methods that are not nogc, but cannot do any direct calls to GC like new (apart from exceptions)). It is something that has been on my mind for a while now. But that wouldn't help for forcing the caller You'd still need to use scope on the parameter.
Nov 20 2020
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/20/2020 12:06 AM, Manu wrote:
 So, the thing that makes me nervous about this DIP, is that it may
substantially 
 proliferate allocated closures.
 I would want to have high confidence that people exclusively use `scope` 
 delegates, such that the closure can (will?/must?) be stack allocated.
 
 In my experience, in the rare instance that I want to use a lazy parameter in 
 the sorts of ways that might be affected by this DIP, it's usually in support
of 
 a fairly small optimisation, or a modest convenience in the API.
 Relative to that optimisation, if there's a risk of introducing a closure 
 allocation, that would vastly out-weight the advantage by my judgement, and
it's 
 very easy for such allocations to go unnoticed. It's completely invisible.
 
 I would appeal that this DIP be changed such that auto-delegates must be 
 `scope`, and non-scope delegates should require the user to specify a
non-scope 
 delegate argument using typical delegate syntax, so that you can plainly see
it.
 Without requiring `scope` delegates, the risk of hidden allocations is
extremely 
 high, and it's almost certainly NOT what anybody would ever want from a lazy 
 argument, which is virtually always an INPUT argument, and shouldn't be
retained 
 past the life of the call.
Hmm, this is a good point I never thought of. Well put!
Nov 22 2020
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 22.11.20 10:18, Walter Bright wrote:
 On 11/20/2020 12:06 AM, Manu wrote:
 So, the thing that makes me nervous about this DIP, is that it may 
 substantially proliferate allocated closures.
 I would want to have high confidence that people exclusively use 
 `scope` delegates, such that the closure can (will?/must?) be stack 
 allocated.

 In my experience, in the rare instance that I want to use a lazy 
 parameter in the sorts of ways that might be affected by this DIP, 
 it's usually in support of a fairly small optimisation, or a modest 
 convenience in the API.
 Relative to that optimisation, if there's a risk of introducing a 
 closure allocation, that would vastly out-weight the advantage by my 
 judgement, and it's very easy for such allocations to go unnoticed. 
 It's completely invisible.

 I would appeal that this DIP be changed such that auto-delegates must 
 be `scope`, and non-scope delegates should require the user to specify 
 a non-scope delegate argument using typical delegate syntax, so that 
 you can plainly see it.
 Without requiring `scope` delegates, the risk of hidden allocations is 
 extremely high, and it's almost certainly NOT what anybody would ever 
 want from a lazy argument, which is virtually always an INPUT 
 argument, and shouldn't be retained past the life of the call.
Hmm, this is a good point I never thought of. Well put!
There's plenty of tools to prevent implicit allocations and if the delegate is dropped after the function call, it will be `scope` anyway. The benefit of allowing a closure allocation is that it becomes possible to implement actual lazy evaluation.
Nov 22 2020
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Nov 23, 2020 at 7:46 AM Timon Gehr via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 22.11.20 10:18, Walter Bright wrote:
 On 11/20/2020 12:06 AM, Manu wrote:
 So, the thing that makes me nervous about this DIP, is that it may
 substantially proliferate allocated closures.
 I would want to have high confidence that people exclusively use
 `scope` delegates, such that the closure can (will?/must?) be stack
 allocated.

 In my experience, in the rare instance that I want to use a lazy
 parameter in the sorts of ways that might be affected by this DIP,
 it's usually in support of a fairly small optimisation, or a modest
 convenience in the API.
 Relative to that optimisation, if there's a risk of introducing a
 closure allocation, that would vastly out-weight the advantage by my
 judgement, and it's very easy for such allocations to go unnoticed.
 It's completely invisible.

 I would appeal that this DIP be changed such that auto-delegates must
 be `scope`, and non-scope delegates should require the user to specify
 a non-scope delegate argument using typical delegate syntax, so that
 you can plainly see it.
 Without requiring `scope` delegates, the risk of hidden allocations is
 extremely high, and it's almost certainly NOT what anybody would ever
 want from a lazy argument, which is virtually always an INPUT
 argument, and shouldn't be retained past the life of the call.
Hmm, this is a good point I never thought of. Well put!
There's plenty of tools to prevent implicit allocations and if the delegate is dropped after the function call, it will be `scope` anyway. The benefit of allowing a closure allocation is that it becomes possible to implement actual lazy evaluation.
You can just write `() => expr` in that case, then the allocation is visible. I think the risk of hidden allocated closures is substantial and shouldn't be taken lightly, and I don't see evidence that deferred lazy functions is a popular enough pattern to justify accepting this risk. This is a restriction that can be trivially lifted in the future if the pattern you describe is prolific and my suggestion is proven to be cumbersome, but it's virtually impossible to add the restriction in the future once the cat is already out of the bag. I am _deeply_ concerned by a core language syntax that may invisibly result in random allocations at any function callsite. It's also the sort of thing that would be extremely off-putting to tech-directors doing technology/language assessments in my industry; it's at the level where it could tip someone's judgement. Please consider a conservative approach, and lift the restriction in the future if there's demonstrated advantage.
Nov 23 2020
next sibling parent reply Nick Treleaven <nick geany.org> writes:
On Monday, 23 November 2020 at 08:01:00 UTC, Manu wrote:
 This is a restriction that can be trivially lifted in the 
 future if the
 pattern you describe is prolific and my suggestion is proven to 
 be
 cumbersome, but it's virtually impossible to add the 
 restriction in the
 future once the cat is already out of the bag.
 I am _deeply_ concerned by a core  language syntax that may 
 invisibly result
 in random allocations at any function callsite.
+1, absolutely. In a systems language the caller should always be aware whether the function scope is heap-allocated or not. This is about performance, predictability and easier code review. (It's not just for those wishing to minimise use of the GC).
Nov 23 2020
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 23.11.20 10:00, Nick Treleaven wrote:
 On Monday, 23 November 2020 at 08:01:00 UTC, Manu wrote:
 This is a restriction that can be trivially lifted in the future if the
 pattern you describe is prolific and my suggestion is proven to be
 cumbersome, but it's virtually impossible to add the restriction in the
 future once the cat is already out of the bag.
 I am _deeply_ concerned by a core  language syntax that may invisibly 
 result
 in random allocations at any function callsite.
+1, absolutely. In a systems language the caller should always be aware whether the function scope is heap-allocated or not. This is about performance, predictability and easier code review. (It's not just for those wishing to minimise use of the GC).
No, sorry, that's exactly just who it is for. The ability to write code at the appropriate level of abstraction for the given use case is a strength of D.
Nov 23 2020
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 23.11.20 09:01, Manu wrote:
 ...
      >> Without requiring `scope` delegates, the risk of hidden
     allocations is
      >> extremely high, and it's almost certainly NOT what anybody would
     ever
      >> want from a lazy argument, which is virtually always an INPUT
      >> argument, and shouldn't be retained past the life of the call.
      >
      > Hmm, this is a good point I never thought of. Well put!
 
     There's plenty of tools to prevent implicit allocations and if the
     delegate is dropped after the function call, it will be `scope` anyway.
     The benefit of allowing a closure allocation is that it becomes
     possible
     to implement actual lazy evaluation.
 
 
 You can just write `() => expr` in that case, then the allocation is 
 visible. I think the risk of hidden allocated closures is substantial 
 and shouldn't be taken lightly, and I don't see evidence that deferred 
 lazy functions is a popular enough pattern to justify accepting this risk.
I am not sure this is even officially supported right now. Taking the address of a lazy parameter is not safe. (This might be an oversight, though I'm pretty sure the documentation used to state that lazy implies scope.)
 This is a restriction that can be trivially lifted in the future if the 
 pattern you describe is prolific and my suggestion is proven to be 
 cumbersome, but it's virtually impossible to add the restriction in the 
 future once the cat is already out of the bag.
 I am _deeply_ concerned by a core language syntax that may invisibly 
 result in random allocations at any function callsite.
It really does not matter much whether the allocation is at the callsite or at the beginning of the function itself. If it's at the call site, at least you can tell from the function signature...
 It's also the sort of thing that would be extremely off-putting to
tech-directors 
 doing technology/language assessments in my industry; it's at the level 
 where it could tip someone's judgement.
 ...
We have nogc. What's the point of even supporting nogc if this kind of rhetoric continues anyway? I'd rather have a language that is useful instead of one that appeals to people with bad decision making.
 Please consider a conservative approach, and lift the restriction in the 
 future if there's demonstrated advantage.
It's not up to me.
Nov 23 2020
parent reply Nick Treleaven <nick geany.org> writes:
On Monday, 23 November 2020 at 12:55:45 UTC, Timon Gehr wrote:
 If it's at the call site, at least you can tell from the 
 function signature...
If you and all reviewers correctly detect the right overload. What if the programmer doesn't check the signature every time they use that function?
 We have  nogc. What's the point of even supporting  nogc if 
 this kind of rhetoric continues anyway?
You may still want some GC allocations, but not want a closure allocated. Or you simply want allocations to be obvious, because they can be slow.
 I'd rather have a language that is useful instead of one that 
 appeals to people with bad decision making.
How does having to write `() => ` for each argument flip a language from being useful to not useful?
Nov 23 2020
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 23.11.20 17:00, Nick Treleaven wrote:
 On Monday, 23 November 2020 at 12:55:45 UTC, Timon Gehr wrote:
 If it's at the call site, at least you can tell from the function 
 signature...
If you and all reviewers correctly detect the right overload. What if the programmer doesn't check the signature every time they use that function? ...
What if they don't check if the function allocates?
 We have  nogc. What's the point of even supporting  nogc if this kind 
 of rhetoric continues anyway?
You may still want some GC allocations, but not want a closure allocated. Or you simply want allocations to be obvious, because they can be slow. ...
Allocations can hide behind function calls anyway.
 I'd rather have a language that is useful instead of one that appeals 
 to people with bad decision making.
How does having to write `() => ` for each argument flip a language from being useful to not useful?
It's a continuum... D has enough weird non-orthogonal restrictions as-is.
Nov 23 2020
prev sibling next sibling parent Q. Schroll <qs.il.paperinik gmail.com> writes:
In the Feedback thread, Walter wrote:

 All this [the proposed changes] does is replace the 'lazy' with 
 the delegate syntax. D already uses this for variadic lazy 
 arguments, and nothing has come up bad about it.
Have you ever tried to use attributes on them? It's a mess. The expressions converted to delegates are not at all equivalent to literal delegates when attributes are at play. int fun(int delegate() pure [] xs...) pure { foreach (x; xs) if (auto value = x()) return value; return 0; } void impureContext() { import std.stdio : write; int impureFactory() { write(""); return 0; } fun(impureFactory()); // passes, but why?? fun(&impureFactory); // fails, no surprise fun(() => impureFactory()); // fails, no surprise } void pureContext() pure { int pureFactory() pure { return 0; } fun(pureFactory()); // passes, no surprise fun(&pureFactory); // passes, no surprise fun(() => pureFactory()); // passes, no surprise } The DIP should make clear, that "simply" lowering expressions to delegates isn't what's going on.
Nov 22 2020
prev sibling next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Friday, 20 November 2020 at 07:29:21 UTC, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 1033, 
 "Implicit Conversion of Expressions to Delegates":

 https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md
Does DIP1033, or rather, a post-DIP1033 language, offer any hope for https://issues.dlang.org/show_bug.cgi?id=21420 ? Tl;dr: the default parameter to Nullable.get() cannot be lazy because if it were lazy, Nullable.get() could neither infer nor carry any sort of nothrow or safe annotation, making it unusable from safe/nothrow code. Could DIP1033 offer something like ... inout(T) get(DG : inout(T) delegate())(DG fallback) pure { ... } Where DG would carry callsite inference about nothrow and safe ness of the converted expression?
Nov 24 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 24 November 2020 at 09:47:33 UTC, FeepingCreature 
wrote:
 Could DIP1033 offer something like ...

 inout(T) get(DG : inout(T) delegate())(DG fallback) pure { ... }

 Where DG would carry callsite inference about nothrow and  safe 
 ness of the converted expression?
As I understand it, with DIP 1033, a call to your example `get` function like `myNullable.get(123)` will deduce `DG` to be `int` (as it currently would), but it will instantiate successfully instead of failing, because `int` will now have an implicit conversion to `inout(int) delegate`. At runtime, the argument will be evaluated eagerly unless you explicitly wrap it in a delegate (e.g., with `() =>`).
Nov 24 2020
parent FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 24 November 2020 at 17:12:38 UTC, Paul Backus wrote:
 On Tuesday, 24 November 2020 at 09:47:33 UTC, FeepingCreature 
 wrote:
 Could DIP1033 offer something like ...

 inout(T) get(DG : inout(T) delegate())(DG fallback) pure { ... 
 }

 Where DG would carry callsite inference about nothrow and 
  safe ness of the converted expression?
As I understand it, with DIP 1033, a call to your example `get` function like `myNullable.get(123)` will deduce `DG` to be `int` (as it currently would), but it will instantiate successfully instead of failing, because `int` will now have an implicit conversion to `inout(int) delegate`. At runtime, the argument will be evaluated eagerly unless you explicitly wrap it in a delegate (e.g., with `() =>`).
Ah crud, yeah. Damn. It would be *really valuable* to have a way to actually combine lazy with safe, pure, nothrow etc.
Nov 25 2020
prev sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Friday, 20 November 2020 at 07:29:21 UTC, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 1033, 
 "Implicit Conversion of Expressions to Delegates":

 https://github.com/dlang/DIPs/blob/8e56fc593ece5c74f18b8eb68c3f9dcedf2396a7/DIPs/DIP1033.md
I don't quite understand this paragraph on "null": "null implicitly converts directly to any delegate, but is not of type T, so it will not be turned into a lambda. Again, this is what is expected and is consistent with existing code." What if T is another nullable type? class C { } void foo(C delegate() c) { C c2 = c(); // According to the DIP, segfaults immediately instead of initializing c2 to null } void main() { foo(null); } "null" implicitly converts to C and, therefore, should be converted to "delegate() typeof(null){ return null; }" if we want proper lazy semantics.
Nov 25 2020