July 10, 2014
On 07/09/2014 09:50 PM, Walter Bright wrote:
> On 7/9/2014 7:37 AM, Timon Gehr wrote:
>> On 07/08/2014 11:22 PM, Walter Bright wrote:
>>> 3. 'ref' means 'borrowed', to use Rust's terminology
>>> We're almost there with this. This means better escape analysis, too.
>> What makes you think that 'ref' is a good match for this
>> functionality, and how
>> are we almost there with this?
>
> 'ref' is already used conventionally in such a manner as implying it is
> borrowed. 'ref' pointers cannot be stored,

Borrowed pointers can be stored in data structures and they can be reassigned.

> and one cannot take the address of a ref'd variable in @safe code.
> ...

Borrowed should also be enforced in @system code by default.
Also, how do I borrow a class reference?

>
>
>>> 8. NotNull!T type
>>>
>>> For those that want a non-nullable reference type. This should be doable
>>> as a library type.
>> No.
>
> Rationale?

null
July 10, 2014
On 7/9/2014 5:24 PM, Timon Gehr wrote:
> On 07/09/2014 09:50 PM, Walter Bright wrote:
>> On 7/9/2014 7:37 AM, Timon Gehr wrote:
>>> On 07/08/2014 11:22 PM, Walter Bright wrote:
>>>> 3. 'ref' means 'borrowed', to use Rust's terminology
>>>> We're almost there with this. This means better escape analysis, too.
>>> What makes you think that 'ref' is a good match for this
>>> functionality, and how
>>> are we almost there with this?
>>
>> 'ref' is already used conventionally in such a manner as implying it is
>> borrowed. 'ref' pointers cannot be stored,
>
> Borrowed pointers can be stored in data structures and they can be reassigned.

My purpose in posting this is not "I have a design". I don't have a design. A design needs to be created:

1. assess where we are
2. decide where we want to be
3. have a design and a plan that gets there

There's no law that says D refs must be exactly like Rust borrowed. We can come up with a design that works best for D. D != Rust. Do you have a design in mind?


>> and one cannot take the address of a ref'd variable in @safe code.
>> ...
>
> Borrowed should also be enforced in @system code by default.
> Also, how do I borrow a class reference?

Address that in the design.


>>>> For those that want a non-nullable reference type. This should be doable
>>>> as a library type.
>>> No.
>>
>> Rationale?
>
> null

??
July 10, 2014
On Wednesday, 9 July 2014 at 22:28:23 UTC, Walter Bright wrote:
> On 7/9/2014 1:58 PM, Sean Kelly wrote:
>> I think it still mostly comes down to marketing :-)  That said,
>> we're pretty close in D once my Scheduler pull request is
>> accepted.  Between that and the Generator type in the same pull
>> request,
>
> Ah, I didn't know you had a PR request already! Awesome!
>
>
> > we're not missing much but the weird switch syntax they have.
>
> I'm not concerned about the syntax. Any syntax we use should be "D style" syntax, not "Go style".
>

Rob Pike has said multiple times that the key/unique thing about Go is "select" and that goroutines are the easy part. I'm not entirely sure I grok what he means but we should if we're going to try and do what they got right.

Atila
July 10, 2014
On 7/9/2014 7:12 PM, Atila Neves wrote:
> Rob Pike has said multiple times that the key/unique thing about Go is "select"
> and that goroutines are the easy part. I'm not entirely sure I grok what he
> means but we should if we're going to try and do what they got right.

I don't know what he means, either.

July 10, 2014
On 07/10/2014 02:39 AM, Walter Bright wrote:
> On 7/9/2014 5:24 PM, Timon Gehr wrote:
>> On 07/09/2014 09:50 PM, Walter Bright wrote:
>>> On 7/9/2014 7:37 AM, Timon Gehr wrote:
>>>> On 07/08/2014 11:22 PM, Walter Bright wrote:
>>>>> 3. 'ref' means 'borrowed', to use Rust's terminology
>>>>> We're almost there with this. This means better escape analysis, too.
>>>> What makes you think that 'ref' is a good match for this
>>>> functionality, and how
>>>> are we almost there with this?
>>>
>>> 'ref' is already used conventionally in such a manner as implying it is
>>> borrowed. 'ref' pointers cannot be stored,
>>
>> Borrowed pointers can be stored in data structures and they can be
>> reassigned.
>
> My purpose in posting this is not "I have a design". I don't have a
> design. A design needs to be created:
>
> 1. assess where we are

