May 18, 2007
Walter Bright wrote:
> Bill Baxter wrote:
>> So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0?
> 
> Right - except that you won't be able to past string literals to them (as string literals will be const).

Ok.  Well that is actually a little nicer than C++ where every reference param you don't intend to modify needs to be marked 'const'.  Nicer in the sense that 'in' is shorter to type, at least, and in that it won't make Don Clugston cringe every time he has to type it.

What about method signatures that want 'this' to be an 'in' param. Trailing 'in' like C++?

   void aMethod() in {
       writefln(x, toString);
   }

Seems a little strange but I'm sure I'd get used to it.
I guess const would mean the same thing, though, since 'this' is already final and scope doesn't really apply.

--bb
May 18, 2007

Bill Baxter wrote:
> Walter Bright wrote:
>> Bill Baxter wrote:
>>> So if you don't use 'in' then the behavior will the the same as not using anything (or using 'in') in D1.0?
>>
>> Right - except that you won't be able to past string literals to them (as string literals will be const).
> 
> Ok.  Well that is actually a little nicer than C++ where every reference param you don't intend to modify needs to be marked 'const'.  Nicer in the sense that 'in' is shorter to type, at least, and in that it won't make Don Clugston cringe every time he has to type it.
> 
> What about method signatures that want 'this' to be an 'in' param. Trailing 'in' like C++?
> 
>    void aMethod() in {
>        writefln(x, toString);
>    }

Assuming they haven't changed, this would break pre-conditions.

> Seems a little strange but I'm sure I'd get used to it.
> I guess const would mean the same thing, though, since 'this' is already final and scope doesn't really apply.
> 
> --bb

Since this may have its uses, and so long as the meaning is very clear, I could live with 'const' in that position.

-- Chris Nicholson-Sauls
May 18, 2007
Note: I've read the reply where you clarified that this is to allow static things like string literals to be passed in.

Walter Bright wrote:
> This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them.
> 
> 'in' will mean 'scope const final', which means:
> 
> final - the parameter will not be reassigned within the function
> const - the function will not attempt to change the contents of what is
> referred to
> scope - the function will not keep a reference to the parameter's data
> that will persist beyond the scope of the function
> 
> For example:
> 
> int[] g;
> 
> void foo(in int[] a)
> {
>     a = [1,2];    // error, a is final
>     a[1] = 2;   // error, a is const
>     g = a;    // error, a is scope
> }
> Do not use 'in' if you wish to do any of these operations on a
> parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be
> backwards compatible.

Is final really necessary?  I can understand const and scope; but is it really a problem if the function rebinds the argument?  I mean, that shouldn't affect the calling code in the slightest, should it?

void foo(const scope int[] a)
{
    a = [1,2];
}

static bar = [3,4];
foo(bar);
assert( bar == [3,4] ); // This should still hold, right?

There are a few functions I've written which re-bind the argument as they run; the simplest examples being functions that process strings (effectively, it just loops until there's just an empty slice left).

Apart from that, I don't think there's any problems with doing this.  Oh well; I'll just have to declare an extra argument.  :P

> Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.

Actually, I was thinking of doing this anyway so that my argument lists are nice and symmetric (qualifiers on all of them, instead of just ref and out).  Now I have an excellent reason to do so other than my pedantic-ness. :)

One question: is there a keyword for "normal" arguments--for instance, I know that most variables are "auto" if you don't specify the storage class explicitly.  I can't imagine where it would be useful; just curious.

At any rate, looks spiffy.

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
May 18, 2007
Walter Bright pisze:
> This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them.
> 
> 'in' will mean 'scope const final', which means:
> 
> final - the parameter will not be reassigned within the function
> const - the function will not attempt to change the contents of what is referred to
> scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function
> 
> For example:
> 
> int[] g;
> 
> void foo(in int[] a)
> {
>     a = [1,2];    // error, a is final
>     a[1] = 2;   // error, a is const
>     g = a;    // error, a is scope
> }
> 
> Do not use 'in' if you wish to do any of these operations on a parameter. Using 'in' has no useful effect on D 1.0 code, so it'll be backwards compatible.
> 
> Adding in all those 'in's is tedious, as I'm finding out :-(, but I think the results will be worth the effort.

