www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Make a variable single-assignment?

reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
Hi,

Is there any way to make a variable single-assignment, regardless of its 
type? I.e.:

void foo()
{
     <some magical keyword?> int i = 0;
     i = 2; // Error: i cannot be reassigned
}

I realize const and immutable will do this, but they are transitive and 
infect the type, which I do *not* want. I simply want the variable to be 
single-assignment. Is it possible?

- Alex
Nov 21 2011
next sibling parent reply Trass3r <un known.com> writes:
Don't think so.
You could also wrap it in a struct with disabled opAssign, but this would  
also change the type.
Nov 21 2011
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 21-11-2011 15:48, Trass3r wrote:
 Don't think so.
 You could also wrap it in a struct with disabled opAssign, but this
 would also change the type.
Perhaps allowing 'final' on fields and locals would be a nice way to gain this effect... - Alex
Nov 21 2011
prev sibling next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 11/21/11 11:04 AM, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
Why do you want that?
Nov 21 2011
parent reply Kapps <Kapps NotValidEmail.com> writes:
For one reason, public fields that lack a set without having to create a 
backing field, followed by a bulky property. It does sound lazy, but 
when it's something you have to repeat many times, it gets annoying.

On 21/11/2011 9:43 AM, Ary Manzana wrote:
 On 11/21/11 11:04 AM, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
Why do you want that?
Nov 21 2011
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 21-11-2011 17:17, Kapps wrote:
 For one reason, public fields that lack a set without having to create a
 backing field, followed by a bulky property. It does sound lazy, but
 when it's something you have to repeat many times, it gets annoying.

 On 21/11/2011 9:43 AM, Ary Manzana wrote:
 On 11/21/11 11:04 AM, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
Why do you want that?
Exactly. In general, it would be useful for guaranteeing that you don't make an accidental assignment to a local or field. Just because you don't want it reassignable doesn't mean you don't want the *contents* reassignable, hence why transitive immutable is not acceptable. - Alex
Nov 21 2011
prev sibling parent Ary Manzana <ary esperanto.org.ar> writes:
On 11/21/11 1:17 PM, Kapps wrote:
 For one reason, public fields that lack a set without having to create a
 backing field, followed by a bulky property. It does sound lazy, but
 when it's something you have to repeat many times, it gets annoying.

 On 21/11/2011 9:43 AM, Ary Manzana wrote:
 On 11/21/11 11:04 AM, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
Why do you want that?
But that's different from what you asked. In your example "i" is a local variable. You want that for public fields... In Ruby you'd do: attr_reader :foo Isn't some standard mixin in D for that? (if the accesor method gets inline then the method call shouldn't affect the performance)
Nov 22 2011
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/21/2011 03:04 PM, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
How should that be possible without infecting the type? void main(){ <magical keyword> int i = 0; auto a = &i; *a = 2; // oops... }
Nov 21 2011
prev sibling next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 21/11/2011 15:04, Alex Rønne Petersen a écrit :
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
You can create a struct Final you could use as Final!(type) variable; Overloading opAssign should do whatever you need. I don't think adding to the core language what could ba achived with a nice abstraction should be done.
Nov 21 2011
prev sibling next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 21/11/2011 14:04, Alex Rønne Petersen wrote:
 Hi,

 Is there any way to make a variable single-assignment, regardless of its
 type? I.e.:

 void foo()
 {
 <some magical keyword?> int i = 0;
 i = 2; // Error: i cannot be reassigned
 }

 I realize const and immutable will do this, but they are transitive and
 infect the type, which I do *not* want. I simply want the variable to be
 single-assignment. Is it possible?

 - Alex
In D1 you could use final, in D2 your choices are either const, immutable, or as others have suggested, some sort of a wrapper. You could also use enum if you only want to work with primitive types and the value can be calculated at compile time. -- Robert http://octarineparrot.com/
Nov 21 2011
prev sibling parent reply Jesse Phillips <Jesse.K.Phillips gmail.com> writes:
What you are describing is Head Const, and is not available.

http://www.d-programming-language.org/const-faq.html#head-const

It will not be added as it doesn't provide any guarantees about the code that
is useful to the compiler. It can't be added to the existing system without
complicating the type system even more, which outweighs the benefits.

Tail Const, a more useful direction has been shafted for much the same reason.
There is however a pull request to add support into the compiler.
Nov 21 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
The only thing I can think of:

struct Once(T)
{
    this(T val)
    {
        i = val;
    }

    immutable T i;
    alias i this;
}

void main()
{
    Once!int i = 1;  // ok
    i = 4;  // ng
}

However it seems I've found a little hole in the system:

void foo(ref int x)
{
    x = 2;
}

void main()
{
    Once!int i = 1;  // ok
    foo(i);
    assert(i == 1);  // fail, changed to 2
}

Is this reported somewhere?
Nov 21 2011
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 21/11/2011 20:06, Jesse Phillips wrote:
 What you are describing is Head Const, and is not available.

 http://www.d-programming-language.org/const-faq.html#head-const

 It will not be added as it doesn't provide any guarantees about the code that
is useful
 to the compiler. It can't be added to the existing system without complicating
the type
 system even more, which outweighs the benefits.
<snip> Guarantees about the code don't need to be useful to the compiler - they can be just useful to the programmer. After all, this is the main point of DbC. And it doesn't need to be a full-fledged head const. At the simplest, a single-assignment variable could just be an rvalue - something of which the address cannot be taken and so the absence of head const becomes irrelevant. That said, it isn't much complexity to allow the address to be taken of such a thing final T data; auto ptr = &data; with the following rules: - if T is a value type, immutable(something)[] or immutable(something)*, then &data is an immutable(T)* - otherwise, &data is a const(T)*. Once upon a time there was const/final/invariant. What exactly did final do back then? Stewart.
Nov 30 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/01/2011 12:08 AM, Stewart Gordon wrote:
 On 21/11/2011 20:06, Jesse Phillips wrote:
 What you are describing is Head Const, and is not available.

 http://www.d-programming-language.org/const-faq.html#head-const

 It will not be added as it doesn't provide any guarantees about the
 code that is useful
 to the compiler.  It can't be added to the existing system without
 complicating the type
 system even more, which outweighs the benefits.
<snip> Guarantees about the code don't need to be useful to the compiler - they can be just useful to the programmer. After all, this is the main point of DbC. And it doesn't need to be a full-fledged head const. At the simplest, a single-assignment variable could just be an rvalue - something of which the address cannot be taken and so the absence of head const becomes irrelevant. That said, it isn't much complexity to allow the address to be taken of such a thing final T data; auto ptr = &data; with the following rules: - if T is a value type, immutable(something)[] or immutable(something)*, then &data is an immutable(T)* - otherwise, &data is a const(T)*. Once upon a time there was const/final/invariant. What exactly did final do back then? Stewart.
Here is some documentation from that time: http://www.digitalmars.com/d/final-const-invariant.html It did indeed mean head const, like in Java. I wonder why it was removed from the design though, it gives extra expressiveness at no cost. (maybe because then people will start pushing for readonly (tail const)? :))
Nov 30 2011