May 25, 2017
On Wednesday, 24 May 2017 at 20:15:37 UTC, Vittorio Romeo wrote:
> If you're interested in contributing, please let me know and I'll add you as a collaborator.

can i just edit it on the site?

but a few comments:

"Currently FunctionLiterals that capture their outer context (i.e. closures/delegates) require an allocation and the garbage collector. "


Not necessarily true, make sure you actually mention `scope delegate` and `alias` params that do not return it. Those capture but do not allocate.


"We will be proposing a syntax redundant w.r.t. current behavior (i.e. capture by reference), so maybe we should consider proposing deprecation?"

Don't do that.

"    // or simply, using existing syntax:
    //auto l = () => writeln("hello!");"

That existing one will actually make a function, not a delegate, since it doesn't access any locals.

"    struct anonymous_l"

That should be `static struct`.

"Capture by reference"

I'm against that, no need adding it and it complicates the whole thing. For example, "ref int _i;" as a struct member; there's no such thing in D. (the compiler could do it but still). And you'd have to explain the lifetime. Just no point doing this, the current behavior is completely fine for this.
May 25, 2017
On Thursday, 25 May 2017 at 01:18:22 UTC, Mike Parker wrote:

label:
if (self.bored) goto disclaimer;

>> We're well aware. The file name is not indicative of anything.


> The README outlines the procedure for DIP submission, including the format of the filename. The concern is that if you include number in the filename, it opens the door to people referring to it by that number. We want to avoid that.
>
> [1] https://github.com/dlang/DIPs/blob/master/README.md

// warning, loops until self.bored is true
goto label;

disclaimer:

Mike, I've read that README several times over. Yes, a mistake was made, a number self-assigned. Yes, that is not how it's done. Yes, we know. Yes. Thanks for the reminder. All is fixed.
May 25, 2017
On Thursday, 25 May 2017 at 03:10:04 UTC, Adam D. Ruppe wrote:

>
> "Currently FunctionLiterals that capture their outer context (i.e. closures/delegates) require an allocation and the garbage collector. "
>
>
> Not necessarily true, make sure you actually mention `scope delegate` and `alias` params that do not return it. Those capture but do not allocate.

It's an infant document, wording is out there somewhere...

> "We will be proposing a syntax redundant w.r.t. current behavior (i.e. capture by reference), so maybe we should consider proposing deprecation?"
>
> Don't do that.

Why not? I, personally, have a simple, but solid, justification:

Captures, if any, should be explicit. That is all :)

That is solely my opinion, hence the cautious "maybe"...

> "Capture by reference"
>
> I'm against that, no need adding it and it complicates the whole thing. For example, "ref int _i;" as a struct member; there's no such thing in D. (the compiler could do it but still). And you'd have to explain the lifetime. Just no point doing this, the current behavior is completely fine for this.

By inference, adding capture syntax at all will also complicate the whole thing. IMHO, we either should have one, or the other, but not both. P.S. have you seen the TODO at the bottom of that section?
May 25, 2017
On Thursday, 25 May 2017 at 03:30:38 UTC, Stanislav Blinov wrote:
> Captures, if any, should be explicit. That is all :)

The current behavior is fine in most cases. The explicit by-value capture handles the remaining cases.

> By inference, adding capture syntax at all will also complicate the whole thing.

Yeah, there's some complication in adding it but it is worth it because it gives something new without breaking anything old.

> P.S. have you seen the TODO at the bottom of that section?

Yeah, I'm EXTREMELY against removing the current behavior. I'd kill the whole thing just to avoid that.
May 25, 2017
On Thursday, 25 May 2017 at 03:42:11 UTC, Adam D. Ruppe wrote:
> On Thursday, 25 May 2017 at 03:30:38 UTC, Stanislav Blinov wrote:
>> Captures, if any, should be explicit. That is all :)
>
> The current behavior is fine in most cases. The explicit by-value capture handles the remaining cases.

In my opinion, it is not, because it's utterly silent unless you either stumble upon it via @nogc or a compiler switch.

>> By inference, adding capture syntax at all will also complicate the whole thing.
>
> Yeah, there's some complication in adding it but it is worth it because it gives something new without breaking anything old.
>
>> P.S. have you seen the TODO at the bottom of that section?
>
> Yeah, I'm EXTREMELY against removing the current behavior. I'd kill the whole thing just to avoid that.

I understand perfectly, wasn't exactly easy contemplating that "maybe" either. In any case, we should not get ahead of ourselves. I'm not insisting on that particular change, I've brought it up for consideration, opened a discussion, and it looks like it worked :)
May 25, 2017
On Thursday, 25 May 2017 at 03:14:14 UTC, Stanislav Blinov wrote:

>
> Mike, I've read that README several times over. Yes, a mistake was made, a number self-assigned. Yes, that is not how it's done. Yes, we know. Yes. Thanks for the reminder. All is fixed.

