July 13, 2005
"Dave" <Dave_member@pathlink.com> wrote in message news:db3pfk$rje$1@digitaldaemon.com...
> In article <db3g4b$jdj$1@digitaldaemon.com>, Andrew Fedoniouk says...
>>
>>
>>"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:db3ejf$i7u$1@digitaldaemon.com...
>>>> A variation on this is to just use the 'final' keyword and forget about
>>>> marking output values. So an input parameter, local variable or field
>>>> marked 'final' means "deep immutable" in Walter's sense for the
>>>> lifetime
>>>> of that variable. A final variable of array, pointer or reference type
>>>> can be assigned new values but the contents of the array, pointer or
>>>> reference (recursively) cannot change.
>>>> void foo(final char[] str); // Walter's idea with 'final' instead of
>>>> 'in'
>>>> final char[] str = "blah"; // str contents are read-only
>>>> struct Foo { final char[] str; }
>>>
>>> It occured to me a benefit of using a keyword other than 'in' is that it
>>> allows you to write
>>> void foo(final inout BigHonkinStruct x)
>>> to get both pass-by-reference and immutability.
>>>
>>
>>Yep, in/out is just byval/byref and has nothing common with constness.
>>
>>BTW: You've provided example which has little sense :)
>>
>>void foo(final inout BigHonkinStruct x)
>>
>>As 'inout' tells us - information will flow in and out
>>but foo cannot modify x so it is only 'in' in fact.
>
> With Walter's 'explicit in' idea, then having 'inout' "double" as a way to
> pass
> a byval variable (greater in size than a machine word more efficiently)
> wouldn't
> be needed - the compiler could easily decide that and just do the
> optimization.

It can? How about an example like
  struct BigHonkinStruct { int a; } //ok not so honkin but you get the idea
  void foo(in BigHonkinStruct x, void delegate() cb) {
    int old = x.a;
    cb();
    assert( x.a == old );
  }
  void bar() {
    BigHonkinStruct y;
    void baz(){y.a = 10;}
    foo(y,&baz);
  }
Pass-by-value semantics means that the x inside foo is (semantically) a copy
of y so the function bar must be able to change y whenever it wants and it
has no impact on x. Hence you can't pass y by reference to foo even though
it is declared as 'explicit in'.
Are you thinking of something else? I might be mis-reading your point.

> This can be more efficient with something even as small as a long or a
> double
> prec. fp var. on 32 bit machines.
>
> so instead of
>
> 'void foo(final inout BigHonkinStruct x)'
>
> or
>
> 'void foo(in BigHonkinStruct*# x)'
>
> it would just be:
>
> 'void foo(in BigHonkinStruct x)'
>
> With that in mind, I *still* say both 'implicit in' and 'explicit in'
> should be
> changed to act like Walter's proposal because that is what is expected in
> 99% of
> the cases anyhow, and the other 1% is when the programmer forgot the 'out'
> or
> 'inout' with byref vars.
>
> If the compiler detects even the simple cases, then most of the remaining
> 1%
> wouldn't compile anyway and the programmer would simply have to change it
> to
> 'out' or 'inout' as it should have been in the first place <g>.
>
> The other issue with using 'inout' as a substitute for '&' is that you
> can't
> pass a temporary:
>
> struct S { int x, y, z; }
> S initAnS(int x, int y, int z) { S s; s.x = x, s.y = y, s.z = z; return
> s; }
> int foo(inout S s) { return s.x * s.y * s.z; }
>
> void main()
> {
> int i = foo(initAnS(10,20,30)); // Error: initAnS(10,20,30) is not an
> lvalue
> }
>
> The optimizations aren't my biggest deal though -- IMHO, the param.
> storage
> specifiers should mean what they say or imply, it's just that the
> semantics of
> 'in' (both implicit and explicit) need to change to be like the const or
> 'readonly' vars. that we've all been talking about and then perhaps (if
> needed)
> a contrary keyword like 'mutable' could be added.
>
> Will an 'immutable implicit in' be confusing for C/++ people at first?
> Perhaps,
> but not after the compiler spits out an error for the first few trivial
> cases -
> then it will just be "Ok, if I want to modify a function parameter, I have
> to
> specify 'out' or 'inout' or make a copy.
>
> Maybe it won't be confusing at all because in C-land they have to use a
> pointer
> and in C++ land they have to use '&' so maybe making 'implicit in' act
> like a
> byval for even byref parameters will come more naturally and it's the VB,
> C# and
> Java people wo will be confused at first.
>
> I think Walter had it right on his first pass here:
>
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096
>
> - Dave
>
>

