Idea for avoiding GC for lambdas

Steven Schveighoffer schveiguy at gmail.com
Tue Jun 22 15:05:18 UTC 2021


On 6/21/21 6:19 PM, Elronnd wrote:
> The reason delegates involve GC is because the closure is shared.  E.G.:
> 
> int x;
> auto f = () => x++;
> auto g = () => x++;
> f(); //0
> g(); //1
> f(); //2

Yes, but only necessary if the data is mutated.

> Your proposal is essentially a value delegate; the __context stuff makes 
> that explicit, but it's not actually fundamentally different from the 
> current scheme, it's just that the context becomes a value type rather 
> than a reference type.

Right, I honestly don't know how the context is passed for an alias 
parameter. The compiler must pass some sort of context pointer to the 
calling function, which then gets stored somehow. But it's all hidden. 
If it's hidden, it might as well be as big as needed.

> I think value closures are a good idea--for semantics reasons too, not 
> just avoiding gc--but problematic for existing APIs to support, because 
> every value closure will have a different type and a different size.

Remember, these aren't delegates in the strict sense, they are alias 
parameters. They can be implemented however D wants. Take a look at the 
`filter` 
[implementation](https://github.com/dlang/phobos/blob/61c00065a8c7efdf21efb92ce69d7a9de4904ec9/std/algorithm/iteration.d#L1371-L1432), 
there's not a delegate in sight.

> And we have enough problems already with compile time template explosion :)

This shouldn't have a significant effect on templates -- aliases are 
already unique parameters, causing a new template for every call.

> 
> WRT your proposal, I think it would be better to introduce an alternate 
> syntax for function literals: we have  function(parm) => ret  and  
> delegate(parm) => ret; add  valuedelegate(parm) => ret.  And make it so 
> that valuedelegate.ptr is a struct (the context struct) so you can still 
> introspect it if needed.

I'm unsure if this is how it works, the alias parameters aren't exactly 
delegates, though that might be how the compiler implements them.

My thought was that the compiler could pick to send the function alias 
in as a straight alias (without context) and pass the context in as a 
separate parameter. The function itself would have a type that accepts 
the context data.

>> I realize there are implications if the context parameter is mutable, 
>> so perhaps we would have to require only const contexts
> 
> Why?  What you've made is basically a functor where the compiler infers 
> the context; structs are received by reference (by their methods).  If 
> the context were shared, then const wouldn't be enough; it would have to 
> be immutable to retain value semantics. But the whole point of this was 
> to avoid sharing (and hence GC), so I don't see why that would be a 
> problem.

I mean non-changeable contexts. These can be const data, as long as they 
aren't const references, they should be unchangeable.

I.e. the compiler should be able to pass an x like:

```d
const x = 5;
```

-Steve


More information about the Digitalmars-d mailing list