www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Static attributes & immutability, static attributes seen from instances

reply bearophile <bearophileHUGS lycos.com> writes:
This was a discussion I've started in the digitalmars.D.learn newsgroup, but
div0 has suggested to move it here for a more general public.

This is a reduced version of a D2 program, written while I was trying to
use/learn immutability. This program compiles:


struct Foo {
    static int x;
}
void main() {
    immutable Foo f;
    Foo.x++;
    f.x++;
}


My idea was that immutable applied to a struct makes every thing in such struct
namespace immutable. I was wrong, but what do you think about changing a little
how D works here?
A possible idea is: if one instance is 'const', then the static attribute x is
seen as const from just that instance. If one instance is set to 'immutable' as
here, then the static attributes become immutable in every instance of Foo.


A bit later in the discussion div0 and Pelle M. have said/suggested that
accessing static vars through an instance can be a bad thing, and it's better
to allow the programmer to access them only through the class/struct name.

Bye,
bearophile
Mar 05 2010
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 This is a reduced version of a D2 program, written while I was trying
 to use/learn immutability. This program compiles:
 
 
 struct Foo { static int x; } void main() { immutable Foo f; Foo.x++; 
 f.x++; }
 
 
 My idea was that immutable applied to a struct makes every thing in
 such struct namespace immutable. I was wrong, but what do you think
 about changing a little how D works here? A possible idea is: if one
 instance is 'const', then the static attribute x is seen as const
 from just that instance. If one instance is set to 'immutable' as
 here, then the static attributes become immutable in every instance
 of Foo.
I think that's unworkable, as static variables cannot immutable in one instance and mutable in another.
Mar 05 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
 I think that's unworkable, as static variables cannot immutable in one 
 instance and mutable in another.
If you want you can express your opinion about the second part of the post too. Some people (I think 4 so far) more or less want to disallow the access of static fields from an instance. Generally in my D/Python code I prefer to access static field using the class/struct name, to reduce possible confusion. Bye, bearophile
Mar 06 2010
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:hmrtbk$1aoi$1 digitalmars.com...
 This was a discussion I've started in the digitalmars.D.learn newsgroup, 
 but div0 has suggested to move it here for a more general public.

 This is a reduced version of a D2 program, written while I was trying to 
 use/learn immutability. This program compiles:


 struct Foo {
    static int x;
 }
 void main() {
    immutable Foo f;
    Foo.x++;
    f.x++;
 }


 My idea was that immutable applied to a struct makes every thing in such 
 struct namespace immutable. I was wrong, but what do you think about 
 changing a little how D works here?
 A possible idea is: if one instance is 'const', then the static attribute 
 x is seen as const from just that instance. If one instance is set to 
 'immutable' as here, then the static attributes become immutable in every 
 instance of Foo.


 A bit later in the discussion div0 and Pelle M. have said/suggested that 
 accessing static vars through an instance can be a bad thing, and it's 
 better to allow the programmer to access them only through the 
 class/struct name.

 Bye,
 bearophile
I've always felt that the ability to access static members through an instance was just a bad idea in general, and this seems to add another reason not to allow it.
Mar 05 2010
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:hmsqdk$9ud$1 digitalmars.com...
 "bearophile" <bearophileHUGS lycos.com> wrote in message 
 news:hmrtbk$1aoi$1 digitalmars.com...
 A bit later in the discussion div0 and Pelle M. have said/suggested that 
 accessing static vars through an instance can be a bad thing, and it's 
 better to allow the programmer to access them only through the 
 class/struct name.

 Bye,
 bearophile
I've always felt that the ability to access static members through an instance was just a bad idea in general, and this seems to add another reason not to allow it.
The one possible exception I can think of (and I'm not even sure if it's applicable to D or not) is if you're passed an instance of something and want to call a static member of it polymorphically. Without polymorphism you can just do "typeof(instance).staticFunc()", but I'm not sure offhand whether or not there's a way to do that polymorphically (or if static members can even be polymorphic). However, I think that if people are calling static members through instances instead of types just to make the call polymorphic, then I'd consider that less of a reason to allow "instance.staticMember" and more of a reason to have some sort of polymorphic runtime equivilent to typeof() (Do we currently have such a thing that can suffice?).
Mar 05 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 06 Mar 2010 07:33:43 +0100, Nick Sabalausky <a a.a> wrote:

 The one possible exception I can think of (and I'm not even sure if it's
 applicable to D or not) is if you're passed an instance of something and
 want to call a static member of it polymorphically. Without polymorphism  
 you
 can just do "typeof(instance).staticFunc()", but I'm not sure offhand
 whether or not there's a way to do that polymorphically (or if static
 members can even be polymorphic).