IMHO 'implicit in' forcing immutability would be a big language change from C/C++/Java/C#. Especially if it were easy to break the immutability contract without the compiler throwing fits. I agree if implicit in were changed then a 'mutable' keyword would be needed to avoid having to use inout/out and force lvalues. I also hope it wouldn't encourage people to use global variables in order to avoid passing state around and micro-managing the mutability.


July 13, 2005
"Dave" <Dave_member@pathlink.com> wrote in message news:db3pfk$rje$1@digitaldaemon.com...
> In article <db3g4b$jdj$1@digitaldaemon.com>, Andrew Fedoniouk says...
>>
>>
>>"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:db3ejf$i7u$1@digitaldaemon.com...
>>>> A variation on this is to just use the 'final' keyword and forget about
>>>> marking output values. So an input parameter, local variable or field
>>>> marked 'final' means "deep immutable" in Walter's sense for the
>>>> lifetime
>>>> of that variable. A final variable of array, pointer or reference type
>>>> can be assigned new values but the contents of the array, pointer or
>>>> reference (recursively) cannot change.
>>>> void foo(final char[] str); // Walter's idea with 'final' instead of
>>>> 'in'
>>>> final char[] str = "blah"; // str contents are read-only
>>>> struct Foo { final char[] str; }
>>>
>>> It occured to me a benefit of using a keyword other than 'in' is that it
>>> allows you to write
>>> void foo(final inout BigHonkinStruct x)
>>> to get both pass-by-reference and immutability.
>>>
>>
>>Yep, in/out is just byval/byref and has nothing common with constness.
>>
>>BTW: You've provided example which has little sense :)
>>
>>void foo(final inout BigHonkinStruct x)
>>
>>As 'inout' tells us - information will flow in and out
>>but foo cannot modify x so it is only 'in' in fact.
>
> With Walter's 'explicit in' idea, then having 'inout' "double" as a way to
> pass
> a byval variable (greater in size than a machine word more efficiently)
> wouldn't
> be needed - the compiler could easily decide that and just do the
> optimization.
> This can be more efficient with something even as small as a long or a
> double
> prec. fp var. on 32 bit machines.
>
> so instead of
>
> 'void foo(final inout BigHonkinStruct x)'
>
> or
>
> 'void foo(in BigHonkinStruct*# x)'
>
> it would just be:
>
> 'void foo(in BigHonkinStruct x)'
>
> With that in mind, I *still* say both 'implicit in' and 'explicit in'
> should be
> changed to act like Walter's proposal because that is what is expected in
> 99% of
> the cases anyhow, and the other 1% is when the programmer forgot the 'out'
> or
> 'inout' with byref vars.
>
> If the compiler detects even the simple cases, then most of the remaining
> 1%
> wouldn't compile anyway and the programmer would simply have to change it
> to
> 'out' or 'inout' as it should have been in the first place <g>.
>
> The other issue with using 'inout' as a substitute for '&' is that you
> can't
> pass a temporary:
>
> struct S { int x, y, z; }
> S initAnS(int x, int y, int z) { S s; s.x = x, s.y = y, s.z = z; return
> s; }
> int foo(inout S s) { return s.x * s.y * s.z; }
>
> void main()
> {
> int i = foo(initAnS(10,20,30)); // Error: initAnS(10,20,30) is not an
> lvalue
> }
>
> The optimizations aren't my biggest deal though -- IMHO, the param.
> storage
> specifiers should mean what they say or imply, it's just that the
> semantics of
> 'in' (both implicit and explicit) need to change to be like the const or
> 'readonly' vars. that we've all been talking about and then perhaps (if
> needed)
> a contrary keyword like 'mutable' could be added.
>
> Will an 'immutable implicit in' be confusing for C/++ people at first?
> Perhaps,
> but not after the compiler spits out an error for the first few trivial
> cases -
> then it will just be "Ok, if I want to modify a function parameter, I have
> to
> specify 'out' or 'inout' or make a copy.
>
> Maybe it won't be confusing at all because in C-land they have to use a
> pointer
> and in C++ land they have to use '&' so maybe making 'implicit in' act
> like a
> byval for even byref parameters will come more naturally and it's the VB,
> C# and
> Java people wo will be confused at first.
>
> I think Walter had it right on his first pass here:
>
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096
>
> - Dave
>