I want to ask about something opposite to above example...

Will it be possible to pass ownership of object? I mean that when you
pass object by reference to function/class/member variable you can still
modify this object from outside of function/class. It breaks
encapsulation in program.

Example:

import std.stdio;
public class TestX {
   char[] value;
   char[] toString() {
       return value;
   }
}
public class TestMain {
   TestX x;
}

void main(char[][] args) {
      TestX parameter = new TestX();
      parameter.value = "First assignment";

      TestMain tmain = new TestMain();
      tmain.x = parameter;

      parameter.value = "Second assignment";
      writefln(tmain.x);
}

Notice that tmain.x value has changed although I would like just to set
once, and have second assignment to parameter illegal... When using
setters and getters problem is even more visible....

How to achieve proper behavior with new final/const/invariant/scope??

Regards
Marcin Kuszczak
(aarti_pl)
May 18, 2007

Aarti_pl wrote:
> I want to ask about something opposite to above example...
> 
> Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program.
> 
> Example:
> 
> import std.stdio;
> public class TestX {
>    char[] value;
>    char[] toString() {
>        return value;
>    }
> }
> public class TestMain {
>    TestX x;
> }
> 
> void main(char[][] args) {
>       TestX parameter = new TestX();
>       parameter.value = "First assignment";
> 
>       TestMain tmain = new TestMain();
>       tmain.x = parameter;
> 
>       parameter.value = "Second assignment";
>       writefln(tmain.x);
> }
> 
> Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible....
> 
> How to achieve proper behavior with new final/const/invariant/scope??
> 
> Regards
> Marcin Kuszczak
> (aarti_pl)

I don't think the new const, final & invariant are going to help you any.  Basically, you seem to be complaining that reference semantics are... well, reference semantics.

That's like complaining that water is wet :P

There's a few things I can think of to get the behaviour you want.

1. Use a write-once setter for 'value'.  You can either create a nullable template, or use a flag to ensure external code can only set it once.

1.a. A "nicer" approach would be to set it in the constructor, and then either mark it "final" (with the new final), or only write a public getter function.

2. Use a struct instead; no references, no indirect changes.

3. Take a private copy of the object by writing a .dup method.

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
May 18, 2007
Daniel Keep pisze:
> 
> Aarti_pl wrote:
>> I want to ask about something opposite to above example...
>>
>> Will it be possible to pass ownership of object? I mean that when you
>> pass object by reference to function/class/member variable you can still
>> modify this object from outside of function/class. It breaks
>> encapsulation in program.
>>
>> Example:
>>
>> import std.stdio;
>> public class TestX {
>>    char[] value;
>>    char[] toString() {
>>        return value;
>>    }
>> }
>> public class TestMain {
>>    TestX x;
>> }
>>
>> void main(char[][] args) {
>>       TestX parameter = new TestX();
>>       parameter.value = "First assignment";
>>
>>       TestMain tmain = new TestMain();
>>       tmain.x = parameter;
>>
>>       parameter.value = "Second assignment";
>>       writefln(tmain.x);
>> }
>>
>> Notice that tmain.x value has changed although I would like just to set
>> once, and have second assignment to parameter illegal... When using
>> setters and getters problem is even more visible....
>>
>> How to achieve proper behavior with new final/const/invariant/scope??
>>
>> Regards
>> Marcin Kuszczak
>> (aarti_pl)
> 
> I don't think the new const, final & invariant are going to help you
> any.  Basically, you seem to be complaining that reference semantics
> are... well, reference semantics.
> 
> That's like complaining that water is wet :P
> 

The problem here is that current behavior breaks encapsulation - you can   change already passed value from outside of object, when contract is that you can set it only with setter. Imagine consequences in multithreaded application, when in the middle of function your data suddenly change... But also with single threaded application it can be real problem when you change referenced object by mistake.

