May 27, 2021

On Wednesday, 26 May 2021 at 12:36:42 UTC, Atila Neves wrote:

>

On Tuesday, 25 May 2021 at 22:19:23 UTC, tsbockman wrote:

>

This sounds like a really annoying and arbitrary limitation.

It's not arbritrary at all - the purpose is to avoid this:

https://carols10cents.github.io/book/ch10-03-lifetime-syntax.html#lifetime-annotations-in-function-signatures

Reasonable people of course can disagree on whether or not avoiding that is a good idea.

I understand that motivation, but at the same time, it's not necessarily good to reduce flexibility for the programmer. I think I would rather have to clearly annotate my target ref/out parameters every time, than rely on a "magic" rule like "the first parameter is the targeted one".

Of course, that doesn't mean that I want to have Rust-style lifetime annotation if we can have something simpler and easier! But it would certainly be very nice to have the full scope of possibilities that Rust allows. It strikes me that what D should aim for is notation that is clear and unambiguous in intent, but which scales nicely with the complexity of what the programmer wants to achieve (so e.g. if you want to ensure a struct instance outlives a pointer/reference that it wraps, you might have to do more annotation, but if you want to make sure that in input parameter outlives a returned parameter, that's simple and easy).

May 27, 2021

On Wednesday, 26 May 2021 at 12:36:42 UTC, Atila Neves wrote:

>

Reasonable people of course can disagree on whether or not avoiding that is a good idea.

I find Rust's approach more intuitive, even though I am not a Rust programmer...

In general, there is way too many words to remember the meaning of on D function signatures.

But I guess @system is still available...

May 27, 2021

On Thursday, 27 May 2021 at 19:57:49 UTC, Ola Fosheim Grostad wrote:

>

On Wednesday, 26 May 2021 at 12:36:42 UTC, Atila Neves wrote:

>

Reasonable people of course can disagree on whether or not avoiding that is a good idea.

I find Rust's approach more intuitive, even though I am not a Rust programmer...

In general, there is way too many words to remember the meaning of on D function signatures.

But I guess @system is still available...

I do find it more intuitive in Rust too, and lifetime parameters in Rust also apply to structs so you can have a struct that has the same lifetime as the reference it receives, so you can have a Mutex for example return a LockGuard struct that will not outlive the Mutex.

May 27, 2021

On Thursday, 27 May 2021 at 20:11:37 UTC, vitoroak wrote:

>

I do find it more intuitive in Rust too, and lifetime parameters in Rust also apply to structs so you can have a struct that has the same lifetime as the reference it receives, so you can have a Mutex for example return a LockGuard struct that will not outlive the Mutex.

Sounds useful. I have never used lifetimes myself, only read about it (including some theory), but I know that lifetime annotations predates Rust, I think it was used in a ML dialect. So it isn't unique to Rust and I assume universities will teach it... So, it will most likely become standard? Dunno.

May 29, 2021

On Tuesday, 25 May 2021 at 11:24:59 UTC, Dennis wrote:

>

We want to express:

//                       ┌─────────>─────────┐
void move(T)(return T source, ref scope T target)

Here's a simple extension idea: https://github.com/dlang/dmd/pull/12601

Simply skip over return parameters when looking for the 'first' parameter, since making a return parameter its own destination has no use. It's still constraining the parameter order, but may be good enough to move forward with move.

May 29, 2021

On Thursday, 27 May 2021 at 20:21:58 UTC, Ola Fosheim Grostad wrote:

>

On Thursday, 27 May 2021 at 20:11:37 UTC, vitoroak wrote:

>

I do find it more intuitive in Rust too, and lifetime parameters in Rust also apply to structs so you can have a struct that has the same lifetime as the reference it receives, so you can have a Mutex for example return a LockGuard struct that will not outlive the Mutex.

Sounds useful. I have never used lifetimes myself, only read about it (including some theory), but I know that lifetime annotations predates Rust, I think it was used in a ML dialect. So it isn't unique to Rust and I assume universities will teach it... So, it will most likely become standard? Dunno.

It goes back to Cyclone, https://cyclone.thelanguage.org/

May 29, 2021

On Saturday, 29 May 2021 at 12:32:49 UTC, Paulo Pinto wrote:

>

It goes back to Cyclone, https://cyclone.thelanguage.org/

There you go, with original papers and all.

I still think local GC + ARC for shared is a more convenient path for @safe users, but who am I to judge if people want affine/linear types.

May 29, 2021

On Saturday, 29 May 2021 at 12:39:48 UTC, Ola Fosheim Grøstad wrote:

>

On Saturday, 29 May 2021 at 12:32:49 UTC, Paulo Pinto wrote:

>

It goes back to Cyclone, https://cyclone.thelanguage.org/

There you go, with original papers and all.

I still think local GC + ARC for shared is a more convenient path for @safe users, but who am I to judge if people want affine/linear types.

I would rather bet on GC + affine/linear types like Haskell is pursuing.

In any case, there is even research trying to make use of C2X annotations to retrofit it into C,

https://plv.mpi-sws.org/refinedc/

May 30, 2021

On Saturday, 29 May 2021 at 18:21:15 UTC, Paulo Pinto wrote:

>

I would rather bet on GC + affine/linear types like Haskell is pursuing.

Haskell is a functional language, so they are in a much better position to separating the heap and doing shape analysis.

>

In any case, there is even research trying to make use of C2X annotations to retrofit it into C,

https://plv.mpi-sws.org/refinedc/

Looks more or less like other languages that focus on full formal verification using Hoare logic.

May 30, 2021

On Saturday, 29 May 2021 at 11:32:50 UTC, Dennis wrote:

> >

We want to express:

//                       ┌─────────>─────────┐
void move(T)(return T source, ref scope T target)

Here's a simple extension idea: https://github.com/dlang/dmd/pull/12601

Simply skip over return parameters when looking for the 'first' parameter, since making a return parameter its own destination has no use. It's still constraining the parameter order, but may be good enough to move forward with move.

It might be more accurate to say, "A simple extension idea, built upon several other 'simple extension ideas,' such that the keyword which activates the feature is now completely counterintuitive!"

Apart from the counterintuitive meaning, the other downside, as I see it, would be if the return keyword were stretched to the point of exhaustion, and yet still proved insufficient. At that point, a more robust solution would have to be added, and the new solution would have to exist side-by-side with existing overextended uses of return.

Perhaps in the end, return alone, totally out of its element, will nonetheless cover all necessary use cases. But if not, for example, the system I proposed my prior post (https://forum.dlang.org/post/cdurilferuuvwgciqdtb@forum.dlang.org) could replace the above extension of return in a far more intuitive way. The system uses designated attributes to refer to built-in lifetime routing channels. If we use, for example, @in1 and @out1 for channel 1, the move function would look like this:

//                    ┌─────────────>───────────┐
void move(T)(@in1 T source, @out1 ref scope T target)

Under this system, the return attribute can still be defined—it is a routing channel which automatically attaches to the first viable target, starting with the return reference and then through... whatever the sequence is....

The main point is that if return is stretched as far as possible, the day may come when it will be forced to live side-by-side with a replacement which covers much of the same territory.

It's likely a manageable problem, a small stain on future incarnations of the language. But worth mentioning.