Such explicit 'in' needs 'mutable' designators for all methods allowing
to change state of structure/class. This is the main concern with 'const' in
C++

Again 'in' is a direction of information flow. Please don't mix them with
constantess.
Through 'in' you can pass both mutable reference and immutable reference.
'in' just means that changes of reference value itself will not be visible
for a caller - it is far from "this pointer is only for reading".



July 13, 2005
In article <db3so3$u58$1@digitaldaemon.com>, Ben Hinkle says...
>
>
>"Dave" <Dave_member@pathlink.com> wrote in message news:db3pfk$rje$1@digitaldaemon.com...
>> In article <db3g4b$jdj$1@digitaldaemon.com>, Andrew Fedoniouk says...
>>>
>>>
>>>"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:db3ejf$i7u$1@digitaldaemon.com...
>>>>> A variation on this is to just use the 'final' keyword and forget about
>>>>> marking output values. So an input parameter, local variable or field
>>>>> marked 'final' means "deep immutable" in Walter's sense for the
>>>>> lifetime
>>>>> of that variable. A final variable of array, pointer or reference type
>>>>> can be assigned new values but the contents of the array, pointer or
>>>>> reference (recursively) cannot change.
>>>>> void foo(final char[] str); // Walter's idea with 'final' instead of
>>>>> 'in'
>>>>> final char[] str = "blah"; // str contents are read-only
>>>>> struct Foo { final char[] str; }
>>>>
>>>> It occured to me a benefit of using a keyword other than 'in' is that it
>>>> allows you to write
>>>> void foo(final inout BigHonkinStruct x)
>>>> to get both pass-by-reference and immutability.
>>>>
>>>
>>>Yep, in/out is just byval/byref and has nothing common with constness.
>>>
>>>BTW: You've provided example which has little sense :)
>>>
>>>void foo(final inout BigHonkinStruct x)
>>>
>>>As 'inout' tells us - information will flow in and out
>>>but foo cannot modify x so it is only 'in' in fact.
>>
>> With Walter's 'explicit in' idea, then having 'inout' "double" as a way to
>> pass
>> a byval variable (greater in size than a machine word more efficiently)
>> wouldn't
>> be needed - the compiler could easily decide that and just do the
>> optimization.
>
>It can? How about an example like
>  struct BigHonkinStruct { int a; } //ok not so honkin but you get the idea
>  void foo(in BigHonkinStruct x, void delegate() cb) {
>    int old = x.a;
>    cb();
>    assert( x.a == old );
>  }
>  void bar() {
>    BigHonkinStruct y;
>    void baz(){y.a = 10;}
>    foo(y,&baz);
>  }
>Pass-by-value semantics means that the x inside foo is (semantically) a copy
>of y so the function bar must be able to change y whenever it wants and it
>has no impact on x. Hence you can't pass y by reference to foo even though
>it is declared as 'explicit in'.
>Are you thinking of something else? I might be mis-reading your point.
>

What I meant by 'the compiler could easily decide that' is that the compiler could detect whether or not it would be worth it to pass byref or not, not if the compiler could detect 'immutability' cases like that above.

I know what pass byval semantics do now <g> Part of what I was getting at is basically that the semantics would have to change -- perhaps get rid of the implicit byval/byref distinction based on what the parameter type is, CT error on the 'easy' cases where 'immutability' is broken for in params and rely on the idea of Walter's 'immutability contract'. It would be one of those areas where D is just different.

