www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: const challenge

reply Sergey Gromov <snake.scaly gmail.com> writes:
Janice Caron Wrote:

 On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 1. Anything you 'new' is basically unique:
 2. Any non-unique type within a type casts away uniqueness:
 3. unique(...) casts to invariant(...), const(...), or just ... implicitly
 with well-defined behavior.
 4. There is no such thing as unique variable.

 Did I miss something ?

Only function returns, I think.

Of course, you're right.
 As soon as you assign it to a variable, or use it in an expression it
 stops being unique.

Inline array initialization is also an expression, and unique must survive to allow the whole array be unique. Why using in expression makes data not unique ?
 You need a way of expressing that functions can accept unique objects,
 and return them. e.g.
 
     unique(char)[] fillWithSpaces(unique(char)s)
     {
         foreach(ref c;s) c = ' ';
         return s;
     }

I'm afraid that's not possible if you want strict type safety. A unique parameter effectively results in a local variable of type unique. Or, even worse, of non-unique type. In either case, the compiler doesn't have any chance to check what's happening and enforce type safety. Which is a must: implicit conversions must be safe. So the only way to return a unique result from a function is to dup or new or inline-construct directly within its return statement. Other return values are illegal. SnakE
Feb 01 2008
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 You need a way of expressing that functions can accept unique objects,
 and return them. e.g.

     unique(char)[] fillWithSpaces(unique(char)[]s)
     {
         foreach(ref c;s) c = ' ';
         return s;
     }

I'm afraid that's not possible if you want strict type safety

What I'm telling the compiler here is that the function's formal parameter, s, is unique at the callee site. Within the function, it stops being unique. Thus, within the function body, s is just a char[]. At the callee site, however, the compiler gets to complain if a non-unique type is passed to the function. (My example passed it the return value from new, so it was OK).
 So the only way to return a unique result from a function is to dup
 or new or inline-construct directly within its return statement.  Other
 return values are illegal.

Good point. It should have been return cast(unique)s;
Feb 01 2008
next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Janice Caron Wrote:
 What I'm telling the compiler here is that the function's formal
 parameter, s, is unique at the callee site. Within the function, it
 stops being unique. Thus, within the function body, s is just a
 char[]. At the callee site, however, the compiler gets to complain if
 a non-unique type is passed to the function.

On second thoughts, why would you want a function with a unique parameter ? Nothing casts to unique(), so that the caller is always required to dup() or whatever. Why force the user do it if you can always dup inside the function if you wish ? I think it only complicates the function usage. SnakE
 
 (My example passed it the return value from new, so it was OK).
 
 
 So the only way to return a unique result from a function is to dup
 or new or inline-construct directly within its return statement.  Other
 return values are illegal.

Good point. It should have been return cast(unique)s;

Feb 01 2008
parent Sergey Gromov <snake.scaly gmail.com> writes:
Janice Caron Wrote:

 On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 On second thoughts, why would you want a function with a unique
 parameter ?  Nothing casts to unique(), so that the caller is always
 required to dup() or whatever.

So that you can do string s; string t = f( g( h( i( j( k( s ))))));

Something tells me that this use case is very rare, but the dangers are great: every and each of those functions will include an explicit cast to unique. Can't prove the rariness though. The discussion loses its point unfortunately. The chances that the unique() gets into the language are very slim. SnakE
Feb 03 2008
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Janice Caron Wrote:
 So the only way to return a unique result from a function is to dup
 or new or inline-construct directly within its return statement.  Other
 return values are illegal.

Good point. It should have been return cast(unique)s;

The possibility to cast should still be there for complex cases where you can't/don't want to put data allocation into return statement but can guarantee its uniqueness. SnakE
Feb 01 2008
prev sibling next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 On second thoughts, why would you want a function with a unique
 parameter ?  Nothing casts to unique(), so that the caller is always
 required to dup() or whatever.

So that you can do string s; string t = f( g( h( i( j( k( s )))))); The functions f,g,h,i,j and k all return unique. The functions f,g,h,i and j (but not k) all accept a unique parameter. In this example, no duping or casting is required, because the temporary value is unique right the way through the chain.
 Why force the user do it if you can
 always dup inside the function if you wish ?

That would be five dups in the above example. The fact is, if don't mind duping, we don't need unique /at all/. e.g. string s; char[] t; char[] u = "hello".dup ~ s.dup ~ t; But if we're concerned to minimise allocations and duplications, then you need functions that /accept/ uniques, as well as functions that return them, for reasons demonstrated in the first example.
 I think it only complicates
 the function usage.

As with an other function in-contracts, yes. But misuse would be compiler checkable, so string s; string t = f( s ); (where f is as above) would be a compile error (cannot implicitly cast invariant(char)[] to unique(char)[]). The caller of f would have to change it to one of: string t = f( s.dup ); or string t = f( cast(unique)s ); In the latter case, of course, it would be the caller's responsibility to guarantee uniqueness. If the programmer is wrong, undefined behaviour results.
Feb 01 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 2/1/08, Sergey Gromov wrote:
 On second thoughts, why would you want a function with a unique
 parameter ?  Nothing casts to unique(), so that the caller is always
 required to dup() or whatever.

So that you can do string s; string t = f( g( h( i( j( k( s )))))); The functions f,g,h,i,j and k all return unique. The functions f,g,h,i and j (but not k) all accept a unique parameter. In this example, no duping or casting is required, because the temporary value is unique right the way through the chain.

Can't you just declare the functions as accepting mutable strings? Doesn't unique(char)[] implicitly cast to char[]? As Sergey says, this FORCES you to do a dup if you don't have a unique value. -Steve
Feb 03 2008
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 The possibility to cast should still be there for complex cases where you
 can't/don't want to put data allocation into return statement but can
 guarantee its uniqueness.

I disagree. For type safety, it should be required wherever a non-unique type is assigned to a unique type. By necessity, this must include function returns. Thus unique(char)[] f() { char[] s = whatever(); return cast(unique)s; } In this case, the cast to unique is unavoidable, since, if you omit it, you would be attempting to implicitly cast s (a char[]) to the return type, upon return. This cast is required for type safety, and justified because the code does guarantee uniqueness (because s goes out of scope on return, so at that point there will be no references to the data apart from the return value). It is almost impossible to /prove/ uniqueness, so it is reasonable to rely on programmer assertion (casts). What the compiler /can/ do, and do well, is ensure type safety.
Feb 01 2008
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 2/2/08, Janice Caron <caron800 googlemail.com> wrote:
 On 2/1/08, Sergey Gromov <snake.scaly gmail.com> wrote:
 The possibility to cast should still be there for complex cases where you
 can't/don't want to put data allocation into return statement but can
 guarantee its uniqueness.

I disagree.

Actually, I just realised I might be agreeing (not disagreeing) with you there! Sorry about that.
Feb 01 2008