Thanks. I wasn't criticizing. It wasn't fixed when I clicked the link, so I just wanted to make sure everyone's on the same page. I can't assume everyone has gone over the README.
May 25, 2017
On Thursday, 25 May 2017 at 04:53:14 UTC, Mike Parker wrote:
> On Thursday, 25 May 2017 at 03:14:14 UTC, Stanislav Blinov wrote:
>
>>
>> Mike, I've read that README several times over. Yes, a mistake was made, a number self-assigned. Yes, that is not how it's done. Yes, we know. Yes. Thanks for the reminder. All is fixed.
>
> Thanks. I wasn't criticizing. It wasn't fixed when I clicked the link, so I just wanted to make sure everyone's on the same page. I can't assume everyone has gone over the README.

Sigh... You're right. We should've renamed the file at the same time as removing the number from the contents, because "internets". And I shouldn't have snapped like that. I apologize.
May 25, 2017
On Thursday, 25 May 2017 at 05:03:15 UTC, Stanislav Blinov wrote:

>
> Sigh... You're right. We should've renamed the file at the same time as removing the number from the contents, because "internets". And I shouldn't have snapped like that. I apologize.

It's all good :-)
May 29, 2017
On Thursday, 25 May 2017 at 03:10:04 UTC, Adam D. Ruppe wrote:
> Snip

I think the discussion is going in two orthogonal directions, which are:

1) Capture by value. This is the ability to have a lambda which behaves as expected in the example Vittorio showed

>   void delegate()[] arr;
>
>    foreach(i; 0..5)
>    {
>        arr ~= () => writeln(i);
>    }
>
>    foreach(f; arr)
>    {
>        f();
>    }
>
>This is going to print "4 4 4 4"

2) Allocation of the lambda context. Whether this is performed by the GC, in the stack, or with another mechanism.

The reason these two points are orthogonal is that, as Adam showed, the ability to achieve one of the point is independent from the other (the capture by reference context allocation can be changed with the scope keyword, and from my understanding it's an implementation detail, it does not guarantee the use of the GC. And the value of capture by value could be allocated on the heap with the GC).


I see two weaknesses in this proposal:

1) The lambda is not compatible with a delegate anymore

2) There need to be a special notation for reference capture

Adam said
> I'm against that, no need adding it and it complicates the whole thing. For example, "ref int _i;" as a struct member; there's no such thing in D. (the compiler could do it but still). And you'd have to explain the lifetime. Just no point doing this, the current behavior is completely fine for this.



The other problem I see, which is easily noticeable when defining the new grammar, is that we are proposing a grammar which is a superset of the current one, but we are proposing it as an addition.


One of the assumption of D is that the GC is not a problem in the vast majority of the situations, and you want things to just work.
I think there is big value in the capture context not having to be explicit (even if usually I much prefer explicity over implicity).


Considered this, I'd propose an extension of the lambda syntax instead of an addition of a ValueFunctionLitteral.

Given the syntax
> [...] (...) ... {...}
which is composed of what I will call "capture", "parameters", "attributes", "body" (with capture and attributes optional)
the semantic would be:

- if no capture is provided the behavior is equivalent to today (automatic capturing by reference in a context allocated however the compiler prefers). This provides full backward compatibility.
Example
(int i) { writeln(i + j);}

j is captured by reference in a context allocated (possibly) on the GC. This is compatible with a delegate void(int).


- if capture is provided, then the lambda is rewritten as a struct, which the explicit variables in the capture list being captured by value, and the remaining being captured by reference (so there would still be implicit capture, which is considered convenient in many programming languages).
This is potentially unsafe since a reference could be copied when copying the struct, and the struct might outlive the referred object.
Example
[x] (int i) { writeln(i + j + x);}

x is captured by value in a local struct.
j is captured by reference in a local struct.
This is not a delegate anymore (different ABI).


- if "delegate" is used, then the capture context is allocated however the compile prefers

[x] delegate (int i) { writeln(i + j + x);}

x is captured by value in a (possibly) GC context.
j is captured by reference in a (possibly) GC context.
This is a delegate (compatible ABI).


This thus is an extension of the lambda syntax to allow capturing by value, but maintaining all the current properties and providing a way to remain compatible with the delegate functions.
You can also use the @nogc attribute to verify that the GC is not used (and in case also "delegate" is used "scope" will need to be used so that the compiler does not require the GC).

What are your opinions?
Please state if there are some misconceptions on the current situation.
May 29, 2017
On Monday, 29 May 2017 at 21:26:11 UTC, MakersF wrote:
> 1) Capture by value. This is the ability to have a lambda which behaves as expected in the example Vittorio showed

That's a known bug in the implementation; it is supposed to work that way now.

(Though the bug has been open for so long I treat it as intended and tell people how to work with it, it isn't actually what the design says.)

> 1) The lambda is not compatible with a delegate anymore
>
> 2) There need to be a special notation for reference capture

That's true, but that's the whole point of the new thing. The auto-generated struct btw can be converted to a delegate with `&obj.opCall` or copied into a manually allocated buffer with `memcpy(buffer, &obj, obj.sizeof)`, just like the manually written struct to do the same. (and might have convenience methods, e.g. toDelegate and copyInto, to do these things too).


> - if capture is provided, then the lambda is rewritten as a struct, which the explicit variables in the capture list being captured by value, and the remaining being captured by reference (so there would still be implicit capture, which is considered convenient in many programming languages).

Eh, if you do any explicit, I think it should be ALL explicit. There's value in the simple proposals to syntax rewrite into a struct... but going beyond that I think is a negative and should not be in this proposal.