Continuing the byval/byref though, one of the things that was confusing to people going to Java (where 'everything is an object') is that int 'objects' are passed byval whereas some UDT 'object' is passed byref. So, they ended up modifying an int param in a function and it wouldn't break their code but when they passed a UDT and modified a member of the UDT, it would. This is probably the same with D, expecially for newbies.

If you got rid of the implicit byval/byref distinction so people just knew that if you modify 'in' parameter 'x' inside a function it may have side-effects (regardless of the type) then they wouldn't rely on a parameter being byval. This 'mindset' would also help to get rid of hard to find bugs caused by generic programming where the same template functions do something to a type whether or not it resides on the stack or the heap, for example.

>> This can be more efficient with something even as small as a long or a
>> double
>> prec. fp var. on 32 bit machines.
>>
>> so instead of
>>
>> 'void foo(final inout BigHonkinStruct x)'
>>
>> or
>>
>> 'void foo(in BigHonkinStruct*# x)'
>>
>> it would just be:
>>
>> 'void foo(in BigHonkinStruct x)'
>>
>> With that in mind, I *still* say both 'implicit in' and 'explicit in'
>> should be
>> changed to act like Walter's proposal because that is what is expected in
>> 99% of
>> the cases anyhow, and the other 1% is when the programmer forgot the 'out'
>> or
>> 'inout' with byref vars.
>>
>> If the compiler detects even the simple cases, then most of the remaining
>> 1%
>> wouldn't compile anyway and the programmer would simply have to change it
>> to
>> 'out' or 'inout' as it should have been in the first place <g>.
>>
>> The other issue with using 'inout' as a substitute for '&' is that you
>> can't
>> pass a temporary:
>>
>> struct S { int x, y, z; }
>> S initAnS(int x, int y, int z) { S s; s.x = x, s.y = y, s.z = z; return
>> s; }
>> int foo(inout S s) { return s.x * s.y * s.z; }
>>
>> void main()
>> {
>> int i = foo(initAnS(10,20,30)); // Error: initAnS(10,20,30) is not an
>> lvalue
>> }
>>
>> The optimizations aren't my biggest deal though -- IMHO, the param.
>> storage
>> specifiers should mean what they say or imply, it's just that the
>> semantics of
>> 'in' (both implicit and explicit) need to change to be like the const or
>> 'readonly' vars. that we've all been talking about and then perhaps (if
>> needed)
>> a contrary keyword like 'mutable' could be added.
>>
>> Will an 'immutable implicit in' be confusing for C/++ people at first?
>> Perhaps,
>> but not after the compiler spits out an error for the first few trivial
>> cases -
>> then it will just be "Ok, if I want to modify a function parameter, I have
>> to
>> specify 'out' or 'inout' or make a copy.
>>
>> Maybe it won't be confusing at all because in C-land they have to use a
>> pointer
>> and in C++ land they have to use '&' so maybe making 'implicit in' act
>> like a
>> byval for even byref parameters will come more naturally and it's the VB,
>> C# and
>> Java people wo will be confused at first.
>>
>> I think Walter had it right on his first pass here:
>>
>> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/26096
>>
>> - Dave
>>
>>
>
>IMHO 'implicit in' forcing immutability would be a big language change from C/C++/Java/C#. Especially if it were easy to break the immutability contract without the compiler throwing fits. I agree if implicit in were changed then a 'mutable' keyword would be needed to avoid having to use inout/out and force lvalues. I also hope it wouldn't encourage people to use global variables in order to avoid passing state around and micro-managing the mutability.
>


July 13, 2005
On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
> Such explicit 'in' needs 'mutable' designators for all methods allowing
> to change state of structure/class. This is the main concern with 'const' in C++
>
> Again 'in' is a direction of information flow. Please don't mix them with
> constantess.
> Through 'in' you can pass both mutable reference and immutable reference.
> 'in' just means that changes of reference value itself will not be visible
> for a caller - it is far from "this pointer is only for reading".