They can't. So the only reason for static members to be available from an instance is to avoid typeof( T ). The presence of this feature does not bother me, but I feel the right thing would be to axe it. -- Simen
Mar 06 2010
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Nick Sabalausky wrote:

...
 I've always felt that the ability to access static members through an
 instance was just a bad idea in general, and this seems to add another
 reason not to allow it.
I agree, some compilers issue warnings in this case.
Mar 06 2010
parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
Lutger wrote:

 Nick Sabalausky wrote:
 
 ...
 I've always felt that the ability to access static members through an
 instance was just a bad idea in general, and this seems to add another
 reason not to allow it.
I agree, some compilers issue warnings in this case.
Warnings? Why allow it at all? I'm not aware of anything that you really gain by it. It's just confusing for no extra benefit. I have no idea why any language has ever allowed it. Sure, a warning is better than nothing, but it really should be disallowed entirely. - Jonathan M Davis
Mar 06 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:
 Warnings? Why allow it at all? I'm not aware of anything that you really 
 gain by it. It's just confusing for no extra benefit. I have no idea why any 
 language has ever allowed it. Sure, a warning is better than nothing, but it 
 really should be disallowed entirely.
Walter has not commented about this topic yet. If you want you can file a bug, trying to explain well all pros and cons of this idea (I moderately agree with it, I think it can make D a bit more tidy). Bye, bearophile
Mar 06 2010
prev sibling next sibling parent reply Michal Minich <michal.minich gmail.com> writes:
On Fri, 05 Mar 2010 16:33:40 -0500, bearophile wrote:

 A bit later in the discussion div0 and Pelle M. have said/suggested that
 accessing static vars through an instance can be a bad thing, and it's
 better to allow the programmer to access them only through the
 class/struct name.
I think that calling static members through an instance should be disallowed. In my opinion this is serious misfeature. It causes semantic un-clearness on usage - As you shown with the example with immutable static member. Here is one with mutable member: consider: struct S { static int s; int i } and usage in some other module: S s1, s2; s1.s += 1; s1.i += 1; now s2.s == 1, s2.i == 0. from usage is not apparent that 's' is a static member, in fact it seems it is instance member. This just makes program less clear. When one is presented with new code base and want to understand it, he must allays check if the member is not static - it should be apparent from usage and compiler should force it. This would allow an additional feature: two "namespaces" in the class/ struct - one for static names and one for instance names, giving ability to "overload" members - i.e. have two opCall in struct - one for type and one for instance. But I cannot think of any example use case of this feature right now.
Mar 06 2010
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sat, Mar 06, 2010 at 11:33:02AM +0000, Michal Minich wrote:
 This would allow an additional feature: two "namespaces" in the class/
 struct - one for static names and one for instance names, giving ability 
 to "overload" members - i.e. have two opCall in struct - one for type and 
 one for instance. But I cannot think of any example use case of this 
 feature right now.
I'd really like for opCall to be separated out, so you can initialize structs from various types and treat it like a function object without hassle. I've tried to do this now, but it keeps calling static opcall when I wanted the other one, and sometimes vice versa. In a perfect world, all three of these would be workable: Variant a = 10; Variant b = { writefln("Hello, world!"); }; b(); But, last time I tried, I could get line 2 or line 3 to work, but not both. Separating static from instance should do the trick. -- Adam D. Ruppe http://arsdnet.net
Mar 06 2010
parent reply Michal Minich <michal.minich gmail.com> writes:
On Sat, 06 Mar 2010 11:30:45 -0500, Adam D. Ruppe wrote:

 On Sat, Mar 06, 2010 at 11:33:02AM +0000, Michal Minich wrote:
 This would allow an additional feature: two "namespaces" in the class/
 struct - one for static names and one for instance names, giving
 ability to "overload" members - i.e. have two opCall in struct - one
 for type and one for instance. But I cannot think of any example use
 case of this feature right now.