I think we are basically nowhere. Borrowing is about controlling lifetimes.

> 2. decide where we want to be

I don't know, but I assume it would have to be competitive with what Rust provides.

> 3. have a design and a plan that gets there
>
> There's no law that says D refs must be exactly like Rust borrowed. We
> can come up with a design that works best for D. D != Rust. Do you have
> a design in mind?
> ...

Roughly, but not with 'ref'. It is also an issue of syntax at this point. I think we should get at least the basics fixed there before talking in-depth about semantics. (In any case, I still have one DIP pending in an unacceptable state that I couldn't find the time to write down properly yet.)

Fundamentally, we need syntax for (examples provided for illustration, those are not proposals):

- Parametric polymorphism

Eg.: void foo[A](int x){ ... }


- Lifetime parameters. (it's more future-proof if they are not introduced by simple identifiers.)

Eg.: void foo[lifetime lt](int x){ ... }


- Attaching a lifetime to a pointer, class reference, ref argument.

Eg.: void foo[lifetime lt](int scope(lt)* x){ ...}
     void foo[lifetime lt](scope(lt) C c){ ... }
     void foo[lifetime lt](scope(lt) ref int x){ ... }
     void foo[lifetime lt1,lifetime lt2](scope(lt1)(C)scope(lt2)[] a){ ... }

(The last example talks about a slice where the array memory has different lifetimes than the class instances it contains.)

- Lifetime intersection:

Eg.: scope(lt1&lt2)Tuple!(int*,int*) pair[lifetime lt1,lifetime lt2](int scope(lt1)* p1, int scope(lt1)* p2){ ... }

(It can alternatively be done only implicitly at function boundaries.)


- Specifying the lifetime of a struct/class upon construction:

Eg.: struct S[lifetime lt1,lifetime lt2]{
         ...
         this(int scope(lt1)* x, int scope(lt2)* y)scope(lt1&lt2){ ... }
     }

>...
>
>>>>> For those that want a non-nullable reference type. This should be
>>>>> doable
>>>>> as a library type.
>>>> No.
>>>
>>> Rationale?
>>
>> null
>
> ??

My point exactly. http://xkcd.com/641/

Also, there will be the usual problems with subtyping.
July 10, 2014
On Thursday, 10 July 2014 at 02:12:18 UTC, Atila Neves wrote:
> Rob Pike has said multiple times that the key/unique thing about Go is "select" and that goroutines are the easy part. I'm not entirely sure I grok what he means but we should if we're going to try and do what they got right.

Select is vital for Go in the sense that without it there'd be no way to do non-blocking send/receives on channels in Go. It's much more concise than the alternative, which would be something like `if chanA is empty then foo(chanA) else if chanB is empty then bar(chanB)`. It also avoids starvation by checking the channels in a random order - unlike the previous if-else chain, which would never call bar(chanB) if chanA was always empty.

It's been implemented in Rust[1] via a macro, and can be implemented in Haskell[2] without compiler support, so I'd be surprised if it wasn't already possible to implement in D. It wouldn't however be as useful as Go's until D gets message passing between fibres.

Actually, an important question that should be considered: does D want actor-style concurrency, like Erlang and Akka, or CSP-style concurrency, like Rust, Go and Haskell? Or both? Deciding this would allow efforts to be more focused.

I personally think either would be great, and sufficient to make me consider D for any of the work I'd currently use Go. D currently however has neither. It technically implements the actor model in std.concurrency, but using OS threads, which significantly reduces its utility (one doesn't just spawn 100k OS threads).

1. http://thornydev.blogspot.com.au/2014/03/select-over-multiple-rust-channels.html
2. http://stackoverflow.com/questions/24611801/how-to-implement-the-equivalent-of-gos-select-statement-for-haskell-stm-channel
July 10, 2014
On Thursday, 10 July 2014 at 03:12:24 UTC, Timon Gehr wrote:
> I don't know, but I assume it would have to be competitive with what Rust provides.

I think the Rust team found that implementing a sound borrow-checker was basically impossible without requiring lifetime annotations in some cases. So if D wanted to go down the Rust route, it'd have to be willing to add new syntax for lifetime annotations (although these can apparently be inferred in most cases so aren't often required).
July 10, 2014
On Wednesday, 9 July 2014 at 22:55:19 UTC, Walter Bright wrote:
> On 7/9/2014 1:58 PM, Sean Kelly wrote:
>> we're pretty close in D once my Scheduler pull request is
>> accepted.
>
> I couldn't find it. Can you please add the link to the PR to:
>
> https://issues.dlang.org/show_bug.cgi?id=13086
>
> ?