There are several ways you might want to pass a parameter:

1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.

2. copy. you want a copy that you can modify inside the function for the duration of the function.

3. refrence. you want the actual variable so that you can modify it inside the function.

Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.
July 13, 2005
On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz> wrote:
> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>> Such explicit 'in' needs 'mutable' designators for all methods allowing
>> to change state of structure/class. This is the main concern with 'const' in C++
>>
>> Again 'in' is a direction of information flow. Please don't mix them with
>> constantess.
>> Through 'in' you can pass both mutable reference and immutable reference.
>> 'in' just means that changes of reference value itself will not be visible
>> for a caller - it is far from "this pointer is only for reading".
>
> There are several ways you might want to pass a parameter:
>
> 1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.
>
> 2. copy. you want a copy that you can modify inside the function for the duration of the function.
>
> 3. refrence. you want the actual variable so that you can modify it inside the function.
>
> Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.

Sorry, by OP I meant "Dave".

I realise in, out, and inout currently specify how to pass a variable, but, in they also allow the programmer to declare how they intend to use the variable. So while technically they do not declare constness or similar they imply it in cases.

I can't really see a point in ever passing byval, we can instead pass byX (compilers choice) and explicitly copy those variables we need a copy of. Of course in a case like:

void foo(int i) { int j = i; }