I'd really like for opCall to be separated out, so you can initialize structs from various types and treat it like a function object without hassle. I've tried to do this now, but it keeps calling static opcall when I wanted the other one, and sometimes vice versa. In a perfect world, all three of these would be workable: Variant a = 10; Variant b = { writefln("Hello, world!"); }; b(); But, last time I tried, I could get line 2 or line 3 to work, but not both. Separating static from instance should do the trick.
I never used opAssign, but doesn't it solves this problem? Considering that both opCall and opAssign work with "=" their interaction must be probably quite complex...
Mar 06 2010
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sun, Mar 07, 2010 at 12:36:11AM +0000, Michal Minich wrote:
 I never used opAssign, but doesn't it solves this problem? Considering 
 that both opCall and opAssign work with "=" their interaction must be 
 probably quite complex...
opAssign only worked after the struct has been initialized. === import std.stdio; struct S { /* static S opCall(int a) { S tmp; writefln("opCall(%d);", a); return tmp; } */ S* opAssign(int a) { writefln("opAssign(%d);", a); return &this; } } void main() { S a = 10; // Error: cannot implicitly convert expression (10) of type int to S a = 20; a(30); } === Uncomment the opCall, and it compiles, outputting: opCall(10); opAssign(20); opCall(30); If you add a second opCall that is not static, but otherwise identical, then it fails to compile either the first nor third lines, because: c.d(19): Error: function c.S.opCall called with argument types: ((int)) matches both: c.S.opCall(int a) and: c.S.opCall(int a) c.d(21): Error: function c.S.opCall called with argument types: ((int)) matches both: c.S.opCall(int a) and: c.S.opCall(int a) (one being the static opCall, and the other of course being the instance one). JavascriptObject struct right after opDispatch came out - emulating a delegate and accepting assignment at declaration were mutually incompatible. -- Adam D. Ruppe http://arsdnet.net
Mar 06 2010
prev sibling parent yigal chripun <yigal100 gmail.com> writes:
Nick Sabalausky Wrote:

 "Nick Sabalausky" <a a.a> wrote in message 
 news:hmsqdk$9ud$1 digitalmars.com...
 "bearophile" <bearophileHUGS lycos.com> wrote in message 
 news:hmrtbk$1aoi$1 digitalmars.com...
 A bit later in the discussion div0 and Pelle M. have said/suggested that 
 accessing static vars through an instance can be a bad thing, and it's 
 better to allow the programmer to access them only through the 
 class/struct name.

 Bye,
 bearophile
I've always felt that the ability to access static members through an instance was just a bad idea in general, and this seems to add another reason not to allow it.
The one possible exception I can think of (and I'm not even sure if it's applicable to D or not) is if you're passed an instance of something and want to call a static member of it polymorphically. Without polymorphism you can just do "typeof(instance).staticFunc()", but I'm not sure offhand whether or not there's a way to do that polymorphically (or if static members can even be polymorphic). However, I think that if people are calling static members through instances instead of types just to make the call polymorphic, then I'd consider that less of a reason to allow "instance.staticMember" and more of a reason to have some sort of polymorphic runtime equivilent to typeof() (Do we currently have such a thing that can suffice?).
In dynamic languages like Ruby, instances carry a pointer to their class instance which contains the "static" variables. say we have: class Foo { static int bar = 42; //... } foo = new Foo(); foo.bar is resolved at runtime as e.g. foo.Class.bar where Class is the singelton instance that represents the Foo class itself. if foo is const then D style transitivity would mean that bar must be const as well. regarding immutability, this is imposaible since the Foo singleton is shared between all (mutable and immutable) instances. In this case foo mustn't contain a Class member at all and have no access to it's data in order to keep the transitivity. D has a different implementation but I think the above semantics is what people expect and the implementation differences shouldn't affect the semantics, they should be encapsulated. IMO, the entire const design is backwards and ties toghether two completely separate concerns (immutability for conccurency and const for interface definitions) but there's zero change any of it will ever be changed.
Mar 08 2010