So it is more like complaining that water is dry when it should be wet in fact :-)

I know that other languages also have same problem, but I think that D can do better.

> There's a few things I can think of to get the behaviour you want.
> 
> 1. Use a write-once setter for 'value'.  You can either create a
> nullable template, or use a flag to ensure external code can only set it
> once.
> 

Could you please give example? I don't know how to achieve this behavior with this method...

> 1.a. A "nicer" approach would be to set it in the constructor, and then
> either mark it "final" (with the new final), or only write a public getter function.

I think that rather invariant? Final will not disallow changing of referenced object. And I am afraid that it won't help anyway, it would be still possible to change value from outside... Using only getter and passing reference in constructor also doesn't help. You can still also modify variable from outside...

> 
> 2. Use a struct instead; no references, no indirect changes.
> 

Ok. I didn't think about it. But it is basically same as below, so please see comment below. Probably you have also problem when struct has references inside...


> 3. Take a private copy of the object by writing a .dup method.
> 

Yes that is possible solution, but program would be much faster (no unnecessary copies) with other solution...

> 	-- Daniel
> 

BR
Marcin Kuszczak
(aarti_pl)
May 18, 2007

Aarti_pl wrote:
> Daniel Keep pisze:
>>
>> Aarti_pl wrote:
>>> I want to ask about something opposite to above example...
>>>
>>> Will it be possible to pass ownership of object? I mean that when you pass object by reference to function/class/member variable you can still modify this object from outside of function/class. It breaks encapsulation in program.
>>>
>>> Example:
>>>
>>> import std.stdio;
>>> public class TestX {
>>>    char[] value;
>>>    char[] toString() {
>>>        return value;
>>>    }
>>> }
>>> public class TestMain {
>>>    TestX x;
>>> }
>>>
>>> void main(char[][] args) {
>>>       TestX parameter = new TestX();
>>>       parameter.value = "First assignment";
>>>
>>>       TestMain tmain = new TestMain();
>>>       tmain.x = parameter;
>>>
>>>       parameter.value = "Second assignment";
>>>       writefln(tmain.x);
>>> }
>>>
>>> Notice that tmain.x value has changed although I would like just to set once, and have second assignment to parameter illegal... When using setters and getters problem is even more visible....
>>>
>>> How to achieve proper behavior with new final/const/invariant/scope??
>>>
>>> Regards
>>> Marcin Kuszczak
>>> (aarti_pl)
>>
>> I don't think the new const, final & invariant are going to help you any.  Basically, you seem to be complaining that reference semantics are... well, reference semantics.
>>
>> That's like complaining that water is wet :P
>>
> 
> The problem here is that current behavior breaks encapsulation - you can
>   change already passed value from outside of object, when contract is
> that you can set it only with setter. Imagine consequences in
> multithreaded application, when in the middle of function your data
> suddenly change... But also with single threaded application it can be
> real problem when you change referenced object by mistake.
> 
> So it is more like complaining that water is dry when it should be wet in fact :-)
> 
> I know that other languages also have same problem, but I think that D can do better.

Ok: so the problem is that because D's class system doesn't have a concept of ownership, encapsulation can be violated.  That said, I've never seen an OO language that *did* have a concept of ownership, so I don't know what we could do to "fix" it :P

>> There's a few things I can think of to get the behaviour you want.
>>
>> 1. Use a write-once setter for 'value'.  You can either create a nullable template, or use a flag to ensure external code can only set it once.
>>
> 
> Could you please give example? I don't know how to achieve this behavior with this method...

class TestX
{
    private
    {
        char[] _value;
        bool _value_set = false;
    }

    char[] value(char[] v)
    {
        if( _value_set )
            assert(false, "cannot set value more than once!");

        _value = v;
        _value_set = true;
        return v;
    }

    char[] value()
    {
        return _value;
    }
}

