www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Unique as a transitive type?

reply Jason House <jason.james.house gmail.com> writes:
Andrei has stated previously that unique was left out of the type system
because it added little value to the const system. Now that shared and
multithreading are here, unique has more value.

I have two basic questions:

1. What would make unique difficult to add?

2. What benefits do you forsee?


Here are my thoughts:
1) Escape analysis - construction of unique objects must be careful with how
they manipulate their members. This would require scope parameters (AKA lent in
Bartosz's blog/literature). After construction, it may also be necessary to
update the manipulate the unique object while preserving its uniqueness.
Personally, I like the idea of scope by default, but I'm probably in the
minority.

2) Plugs a gaping hole in the type system. Even with shared added, I had a
moderate multi-threaded code base compile and run without use of shared or
casting. That boiled down to an inability to start threads without (silently)
subverting the type system. 
It's also possible to optimize operations on unique data in ways that one can't
do when a rogue write reference might exist somewhere.  That's not the same as
invariant, but it's similar. Unique can be implicitly cast to scope invariant. 
Jun 01 2009
next sibling parent Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
In the short time I was at the Kahili coffeehouse summit I heard Walter say
more than once that he was troubled by the idea of more transitive construction
types because he was afraid of the combinatorial explosion that would occur. 

And that was just adding 'unique'. Bartosz was trying to talk him into 'unique'
and 'lent'.

I don't know if Bartosz and Andrei and Walter came to any agreement -- they
seemed to be in three mutually exclusive frames of mind at the start anyway.

From my knothole I think unique and lent would be positive additions, even if
it does offend Walter's finer sensibilities!

Paul


Jason House Wrote:

 Andrei has stated previously that unique was left out of the type system
because it added little value to the const system. Now that shared and
multithreading are here, unique has more value.
 
 I have two basic questions:
 
 1. What would make unique difficult to add?
 
 2. What benefits do you forsee?
 
 
 Here are my thoughts:
 1) Escape analysis - construction of unique objects must be careful with how
they manipulate their members. This would require scope parameters (AKA lent in
Bartosz's blog/literature). After construction, it may also be necessary to
update the manipulate the unique object while preserving its uniqueness.
Personally, I like the idea of scope by default, but I'm probably in the
minority.
 
 2) Plugs a gaping hole in the type system. Even with shared added, I had a
moderate multi-threaded code base compile and run without use of shared or
casting. That boiled down to an inability to start threads without (silently)
subverting the type system. 
 It's also possible to optimize operations on unique data in ways that one
can't do when a rogue write reference might exist somewhere.  That's not the
same as invariant, but it's similar. Unique can be implicitly cast to scope
invariant. 
Jun 01 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 01 Jun 2009 19:16:55 -0400, Jason House  
<jason.james.house gmail.com> wrote:

 Andrei has stated previously that unique was left out of the type system  
 because it added little value to the const system. Now that shared and  
 multithreading are here, unique has more value.

 I have two basic questions:

 1. What would make unique difficult to add?

 2. What benefits do you forsee?


 Here are my thoughts:
 1) Escape analysis - construction of unique objects must be careful with  
 how they manipulate their members. This would require scope parameters  
 (AKA lent in Bartosz's blog/literature). After construction, it may also  
 be necessary to update the manipulate the unique object while preserving  
 its uniqueness. Personally, I like the idea of scope by default, but I'm  
 probably in the minority.

 2) Plugs a gaping hole in the type system. Even with shared added, I had  
 a moderate multi-threaded code base compile and run without use of  
 shared or casting. That boiled down to an inability to start threads  
 without (silently) subverting the type system.
 It's also possible to optimize operations on unique data in ways that  
 one can't do when a rogue write reference might exist somewhere.  That's  
 not the same as invariant, but it's similar. Unique can be implicitly  
 cast to scope invariant.
1) Well, the difficulty I see, is that you can't just add unique. When I think of unique, I generally think of it as being shallow - i.e. that object is unique, but it can contain references to non-unique objects (not-transitive). Though this makes construction, etc, easier, there are times you'd like to have non-unique members which are protected by the uniqueness of the parent. This adds a 'owned' type, which starts to run into Escape analysis issues. Then there's ref unique, which is an odd duck: first the unique is moved into the function, and then on scope(exit) it is moved back out. This subtly comes into play with things like tasks/futures. Of course, there's also 'lent', which allows unique to be used with a wider range of functions. 2) To me, unique is all about performance. Shared can do all the same things, it just cost's taking a thin-lock to do so, which is pretty cheap. Having it as a type (instead of its current form as library template) does have some integration benefits with the lent system, but that's about it. BTW, shared isn't implemented yet (beyond basic keyword recognition)
Jun 01 2009
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Jason House wrote:
 Andrei has stated previously that unique was left out of the type system
because it added little value to the const system. Now that shared and
multithreading are here, unique has more value.
 
 I have two basic questions:
 
 1. What would make unique difficult to add?
Move semantics. Just passing a unique value type to a function, a copy is performed.
 2. What benefits do you forsee?
Message passing could be done without needless copying and with a reasonable degree of safety. I've done this before in C++ by storing the reference in a modified shared_ptr (so it can live in containers), then asserting is_unique() and transferring the reference to an auto_ptr when passing into the message. Kind of messy, but it works well enough.
Jun 01 2009
parent reply Jason House <jason.james.house gmail.com> writes:
Sean Kelly Wrote:

 Jason House wrote:
 Andrei has stated previously that unique was left out of the type system
because it added little value to the const system. Now that shared and
multithreading are here, unique has more value.
 
 I have two basic questions:
 
 1. What would make unique difficult to add?
Move semantics. Just passing a unique value type to a function, a copy is performed.
Why would copying occur? Can't a function simply pass it by reference and then zero out that register when done?
 2. What benefits do you forsee?
Message passing could be done without needless copying and with a reasonable degree of safety. I've done this before in C++ by storing the reference in a modified shared_ptr (so it can live in containers), then asserting is_unique() and transferring the reference to an auto_ptr when passing into the message. Kind of messy, but it works well enough.
Jun 01 2009
parent Sean Kelly <sean invisibleduck.org> writes:
Jason House wrote:
 Sean Kelly Wrote:
 
 Jason House wrote:
 Andrei has stated previously that unique was left out of the type system
because it added little value to the const system. Now that shared and
multithreading are here, unique has more value.

 I have two basic questions:

 1. What would make unique difficult to add?
Move semantics. Just passing a unique value type to a function, a copy is performed.
Why would copying occur? Can't a function simply pass it by reference and then zero out that register when done?
Technically, yes. I meant more from a language standpoint. A copy theoretically occurs when returning a value from a function as well.
Jun 01 2009