where the compier will pass byvalue (as it's more efficient) and we immediately copy it, making a 2nd copy (no different to how it is today, but), the compiler could optimise this so that the only copy made was 'j', couldn't it?

Regan
July 13, 2005
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opstvgxmlz23k2f5@nrage.netwin.co.nz...
> On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz> wrote:
>> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>>> Such explicit 'in' needs 'mutable' designators for all methods allowing to change state of structure/class. This is the main concern with 'const' in C++
>>>
>>> Again 'in' is a direction of information flow. Please don't mix them
>>> with
>>> constantess.
>>> Through 'in' you can pass both mutable reference and immutable
>>> reference.
>>> 'in' just means that changes of reference value itself will not be
>>> visible
>>> for a caller - it is far from "this pointer is only for reading".
>>
>> There are several ways you might want to pass a parameter:
>>
>> 1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.
>>
>> 2. copy. you want a copy that you can modify inside the function for the duration of the function.
>>
>> 3. refrence. you want the actual variable so that you can modify it inside the function.
>>
>> Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.
>
> Sorry, by OP I meant "Dave".
>
> I realise in, out, and inout currently specify how to pass a variable, but, in they also allow the programmer to declare how they intend to use the variable. So while technically they do not declare constness or similar they imply it in cases.
>
> I can't really see a point in ever passing byval, we can instead pass byX (compilers choice) ...

Are we in gambling business or what?
Compilation and optimization based on gentlemen's agreements, intentions and
brotherhood of men ...
I like the abstract idea but may I ask for something more determinstic in
this pub?


> ... and explicitly copy those variables we need a copy of.  Of course in a case like:
>
> void foo(int i) { int j = i; }
>
> where the compier will pass byvalue (as it's more efficient) and we immediately copy it, making a 2nd copy (no different to how it is today, but), the compiler could optimise this so that the only copy made was 'j', couldn't it?
>
> Regan


July 13, 2005
On Wed, 13 Jul 2005 16:08:08 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opstvgxmlz23k2f5@nrage.netwin.co.nz...
>> On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz>
>> wrote:
>>> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk
>>> <news@terrainformatica.com> wrote:
>>>> Such explicit 'in' needs 'mutable' designators for all methods allowing
>>>> to change state of structure/class. This is the main concern with
>>>> 'const' in C++
>>>>
>>>> Again 'in' is a direction of information flow. Please don't mix them
>>>> with
>>>> constantess.
>>>> Through 'in' you can pass both mutable reference and immutable
>>>> reference.
>>>> 'in' just means that changes of reference value itself will not be
>>>> visible
>>>> for a caller - it is far from "this pointer is only for reading".
>>>
>>> There are several ways you might want to pass a parameter:
>>>
>>> 1. read only. the mechanism of passing copy/byref isn't important you
>>> just want a variable you can only read from. the compiler could
>>> essentially decide to pass this in any way it likes. if passed byref it
>>> would have to enforce read only.
>>>
>>> 2. copy. you want a copy that you can modify inside the function for the
>>> duration of the function.
>>>
>>> 3. refrence. you want the actual variable so that you can modify it
>>> inside the function.
>>>
>>> Right now D has 2 and 3 covered but not 1. The OP is suggesting
>>> something that makes #1 possible, and changes #2 so it is only possible
>>> if the programmer codes it explicitly. #3 remains the same.
>>
>> Sorry, by OP I meant "Dave".
>>
>> I realise in, out, and inout currently specify how to pass a variable,
>> but, in they also allow the programmer to declare how they intend to use
>> the variable. So while technically they do not declare constness or
>> similar they imply it in cases.
>>
>> I can't really see a point in ever passing byval, we can instead pass byX
>> (compilers choice) ...
>
> Are we in gambling business or what?

No, because the point you're missing is that it doesn't matter at all how it passes it if you only read from it, does it? (ignoring efficiency for a sec, as that is how the compiler will choose to pass it)

> Compilation and optimization based on gentlemen's agreements, intentions and brotherhood of men ...
> I like the abstract idea but may I ask for something more determinstic in
> this pub?

When? Is there any situation where you only want to read from a variable and you must have it passed by value, or by reference?

Regan
July 14, 2005
In article <opstvgxmlz23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz> wrote:
>> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>>> Such explicit 'in' needs 'mutable' designators for all methods allowing to change state of structure/class. This is the main concern with 'const' in C++
>>>
>>> Again 'in' is a direction of information flow. Please don't mix them
>>> with
>>> constantess.
>>> Through 'in' you can pass both mutable reference and immutable
>>> reference.
>>> 'in' just means that changes of reference value itself will not be
>>> visible
>>> for a caller - it is far from "this pointer is only for reading".
>>
>> There are several ways you might want to pass a parameter:
>>
>> 1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.
>>
>> 2. copy. you want a copy that you can modify inside the function for the duration of the function.
>>
>> 3. refrence. you want the actual variable so that you can modify it inside the function.
>>
>> Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.
>
>Sorry, by OP I meant "Dave".
>
>I realise in, out, and inout currently specify how to pass a variable, but, in they also allow the programmer to declare how they intend to use the variable. So while technically they do not declare constness or similar they imply it in cases.
>
>I can't really see a point in ever passing byval, we can instead pass byX (compilers choice) and explicitly copy those variables we need a copy of.

Exactly..

>Of course in a case like:
>
>void foo(int i) { int j = i; }
>
>where the compier will pass byvalue (as it's more efficient) and we immediately copy it, making a 2nd copy (no different to how it is today, but), the compiler could optimise this so that the only copy made was 'j', couldn't it?
>

IMHO, it wouldn't matter in a good majority of cases where an int (or a long on 64 bit machines) is passed 'in' anyway because when a simple var. is passed in like that it is usually only part of the rvalue for expressions like:

int x = i * 10;

and not modified (at least in my experience) so the programmer wouldn't usually feel compelled to make a modifiable copy anyhow.

Regardless, I just ran a quick test with the dmd compiler. The optimization you speak of is apparently already done (dead assignment elimination, I think).

Compiled w/ either '-version=nocopy' or not (and -O -inline -release) this actually results in the exact same assembly code:

#import std.stdio;

#void main()
#{
#    int sum = 0;
#    for(int i = 0, j = 0; i < 1000000000; i++, j--)
#    {
#        sum += foo(i,j);
#    }
#    writefln(sum);
#}

#int foo(int x, int y)
#{
#  version(nocopy)
#  {
#    return x++ + y--;
#  }
#  else
#  {
#    int x2 = x, y2 = y;
#    return x2++ + y2--;
#  }
#}

>Regan


July 14, 2005
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opstvj1qwe23k2f5@nrage.netwin.co.nz...
> On Wed, 13 Jul 2005 16:08:08 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>> "Regan Heath" <regan@netwin.co.nz> wrote in message news:opstvgxmlz23k2f5@nrage.netwin.co.nz...
>>> On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz> wrote:
>>>> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>>>>> Such explicit 'in' needs 'mutable' designators for all methods
>>>>> allowing
>>>>> to change state of structure/class. This is the main concern with
>>>>> 'const' in C++
>>>>>
>>>>> Again 'in' is a direction of information flow. Please don't mix them
>>>>> with
>>>>> constantess.
>>>>> Through 'in' you can pass both mutable reference and immutable
>>>>> reference.
>>>>> 'in' just means that changes of reference value itself will not be
>>>>> visible
>>>>> for a caller - it is far from "this pointer is only for reading".
>>>>
>>>> There are several ways you might want to pass a parameter:
>>>>
>>>> 1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.
>>>>
>>>> 2. copy. you want a copy that you can modify inside the function for
>>>> the
>>>> duration of the function.
>>>>
>>>> 3. refrence. you want the actual variable so that you can modify it inside the function.
>>>>
>>>> Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.
>>>
>>> Sorry, by OP I meant "Dave".
>>>
>>> I realise in, out, and inout currently specify how to pass a variable, but, in they also allow the programmer to declare how they intend to use the variable. So while technically they do not declare constness or similar they imply it in cases.
>>>
>>> I can't really see a point in ever passing byval, we can instead pass
>>> byX
>>> (compilers choice) ...
>>
>> Are we in gambling business or what?
>
> No, because the point you're missing is that it doesn't matter at all how it passes it if you only read from it, does it? (ignoring efficiency for a sec, as that is how the compiler will choose to pass it)

Oh, no, please... this horse is dead already...

"1. ... if passed byref it would have to enforce read only."

How the hell compiler will enforce it? This is the whole point.

Check can be made in runtime by running GC-like cycle against this variable. This is the only non-intrusive way as far as I know.  Do you like it?

Andrew.

>
>> Compilation and optimization based on gentlemen's agreements, intentions
>> and brotherhood of men ...
>> I like the abstract idea but may I ask for something more determinstic in
>> this pub?
>
> When? Is there any situation where you only want to read from a variable and you must have it passed by value, or by reference?
>
> Regan


July 14, 2005
In article <db4umv$1spa$1@digitaldaemon.com>, Andrew Fedoniouk says...
>
>
>"Regan Heath" <regan@netwin.co.nz> wrote in message news:opstvj1qwe23k2f5@nrage.netwin.co.nz...
>> On Wed, 13 Jul 2005 16:08:08 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>>> "Regan Heath" <regan@netwin.co.nz> wrote in message news:opstvgxmlz23k2f5@nrage.netwin.co.nz...
>>>> On Thu, 14 Jul 2005 09:56:02 +1200, Regan Heath <regan@netwin.co.nz> wrote:
>>>>> On Wed, 13 Jul 2005 13:29:24 -0700, Andrew Fedoniouk <news@terrainformatica.com> wrote:
>>>>>> Such explicit 'in' needs 'mutable' designators for all methods
>>>>>> allowing
>>>>>> to change state of structure/class. This is the main concern with
>>>>>> 'const' in C++
>>>>>>
>>>>>> Again 'in' is a direction of information flow. Please don't mix them
>>>>>> with
>>>>>> constantess.
>>>>>> Through 'in' you can pass both mutable reference and immutable
>>>>>> reference.
>>>>>> 'in' just means that changes of reference value itself will not be
>>>>>> visible
>>>>>> for a caller - it is far from "this pointer is only for reading".
>>>>>
>>>>> There are several ways you might want to pass a parameter:
>>>>>
>>>>> 1. read only. the mechanism of passing copy/byref isn't important you just want a variable you can only read from. the compiler could essentially decide to pass this in any way it likes. if passed byref it would have to enforce read only.
>>>>>
>>>>> 2. copy. you want a copy that you can modify inside the function for
>>>>> the
>>>>> duration of the function.
>>>>>
>>>>> 3. refrence. you want the actual variable so that you can modify it inside the function.
>>>>>
>>>>> Right now D has 2 and 3 covered but not 1. The OP is suggesting something that makes #1 possible, and changes #2 so it is only possible if the programmer codes it explicitly. #3 remains the same.
>>>>
>>>> Sorry, by OP I meant "Dave".
>>>>
>>>> I realise in, out, and inout currently specify how to pass a variable, but, in they also allow the programmer to declare how they intend to use the variable. So while technically they do not declare constness or similar they imply it in cases.
>>>>
>>>> I can't really see a point in ever passing byval, we can instead pass
>>>> byX
>>>> (compilers choice) ...
>>>
>>> Are we in gambling business or what?
>>
>> No, because the point you're missing is that it doesn't matter at all how it passes it if you only read from it, does it? (ignoring efficiency for a sec, as that is how the compiler will choose to pass it)
>
>Oh, no, please... this horse is dead already...
>
>"1. ... if passed byref it would have to enforce read only."
>
>How the hell compiler will enforce it? This is the whole point.
>

Basically, what I (and I think Regan) have in mind is that the compiler would enforce 'in' params. the same way a C++ compiler would enforce "const [type]" or "const [type] &" params. for analogous types in C++. That way you would get 'C++ const' functionality for params by default (implicit in params would act like Walter's 'explicit in' proposal too).

The difference would be that in D, although it wouldn't be enforced "deeply" by the compiler (because as you've pointed out many times that isn't practical), implicit and explicit 'in' would carry a 'gentlemen's agreement' that these are immutable so that 'in' could have semantic value.

I think that a pretty high majority of the "oops" cases would be caught by the "const [type] &" checks analogous to what a good C++ compiler does and then the programmer would have to change the param to out or inout or explicitly make a copy. For the other cases it would be undefined behaviour because the 'contract' is being broken.

The reasons this makes sense to me are this:

- It would cover most cases and therefore eliminate peppering function
declarations with type/storage modifiers.
- It wouldn't add anything to D syntax.
- It would provide (and enforce) the same C++ const type functionality that it
seems a lot of people in this discussion have been referring to.
- It would seperate how a parameter is passed (byref or byval) from what type it
is (struct, class, array, primitive, pointer) so a D programmer could stop
thinking about that and the compiler could do what makes the most sense when
passing vars. w/o the programmer having to tack '&' onto every param.
- Since 'implicit in' parameters are probably and will stay a good majority, the
compiler could take advantage of the contract to produce better code inside the
function for expressions involving the 'in' params.
- It would reinforce the idea that the 'direction' of a param. should coincide
with whether or not it is modified inside a function. For example, when passing
an instance of a class 'in', you can now (legally) directly modify primitive
members of that class and those modifications live past the lifetime of that
function call. However, passing an instance of a struct modifying the member
won't in many cases, which just seems contradictory to me:

class C { int i = 10; }
struct S { int i = 10; }

template foo(T) { void foo(in T o) { o.i = 20; } }

void main()
{
C c = new C;
printf("%d\n",c.i);
foo!(C)(c);
printf("%d\n",c.i);
S s;
printf("%d\n",s.i);
foo!(S)(s);
printf("%d\n",s.i);
}

One of Walter's goals is to make the compiler much easier to implement than C++, and I'm not sure if doing const param. checks would be one of the things that would severly impact achieving that goal.

It *would* require a new mindset, but I think now's the time to try it out. It would be interesting to add (just) the C++-like const checks to the next build and have everyone run their code through it to see how much code it breaks (as in won't compile) and then regress if it causes too many problems. If it isn't too much effort for Walter, I think it'd be worth a try - this may well 'break' less code than changing AA's (as in the other current discussion) would.

>
>Check can be made in runtime by running GC-like cycle against this variable. This is the only non-intrusive way as far as I know.  Do you like it?
>
>Andrew.
>
>>
>>> Compilation and optimization based on gentlemen's agreements, intentions
>>> and brotherhood of men ...
>>> I like the abstract idea but may I ask for something more determinstic in
>>> this pub?
>>
>> When? Is there any situation where you only want to read from a variable and you must have it passed by value, or by reference?
>>
>> Regan
>
>