>> 1.a. A "nicer" approach would be to set it in the constructor, and then either mark it "final" (with the new final), or only write a public getter function.
> 
> I think that rather invariant? Final will not disallow changing of referenced object. And I am afraid that it won't help anyway, it would be still possible to change value from outside... Using only getter and passing reference in constructor also doesn't help. You can still also modify variable from outside...

Since D2.0 hasn't been released yet, I don't know for certain, but I would hope it would be possible to create a final invariant member.  In this case, you can assign to it *only* during the constructor, and you can only assign something to it which will never change.

But then, I'm not sure if that would really work or not.

>>
>> 2. Use a struct instead; no references, no indirect changes.
>>
> 
> Ok. I didn't think about it. But it is basically same as below, so please see comment below. Probably you have also problem when struct has references inside...

Mmm.

>> 3. Take a private copy of the object by writing a .dup method.
>>
> 
> Yes that is possible solution, but program would be much faster (no unnecessary copies) with other solution...
> 
>>     -- Daniel
>>
> 
> BR
> Marcin Kuszczak
> (aarti_pl)

Here's another idea I had.  This *might* work come D2.0 (but again, I don't know for certain).  The idea here is that if we are passed a possibly mutable value, we take a private copy of it since this is the only way we can ensure no one else can mutate it.

BUT, if we are passed an invariant string, we just take a reference since the compiler is effectively guaranteeing that its contents will never, ever change.

Incidentally, I'm also assuming the whole "casting to const" thing works.

class TestX
{
    private
    {
        char[] _value;
    }

    // Copy v: no external mutations!
    char[] value(char[] v)
    {
        _value = v.dup;
        return v;
    }

    // Invariant, so a reference to it is fine
    char[] value(invariant char[] v)
    {
        _value = v;
        return v;
    }

    // Return const: no one calling this can modify it, even though they
    // have a reference!
    const char[] value()
    {
        return cast(const char[])_value;
    }
}

So maybe you will be able to get what you want.  Will be interesting to find out :)

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
May 18, 2007
Daniel Keep wrote:
>     // Invariant, so a reference to it is fine
>     char[] value(invariant char[] v)
>     {
>         _value = v;
>         return v;
>     }

But a mutable reference to it shouldn't be fine. So IMHO this should fail because you're trying to return an invariant char[] as a mutable char[]...

>     // Return const: no one calling this can modify it, even though they
>     // have a reference!
>     const char[] value()
>     {
>         return cast(const char[])_value;
>     }

I think that explicit cast should be unneeded. Mutable to const should be possible through an implicit cast..
May 18, 2007
Walter Bright wrote:
> Manfred Nowak wrote:
>> Walter Bright wrote
>>
>>> Frank Benoit wrote:
>>>> int[] g;
>>>> void foo(in int[] a){
>>>>     g = a.dup;    // allowed?
>>>> }
>>> Yes.
>>
>> The `.dup'ing an array where a cell contains a reference to the array is allowed too?
>>
>> alias void* T;
>> T[] a;
>> void main(){
>>   T[] g; g.length= 1;
>>   g[0]=&g;
>>   void f( in T[] p){
>>     a= p.dup;
>>   }
>> }
>>
>> That would contradict the given rule.
> 
> I don't understand. What rule is being violated, and how?

I think he is concerning to the scope rule. When 'f' gets called with 'g' as param, then 'a' has implicitly a reference to 'g', namely in a[0]. This would be a violation of the scope rule.

-- Regards
Manuel
May 18, 2007
Walter Bright wrote:
> This is coming for the D 2.0 beta, and it will need some source code changes. Specifically, for function parameters that are arrays or pointers, start using 'in' for them.
> 
> 'in' will mean 'scope const final', which means:
> 
> final - the parameter will not be reassigned within the function
> const - the function will not attempt to change the contents of what is referred to
> scope - the function will not keep a reference to the parameter's data that will persist beyond the scope of the function

Looks great, although somewhat overwhelming for a newcomer.
Will functions be overloadable on all of these?

Anyway, it sounds as though we'll see 2.0 beta 1 before DMD 1.15 ?