https://github.com/D-Programming-Language/phobos/pull/1910
July 10, 2014
On Thu, Jul 10, 2014 at 05:12:23AM +0200, Timon Gehr via Digitalmars-d wrote: [...]
> - Lifetime parameters. (it's more future-proof if they are not
> introduced by simple identifiers.)
> 
> Eg.: void foo[lifetime lt](int x){ ... }
> 
> 
> - Attaching a lifetime to a pointer, class reference, ref argument.
> 
> Eg.: void foo[lifetime lt](int scope(lt)* x){ ...}
>      void foo[lifetime lt](scope(lt) C c){ ... }
>      void foo[lifetime lt](scope(lt) ref int x){ ... }
>      void foo[lifetime lt1,lifetime lt2](scope(lt1)(C)scope(lt2)[] a){ ... }
> 
> (The last example talks about a slice where the array memory has different lifetimes than the class instances it contains.)
[...]

This is starting to look like some parts of my 'scope' proposal in another part of this thread.

I'm wondering if it makes sense to simplify lifetimes by tying them to lexical context rather than using explicit annotations? Being able to specify explicit lifetimes seem a bit excessive to me, but perhaps you have a use case in mind that I'm not aware of?


T

-- 
People demand freedom of speech to make up for the freedom of thought which they avoid. -- Soren Aabye Kierkegaard (1813-1855)
July 10, 2014
On 07/10/2014 07:41 AM, H. S. Teoh via Digitalmars-d wrote:
> On Thu, Jul 10, 2014 at 05:12:23AM +0200, Timon Gehr via Digitalmars-d wrote:
> [...]
>> - Lifetime parameters. (it's more future-proof if they are not
>> introduced by simple identifiers.)
>>
>> Eg.: void foo[lifetime lt](int x){ ... }
>>
>>
>> - Attaching a lifetime to a pointer, class reference, ref argument.
>>
>> Eg.: void foo[lifetime lt](int scope(lt)* x){ ...}
>>       void foo[lifetime lt](scope(lt) C c){ ... }
>>       void foo[lifetime lt](scope(lt) ref int x){ ... }
>>       void foo[lifetime lt1,lifetime lt2](scope(lt1)(C)scope(lt2)[] a){ ... }
>>
>> (The last example talks about a slice where the array memory has
>> different lifetimes than the class instances it contains.)
> [...]
>
> This is starting to look like some parts of my 'scope' proposal in
> another part of this thread.
>
> I'm wondering if it makes sense to simplify lifetimes

(This is not complicated.)

> by tying them to lexical context

They are.

> rather than using explicit annotations?

Suitable rules can be added to automatically do some sensible thing by default, but I don't think it makes sense to try and guess suitable lifetimes just by staring at a function signature in the general case.

> Being able to
> specify explicit lifetimes seem a bit excessive to me, but perhaps you
> have a use case in mind that I'm not aware of?
>...

If lifetimes cannot transcend function invocations, this is a serious limitation, don't you agree? How would you do e.g. an identity function on a borrowed pointer type, to name a simple example?