www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP4: Properties

reply "Nick Sabalausky" <a a.a> writes:
 An alternate usage/definition syntax for properties.

http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

Note that there are a few parts marked NEED HELP, that could use assistance 
from someone with more expertise in this than me.
Jul 23 2009
next sibling parent reply Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Nick Sabalausky wrote:
  An alternate usage/definition syntax for properties.
 
 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4
 
 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
 
 
Have you checked out haXe's syntax for properties? http://haxe.org/ref/properties It's not very sugary, but it doesn't add new keywords and it handles inheritance nicely (to change the prop's behavior in a subclass, just inherit its methods). The other caveat I can think of is that the grammar might need to change a bit before haXe's properties could be used in D, mostly because haXe's declarations are like this: var Identifier : Type; whereas D does decls like so: Type Identifier So perhaps we could have a grammar like this? PropertyDecl: Type Identifier '{' Getter ',' Setter '}' ';' Getter: null default FunctionIdentifier Setter: null default FunctionIdentifier At some point (semantic analysis?) the compiler needs to make sure the functions used in the property have the correct signature. Type foo(); for getter, Type foo(Type); for setter. Something like int foo{default,default}; could be optimized into int foo; though it should otherwise have the semantics of a property and not of a field (e.g. &foo is not allowed or you get a special property struct or somesuch). I also second the importance of whatever Andrei was talking about with respect to properties in some thread a while ago. It was something about potentially needing 3 different accessors for a property due to some inconsistency or potential for pessimization. I forget what exactly. I remember him having difficulty fitting properties into D2's setup for generic algorithms. It would be nice to get that right.
Jul 24 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Chad J" <chadjoan __spam.is.bad__gmail.com> wrote in message 
news:h4cv6h$st6$1 digitalmars.com...
 Have you checked out haXe's syntax for properties?
 http://haxe.org/ref/properties
Yes, in fact, I've been using haxe a lot lately for work. It certainly beats AS2 and PHP, but there's still a lot about it I really dislike, and it's property syntax is one of my biggest complaints. For those not familiar with haxe, compare the following property in my -------------------------------- // D, current DIP4 public int foo { get { return value; } set { value = set; } } -------------------------------- private int _foo; public int foo { get { return _foo; } set { _foo = value; } } -------------------------------- // Haxe public foo(get_foo,set_foo):Int; private _foo:Int; private get_foo():Int { return _foo; } private set_foo(value:Int):Int { _foo = value; return value; } -------------------------------- That's absolutely horrific for anyone who even remotely values DRY and readability (and formatting the the getters/setters on multiple lines doesn't help). There are a bunch of problems with it, but the one that really sticks out to me is: why in the world should I have to specify special getter/setter names for every single property? What in the world is the point of that? That's like being expected to specify a special name for every 'if' block in the program. I don't want or need a special name, just give me a damn if/getter/setter/whatever!
Jul 24 2009
next sibling parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Nick Sabalausky wrote:
 "Chad J" <chadjoan __spam.is.bad__gmail.com> wrote in message 
 news:h4cv6h$st6$1 digitalmars.com...
 Have you checked out haXe's syntax for properties?
 http://haxe.org/ref/properties
Yes, in fact, I've been using haxe a lot lately for work. It certainly beats AS2 and PHP, but there's still a lot about it I really dislike, and it's property syntax is one of my biggest complaints. For those not familiar with haxe, compare the following property in my -------------------------------- // D, current DIP4 public int foo { get { return value; } set { value = set; } } -------------------------------- private int _foo; public int foo { get { return _foo; } set { _foo = value; } } -------------------------------- // Haxe public foo(get_foo,set_foo):Int; private _foo:Int; private get_foo():Int { return _foo; } private set_foo(value:Int):Int { _foo = value; return value; } -------------------------------- That's absolutely horrific for anyone who even remotely values DRY and readability (and formatting the the getters/setters on multiple lines doesn't help). There are a bunch of problems with it, but the one that really sticks out to me is: why in the world should I have to specify special getter/setter names for every single property? What in the world is the point of that? That's like being expected to specify a special name for every 'if' block in the program. I don't want or need a special name, just give me a damn if/getter/setter/whatever!
Good point.
Jul 24 2009
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Nick Sabalausky, el 24 de julio a las 16:16 me escribiste:
 "Chad J" <chadjoan __spam.is.bad__gmail.com> wrote in message 
 news:h4cv6h$st6$1 digitalmars.com...
 Have you checked out haXe's syntax for properties?
 http://haxe.org/ref/properties
Yes, in fact, I've been using haxe a lot lately for work. It certainly beats AS2 and PHP, but there's still a lot about it I really dislike, and it's property syntax is one of my biggest complaints. For those not familiar with haxe, compare the following property in my -------------------------------- // D, current DIP4 public int foo { get { return value; } set { value = set; } }
I think you have good points about not repeating yourself, but I still find it too magical. I think I prefer something a little more explicit, even if I have to repeat myself. And I think there should be a way to get the real underlaying variable easily. What about: public int foo: _foo { get { return _foo; } set(v) { _foo = v; } } Then, when you want to use the real internal variable, you just use _foo. Even when you are repeating yourself, the internal implementation and the external interface are decoupled; you can rename the property to bar without changing the implementation: public int bar: _foo { get { return _foo; } set(v) { _foo = v; } } The default protection attribute for underlaying property variables are private, but you can change it with: public int bar: protected _foo { get { return _foo; } set(v) { _foo = v; } } I think is is not much harder to write and maintain comparing with what you proposed, but I find it a lot more explicit and thus clear. You don't have to remember where that automagically variables came from. You can implement properties without even a real storage variable using your form: public int baz // readonly { get { return 1; } } What do you think? -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- PROTESTA EN PLAZA DE MAYO: MUSICO SE COSIO LA BOCA -- Crónica TV
Jul 24 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Leandro Lucarella" <llucax gmail.com> wrote in message 
news:20090724212800.GA2120 homero.springfield.home...
 I think you have good points about not repeating yourself, but I still
 find it too magical. I think I prefer something a little more explicit,
 even if I have to repeat myself.
I assume you're referring to the automatic "value" and "set" variables here, right? The proposal seems to be getting a lot of complaints about those. But, I haven't seen any explanations of actual problems with them beyond "it's magical", "I prefer", etc (unless I've overlooked something, and my apologies if I have). Any abstraction could be argued to be "magical". I'm getting the impression that this may be a case of an idea meeting resistance more from being different than from lack of merit. Of course, it could also be that I'm just being overprotective of a bad idea. Can you or someone else provide a more detailed argument/example/explanation for a problem with these automatic vars? As I do seem to be the only one in favor of these automatic vars though, I am willing to omit them from the proposal in the interest of (hopefully) getting at least *something* better than the current state. But, I would hate to have to do so without having been presented a deeper argument against them.
 And I think there should be a way to get
 the real underlaying variable easily.
I was thinking something through traits (which does need to be cleaned up anyway). Although, Robert's post has reminded me of the importance of using properties as readonly views to private data that's modifiable by potentially any member of the class. Using traits would indeed be way too clumsy in that case. But, I do have a solution to that particular scenario: public int foo { // default is whatever is used up above // (public in this case) // but, more permissive is not allowed // (like a protected prop with a public getter/setter) public get { return value; } // I'm using the default setter here just for the // heck of it, but you wouldn't have to. private set; } Then, anything in the class could set the internal value with just "foo", and anything else couldn't. And that setter could probably be automatically inlined. Obviously this doesn't take of all cases where one would need to directly access the property's internal data - something else would need to be created for that (like traits or something). But it does take care of what, to my knowledge, is the only non-optimization-related reason to do so. And, below).
 What about:

 public int foo: _foo
 {
    get { return _foo; }
    set(v) { _foo = v; }
 }

 Then, when you want to use the real internal variable, you just use _foo.
At this point, I think it would be good to make a clear distinction between the following issues: 1. Internal storage: auto-named or manually-named? 2. Setter parameter: auto-named or manually-named? 3. Actual syntax for manually-named internal storage. 4. Actual names for auto-named internal storage and auto-named setter parameter. below. The intent of the examples should still be perfectly clear with just the getter. post), there's another syntax idea I have for that (incorporating the "auto" idea from someone else): public int foo { auto _foo; // int, in this case get { return _foo; } //setter here } public int bar { bool isCached=false; // Any other arbitrary var get { /* do expensive work to get value and cache it */ } // maybe a setter here } (This actually makes me wonder about maybe exploring a more struct-derived approach...?) *If* manually-named internal storage is used, then I like both your syntax and the above. Compared to yours, the above is more flexible, but it's also more verbose and might be complete overkill anyway. Even though my original DIP4 proposal provides an automatic "value" for internal storage, there is nothing in the proposal that would prevent anyone private int _foo; public int foo { get { return _foo; } // Note also, that the automatic "value" // could be optimized away in these cases. } So, barring any implementation problems I may have overlooked, under my bondaged and disciplined into making redundant names, and you're not bondaged and disciplined into sticking with a pre-determined name.
 Even when you are repeating yourself, the internal implementation and the
 external interface are decoupled; you can rename the property to bar
 without changing the implementation:

 public int bar: _foo
 {
    get { return _foo; }
    set(v) { _foo = v; }
 }
True, but for anyone using the "myVar : _myVar" naming convention, changing one without changing the other would create . But, that's admittedly a minor before. Maybe a hybrid approach would be in order? Take your syntax, but the " : _foo" part is optional. And when it's omitted, "value" (or whatever) is used as the default. Except...if you're using that syntax to create a name that the whole class can access, then that would be non-unique (and therefore a problem)...So...What about making the " : _foo " name optional *and* only accessible within the property *and* adding in my idea above about "private set {}"? Ie: Hmm, also, I'm going to make two alternates, A and B, not sure which would be better: class FooClass { public int foo : _foo { get { return _foo; } set; // Ehh, I'm just gonna use the default setter here } public int bar { get { return value; } private set; } public func() { int x; x = foo; // Ok (public getter) foo = 5; // Ok (public setter) x = bar; // Ok (public getter) bar = 5; // Ok (private setter) x = value; // Error: Undeclared token value = 5; // Error: Undeclared token x = bar.traits.internalProp; // Ok (but syntax is probably wrong) bar.traits.internalProp = 5; // Ok (but syntax is probably wrong) // Not sure which of these to do... version(A) { x = _foo; // Ok (internal value) _foo = 5; // Ok (internal value) } version(B) { x = _foo; // Error: Undeclared token _foo = 5; // Error: Undeclared token } x = foo.traits.internalProp; // Ok (but syntax is probably wrong) foo.traits.internalProp = 5; // Ok (but syntax is probably wrong) } } void main() { auto fc = new FooClass(); auto f = foo; // Ok (public getter) foo = 5; // Ok (public setter) auto b = bar; // Ok (public getter) bar = 5; // Error: Setter is private auto _f = _foo; // Error: Undeclared token _foo = 5; // Error: Undeclared token auto _v = value; // Error: Undeclared token value = 5; // Error: Undeclared token } In fact, unless there's real immediate objections, or some obvoious problem I'm missing, I may just include all of those ideas into a new version of the DIP. Language experts: Would there be parsing ambiguities with this "int propertyName : internalName" syntax?
 The default protection attribute for underlaying property variables are
 private, but you can change it with:

 public int bar: protected _foo
 {
    get { return _foo; }
    set(v) { _foo = v; }
 }
Sounds good.
 I think is is not much harder to write and maintain comparing with what
 you proposed, but I find it a lot more explicit and thus clear. You don't
 have to remember where that automagically variables came from.
I don't understand what's there that's non-trivial to remember. I've never "set" var in my proposal). And with D's magical $ for length, all of the worries people had about "people aren't going to know that!" "They'll have to remember that!", since that feature was implemented it's gotten used *constantly* and I'm not even aware of once single case where it actually ended up being a problem for anybody. These are not the sorts of things that are difficult to remember. And I'm a person who is notoriously bad at memorization!
 You can
 implement properties without even a real storage variable using your form:

 public int baz // readonly
 {
    get { return 1; }
 }
Agreed
 What do you think?
See everything above ;)
Jul 25 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:h4ecb4$m7g$1 digitalmars.com...
 True, but for anyone using the "myVar : _myVar" naming convention, 
 changing one without changing the other would create . But, that's 
 admittedly a minor issue, and on the whole it's certainly better than the 

Oops! I guess that's a *really* minor issue ;) What I meant to say before forgetting to proofread was "...changing one without changing the other would usually create an ugly inconsistent break from style, or result in the internal var having a name that's no longer appropriate or consistent with updated project terminology. But..." Or something like that anyway...Not that it really matters all that much...
Jul 25 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 25 Jul 2009 03:29:01 -0400, Nick Sabalausky <a a.a> wrote:

 "Leandro Lucarella" <llucax gmail.com> wrote in message
 news:20090724212800.GA2120 homero.springfield.home...
 I think you have good points about not repeating yourself, but I still
 find it too magical. I think I prefer something a little more explicit,
 even if I have to repeat myself.
I assume you're referring to the automatic "value" and "set" variables here, right? The proposal seems to be getting a lot of complaints about those. But, I haven't seen any explanations of actual problems with them beyond "it's magical", "I prefer", etc (unless I've overlooked something, and my apologies if I have). Any abstraction could be argued to be "magical".
I haven't read all the replies yet, but the one issue I have is similar to the array's magical length property: struct S { int value; int prop { get() { return value; // ambiguous } } } If you used something that was not a variable name (like the fix for arrays -- $) then you do not have a conflict. But I like the idea that Leandro brought up best. One other issue that his idea solves -- in an internal private method, you might want to use the underlying storage directly instead of calling the property for performance reasons, this would be difficult to address with a context keyword. -Steve
Jul 26 2009
prev sibling next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Andrei and Rainer have come up with an alternative that might work.
Addressing the points in the Rationale section:

* It may or may prevent unintended usage depending on how it's
implemented, but will certainly CONVEY the expected usage.

* As above, it may or may not solve the ambiguous code problem depending
on implementation details.

* +=, -=, etc.: I've said before that this should be addressed separately.

* It makes properties discoverable.

* There is a solution to the DRY problem.

Basically, the idea is that this:

interface I
{
    int foo();
    int foo(int);
}

becomes:

interface I
{
    int opGet_foo();
    int opSet_foo(int);
}

As I said, this addresses most of the problems: IDEs and debuggers can
simply look for opGet/opSet pairs.  It's extensible since we can add
more "operators" in the future, AND it plays nicely with inheritance.

The problem is that it still violates DRY.  However, I knocked together
a basic prototype property generator that helps alleviate this:

http://gist.github.com/154755

Possible implementations of the above:

class A : I
{
    // Automatic getter, setter and storage
    mixin( Property!(int, "foo") );
}

class B : I
{
    // Fully custom with custom storage and protection
    mixin( Property!(int, "foo",
        q{
            return storage*100;
        },
        q{
            return storage=value/100;
        }
    ));
}

With a more sophisticated template, it could probably be simplified even
further.

The nice thing about this is that it accomplishes the goals of the DIP
without introducing ANY new syntax.  It does still require compiler
changes to map a.b to a.opGet_b and a.b=c to a.opSet_b(c), but it would
hopefully be more palatable to Walter.

If you want, I can write this up as an alternative solution to the DIP.

Rainer's post: news://news.digitalmars.com:119/h4dpoq$2hpu$1 digitalmars.com
Andrei's post: news://news.digitalmars.com:119/h4dscd$2n7f$1 digitalmars.com
My response to Andrei's post:
news://news.digitalmars.com:119/h4ej0g$11p7$1 digitalmars.com
Jul 25 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
I do think this proposal is better than what we have since it meets the 
major requirements, but have one minor point of critique:

Offering a mixin is not a good enough argument to address the DRY 
shortcoming. While it may be acceptable in many cases, it is ugly and messes 
with reporting of errors, debugging, code coverage and profiling.
Jul 25 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Lutger wrote:
 I do think this proposal is better than what we have since it meets the 
 major requirements, but have one minor point of critique:
 
 Offering a mixin is not a good enough argument to address the DRY 
 shortcoming. While it may be acceptable in many cases, it is ugly and messes 
 with reporting of errors, debugging, code coverage and profiling.
Very true. We really need to come up with a way to fix this. That said, I sometimes think that string mixins will NEVER get fixed unless Walter has a strong impetus to do so: i.e., people are using them and hurting. But that's another DIP for another day. :P
Jul 25 2009
parent Lutger <lutger.blijdestijn gmail.com> writes:
Daniel Keep wrote:

 
 
 Lutger wrote:
 I do think this proposal is better than what we have since it meets the
 major requirements, but have one minor point of critique:
 
 Offering a mixin is not a good enough argument to address the DRY
 shortcoming. While it may be acceptable in many cases, it is ugly and
 messes with reporting of errors, debugging, code coverage and profiling.
Very true. We really need to come up with a way to fix this. That said, I sometimes think that string mixins will NEVER get fixed unless Walter has a strong impetus to do so: i.e., people are using them and hurting. But that's another DIP for another day. :P
I'm very curious when that day arrives what it could bring. AST macros may help with some issues, but this kind of trickery seems to me inherently unfriendly for tools and maintainers alike. Not that it's a bad thing though, you have to make some trade-offs somewhere.
Jul 25 2009
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Daniel Keep wrote:

 Basically, the idea is that this:
 
 interface I
 {
     int foo();
     int foo(int);
 }
 
 becomes:
 
 interface I
 {
     int opGet_foo();
     int opSet_foo(int);
 }
It's a little better. But there's still ambiguity: interface I { int foo; int opSet_foo(int); } foo = 5; // which foo is used? To fix that one, you need to report an error when both a var and a property of the same name are declared. Even though they don't have the same name in the interface. interface I { int opGet_foo(); void delegate() opGet_opGet_foo(); } auto x = opGet_foo; Is that the function or the property? Well, perhaps this is not an actual ambiguity in D. But it sure isn't pretty: auto x = opGet_foo; // it's the property auto x = opGet_foo(); // it may be either? auto x = &opGet_foo; // it's the function I just don't understand this resistance against a dedicated property syntax. -- Michiel Helvensteijn
Jul 25 2009
next sibling parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
I think I made a few mistakes in the D code, but the point stands.

-- 
Michiel Helvensteijn
Jul 25 2009
prev sibling next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Michiel Helvensteijn wrote:
 ...
 
 It's a little better. But there's still ambiguity:
 
 interface I {
     int foo;
     int opSet_foo(int);
 }
 
 foo = 5; // which foo is used?
 
 To fix that one, you need to report an error when both a var and a property
 of the same name are declared. Even though they don't have the same name in
 the interface.
I think this would NEED to be an error to keep the compiler from going insane. I don't see how this is appreciably different to a+b suddenly being rewritten as a.opAdd(b).
 ...
 
 I just don't understand this resistance against a dedicated property syntax.
You have to be careful: adding syntax increases the complexity of the language. Sometimes it's worth it, sometimes it isn't. If we can do it without adding syntax and it's not too onerous then we probably should.
Jul 25 2009
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-25 06:10:09 -0400, Michiel Helvensteijn 
<m.helvensteijn.remove gmail.com> said:

 It's a little better. But there's still ambiguity:
 
 interface I {
     int foo;
     int opSet_foo(int);
 }
 
 foo = 5; // which foo is used?
In the other thread, I suggested this, which could aleviate the problem: int foo.opGet(); // getter void foo.opAssign(int); // setter with some support from the compiler. It could even be exteded to support more: int foo.opIndex(int); // foo[1]; void foo.opAddAssign(int); / foo += 1; void foo.invert(); // special function attached to property Basically, all you need to implement properties is not a dedicaced "property" syntax, it's a syntax to implement some kind of local namespace, and am "opGet" or "opValue" operator for representing the local namespace. It could also be expressed like this: namespace foo { int opGet(); // getter void opAssign(int); // setter ... int opIndex(int); // foo[1]; void opAddAssign(int); / foo += 1; void invert(); // special function attached to property } In both cases, the result would be the same: foo = 1; // same as foo.opAssign(1); return foo; // same as return foo.opGet(); -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 25 2009
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-25 07:00:32 -0400, Michel Fortin <michel.fortin michelf.com> said:

 	namespace foo {
 		int opGet(); // getter
 		void opAssign(int); // setter
 		...
 		int opIndex(int); // foo[1];
 		void opAddAssign(int); / foo += 1;
 		void invert(); // special function attached to property
 	}
I just want to clarify that I used "namespace" as a keyword in this example to better illustrate the fact that there is no more magic or special syntax under the hood than with a C++ namespace. I'm not actually suggesting we use a "namespace" keyword, I think it'd be confusing. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 25 2009
prev sibling next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
Michel Fortin wrote:
 On 2009-07-25 06:10:09 -0400, Michiel Helvensteijn 
 <m.helvensteijn.remove gmail.com> said:
 
 It's a little better. But there's still ambiguity:

 interface I {
     int foo;
     int opSet_foo(int);
 }

 foo = 5; // which foo is used?
In the other thread, I suggested this, which could aleviate the problem: int foo.opGet(); // getter void foo.opAssign(int); // setter with some support from the compiler. It could even be exteded to support more: int foo.opIndex(int); // foo[1]; void foo.opAddAssign(int); / foo += 1; void foo.invert(); // special function attached to property Basically, all you need to implement properties is not a dedicaced "property" syntax, it's a syntax to implement some kind of local namespace, and am "opGet" or "opValue" operator for representing the local namespace. It could also be expressed like this: namespace foo { int opGet(); // getter void opAssign(int); // setter ... int opIndex(int); // foo[1]; void opAddAssign(int); / foo += 1; void invert(); // special function attached to property } In both cases, the result would be the same: foo = 1; // same as foo.opAssign(1); return foo; // same as return foo.opGet();
If property is going to be extended like this, why not just make a nested struct. Works even now.
Jul 25 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-25 08:07:56 -0400, KennyTM~ <kennytm gmail.com> said:

 Michel Fortin wrote:
 
 In the other thread, I suggested this, which could aleviate the problem:
 
     int foo.opGet();        // getter
     void foo.opAssign(int); // setter
 
 with some support from the compiler.
 
 It could even be exteded to support more:
 
     int foo.opIndex(int); // foo[1];
     void foo.opAddAssign(int); / foo += 1;
     void foo.invert(); // special function attached to property
 
 Basically, all you need to implement properties is not a dedicaced 
 "property" syntax, it's a syntax to implement some kind of local 
 namespace, and am "opGet" or "opValue" operator for representing the 
 local namespace. It could also be expressed like this:
 
     namespace foo {
         int opGet(); // getter
         void opAssign(int); // setter
         ...
         int opIndex(int); // foo[1];
         void opAddAssign(int); / foo += 1;
         void invert(); // special function attached to property
     }
 
 In both cases, the result would be the same:
 
     foo = 1; // same as foo.opAssign(1);
     return foo; // same as return foo.opGet();
 
If property is going to be extended like this, why not just make a nested struct. Works even now.
Close, but a nested struct doesn't have access to the outer class, nor can you override its functions in a derived class. I'd say what I'm proposing is closer to a named mixin: class Z { int x; template Property() { void opAssign(int v) { x = v; } void opAddAssign(int v) { x += v; } int get() { return x; } alias get this; } mixin Property property; } Z z = new Z; z.property = 1; // works! What doesn't work here is the "alias get this" line: you're still forced to explicitly call the getter. And I have the feeling that overriding in a derived class won't work either. Oh and the syntax isn't great at all. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 25 2009
prev sibling parent reply Chad J <chadjoan __spam.is.bad__gmail.com> writes:
I really like this idea.

It's pleasing to the eye and very general, much more so than typical
properties are.  The only thing it doesn't solve is the optional
implicit backing storage to satiate all of the DRY fans.
Jul 25 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Chad J wrote:
 I really like this idea.
Which? Andrei
Jul 25 2009
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-25 15:13:06 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Chad J wrote:
 I really like this idea.
Which?
His message was in reply to mine: <http://digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=93842> Although there are two syntax proposals in there... I'd guess it's the second one. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 25 2009
prev sibling parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Andrei Alexandrescu wrote:
 Chad J wrote:
 I really like this idea.
Which? Andrei
That whole post I replied to.
     int foo.opIndex(int); // foo[1];
     void foo.opAddAssign(int); / foo += 1;
     void foo.invert(); // special function attached to property 
Or as I see it working in the more verbose case: T foo.opAssign(T bar) { // code goes here. } If namespaces lead to that kind of ability then they seem pretty nifty.
     namespace foo {
         int opGet(); // getter
         void opAssign(int); // setter
         ...
         int opIndex(int); // foo[1];
         void opAddAssign(int); / foo += 1;
         void invert(); // special function attached to property
     } 
That seems pretty useful. Maybe it doesn't have to be namespace. Use scope or auto instead. scope seems appropriate, though it may be asking for ambiguities. I can live without this though if it is too drastic.
Jul 25 2009
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Chad J" <chadjoan __spam.is.bad__gmail.com> wrote in message 
news:h4fjiu$2pbr$1 digitalmars.com...
 The only thing it doesn't solve is the optional
 implicit backing storage to satiate all of the DRY fans.
As far as I can tell, that seems to only be me :/
Jul 25 2009
parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Nick Sabalausky wrote:
 "Chad J" <chadjoan __spam.is.bad__gmail.com> wrote in message 
 news:h4fjiu$2pbr$1 digitalmars.com...
 The only thing it doesn't solve is the optional
 implicit backing storage to satiate all of the DRY fans.
As far as I can tell, that seems to only be me :/
I appreciate it too. I suppose it's not super-important to me because I am willing to eat a bit of cruft for the sake of progress, but yeah, I would like to see some kind of implicit backing to make things less hackey looking in my code.
Jul 25 2009
prev sibling next sibling parent Piotrek <starpit tlen.pl> writes:
Daniel Keep pisze:
 interface I
 {
     int opGet_foo();
     int opSet_foo(int);
 }
..
 
 If you want, I can write this up as an alternative solution to the DIP.
Vote++ Personally, this is my No.1 so far. Cheers Piotrek
Jul 25 2009
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
news:h4ejrk$12vv$1 digitalmars.com...
 Andrei and Rainer have come up with an alternative that might work.
.....
 Basically, the idea is that this:

 interface I
 {
    int foo();
    int foo(int);
 }

 becomes:

 interface I
 {
    int opGet_foo();
    int opSet_foo(int);
 }
...etc... My admittedly sarcastic thoughts on this whole group of property proposals (and pardon my grumpiness): A 'for' loop is great, but one of the most common uses for it is to iterate over a collection. And for that, there are certain issues with using 'for' that other languages have solved by adding a special 'foreach'. But, I see no reason to add a special 'foreach' syntax (and certainly not a new keyword!), because we have most of what we need for 'foreach' in place already: class Foo { int[] content; Iterator opIterator() { return new Iterator(); } class Iterator { private index=0; int opGetNext() { return content[index++]; } bool opHasNext() { return index < content.length; } } } void main() { auto f = new Foo(); // populate f int index; int val; auto iter = f.opIterator(); for(int index=0, int val=iter.opGetNext(); iter.opHasNext(); index++, val=iter.opGetNext()) { // Use index and val } } Granted, that's ugly and won't satisfy the people who like DRY and brevity, but we can solve that with mixins: class Foo { int[] content; mixin(iterator!(int, q{ private index=0; }, q{ return content[index++]; }, q{ return index < content.length; }, )); } void main() { auto f = new Foo(); // populate f mixin(foreach!(f, int, "val", "index", q{ // Use index and val } )); } And then everybody loves this new idea because it's so D-like and makes minimal changes to the syntax/compiler. And then we all spend every weekend wondering why the hell nobody wants to use our wonderful language. Don't get me wrong, using these "foo.opGet" ideas for *behind-the-scenes implementation* of properties sounds like it may very well be the right way to go. But without a real dedicated syntax to cover it all up, it's just idiotic.
Jul 25 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Excused.  :D

Look at it from a practical standpoint: it *would* be nice to have
dedicated syntax, but Walter *is opposed to it*.  He doesn't see the
need for it.

I think I'm like him in this respect: he wants to find a way of doing
this without having to actually extend the language.

If Walter becomes convinced that properties DO need improvement AND
deserve special syntax, then hooray!  The proposal I brought up is
superfluous and can be discarded.

But we know he's currently against adding syntax.  So he might reject
your proposal.  That's where the one I posted about comes in: it
*doesn't* require syntax changes to the language; it improves properties
the best we can without doing adding syntax.

If he rejects yours, maybe he'll be more receptive to the alternative.
Yes, it's not as syntactically nice as yours, but it's STILL an improvement.

And yeah, mixins are ugly.  But if no one ever uses them, they'll never
improve.  Maybe if lots of code is using them, Walter will be inclined
to work on macros to improve the situation.

Some improvement is better than none.  Sometimes you have to compromise.
 I don't think we should ignore or demonise viable alternatives because
they're not what we specifically wanted.
Jul 26 2009
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
news:h4i0tu$hig$1 digitalmars.com...
 Look at it from a practical standpoint: it *would* be nice to have
 dedicated syntax, but Walter *is opposed to it*.  He doesn't see the
 need for it.
....
 Some improvement is better than none.  Sometimes you have to compromise.
 I don't think we should ignore or demonise viable alternatives because
 they're not what we specifically wanted.
I suppose you have a good point. Although I felt like I was compromising plenty just with being willing (if necessary) to abandon the automatic internal storage... :/ (I really want that! :) ) I am convinced though, if properties get done in this Walter-friendly manner, it'll become yet another in the list of prospective user's complaints about D. "Yea, I looked at D. Have you seen the syntax for creating properties? OMG, what were they thinking?!"
Jul 26 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Nick Sabalausky wrote:
 "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
 news:h4i0tu$hig$1 digitalmars.com...
 Look at it from a practical standpoint: it *would* be nice to have
 dedicated syntax, but Walter *is opposed to it*.  He doesn't see the
 need for it.
.....
 Some improvement is better than none.  Sometimes you have to compromise.
 I don't think we should ignore or demonise viable alternatives because
 they're not what we specifically wanted.
I suppose you have a good point. Although I felt like I was compromising plenty just with being willing (if necessary) to abandon the automatic internal storage... :/ (I really want that! :) ) I am convinced though, if properties get done in this Walter-friendly manner, it'll become yet another in the list of prospective user's complaints about D. "Yea, I looked at D. Have you seen the syntax for creating properties? OMG, what were they thinking?!"
Actually, what I'd like to see is this syntax: mixin properties! q{ int foo = 42 { get; set { notify(); storage = value; } } }; The only reason we HAVE to use a string mixin here is that you can't have protection attributes in a mixin template; they get applied to within the scope of the template, not the scope of where they're being mixed in. Pity we can't do: `private(scope) T storage;` or somesuch to escape the protection... As for parsing the string, I suspect that it's possible, but all my experiments into CTFE-based parsing of D code has shown it to be incredibly fiddly and painful.
Jul 26 2009
prev sibling parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Daniel Keep wrote:
 ...
 And yeah, mixins are ugly.  But if no one ever uses them, they'll never
 improve.  Maybe if lots of code is using them, Walter will be inclined
 to work on macros to improve the situation.
 ...
I'd be kinda surprised if Walter is reading all of this and not thinking, "hmmmm, maybe I should fix this someday." Everyone is saying mixins are ugly. Ugly to the point where they obfuscate your code. And it sounds like only a handful of people are using them (hence arguments trying to convince people to use them). Clue by four. At some level I think Walter saw this coming a long time ago, hence talk of AST macros. Too bad they are probably too difficult for a D2 release. Maybe mixins are supposed to be ugly and only useful for optimization hacks and such, but not really intended to allow the language to extend itself. This actually fits better with my memory of the mood surrounding their creation. *shrug* At the end of all of this, I don't find myself feeling like using mixins unless I really have to.
Jul 26 2009
prev sibling next sibling parent reply BLS <windevguy hotmail.de> writes:
Nick Sabalausky wrote:
  An alternate usage/definition syntax for properties.
 
 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4
 
 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
 
 
A one liner should do the trick too. [public] [const] property int i; public -> delphi published const -> readonly / getter the compiler can generate getter and setter code.
Jul 25 2009
next sibling parent BLS <windevguy hotmail.de> writes:
BLS wrote:
 Nick Sabalausky wrote:
  An alternate usage/definition syntax for properties.

 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

 Note that there are a few parts marked NEED HELP, that could use 
 assistance from someone with more expertise in this than me.
A one liner should do the trick too. [public] [const] property int i; public -> delphi published const -> readonly / getter the compiler can generate getter and setter code.
[public] [const|immutable] property int i;
Jul 25 2009
prev sibling parent reply BLS <windevguy hotmail.de> writes:
BLS wrote:
 Nick Sabalausky wrote:
  An alternate usage/definition syntax for properties.

 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

 Note that there are a few parts marked NEED HELP, that could use 
 assistance from someone with more expertise in this than me.
A one liner should do the trick too. [public] [const] property int i; public -> delphi published const -> readonly / getter the compiler can generate getter and setter code.
I am a little bit ''' about the feedback : Is there really nobody who got it : immutable property int i -> becomes : pure int get_i() nothrow { return i } take the rest of the syntax and tell me where the leak is.
Jul 26 2009
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
BLS wrote:

 A one liner should do the trick too.
 [public] [const] property int i;
I am a little bit ''' about the feedback : Is there really nobody who got it :
I think people got it. But it's not a property. Your one-liner seems to be equivalent to a field. Except, I guess, that you can't take the address. The whole idea of a property is that it can have non-trivial getter/setter functions. Like a read-only property of a Line, that returns its length automatically calculated from its two points. Or a getter and setter that keep a log of all accesses to the information. My favorite example is of a Color class, that internally stores its value in the RGB model, but has properties to read and change its value through the HSV and HSL models as well. -- Michiel Helvensteijn
Jul 26 2009
parent reply BLS <windevguy hotmail.de> writes:
Michiel Helvensteijn wrote:
 BLS wrote:
 
 A one liner should do the trick too.
 [public] [const] property int i;
I am a little bit ''' about the feedback : Is there really nobody who got it :
I think people got it. But it's not a property. Your one-liner seems to be equivalent to a field. Except, I guess, that you can't take the address. The whole idea of a property is that it can have non-trivial getter/setter functions. Like a read-only property of a Line, that returns its length automatically calculated from its two points. Or a getter and setter that keep a log of all accesses to the information. My favorite example is of a Color class, that internally stores its value in the RGB model, but has properties to read and change its value through the HSV and HSL models as well.
well, the one liner assumes that the compiler will do code generation. (maybe I should figure that out... imutable property uint theAnswer = 42: ====================================== ie. class universe { inmutable property uint theAnswer = 42: /* expands to !! pure uint get_theAnswer() nothrow() { return theAnswer; } private inmutable int theAnswer = 42 */ } and : property bool has_cojones; ========================== class manorweeny { property bool has_cojones; /* expands to !! bool get_has_cojones() { return has_cojones; } void set_has_Cojones(bool yep) { has_cjojones = yep; } private bool has_cojones = false; */ } ---- I just can imagine two property situations : Read + Write OR Read Only... thanks for you feedback Michiel, Björn
Jul 26 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"BLS" <windevguy hotmail.de> wrote in message 
news:h4ilju$1m51$1 digitalmars.com...
 well, the  one liner assumes that the compiler will do code generation. 
 (maybe I should figure that out...


 imutable property uint theAnswer = 42:
 ======================================

 ie.
 class universe
 {

   inmutable property uint theAnswer = 42:

   /* expands to !!

   pure uint get_theAnswer() nothrow()
   {
     return theAnswer;
   }


   private inmutable int theAnswer = 42

   */

 }


 and :

 property bool has_cojones;
 ==========================

 class manorweeny
 {

   property bool has_cojones;

   /* expands to !!

   bool get_has_cojones()
   {
     return has_cojones;
   }

   void set_has_Cojones(bool yep)
   {
     has_cjojones = yep;
   }

   private bool has_cojones = false;
  */

 }

 ---- I just can imagine two property situations :
 Read + Write OR  Read Only...

 thanks for you feedback Michiel,
 Björn
I still don't see how any of that allows any of the things that properties are actually used for (as opposed to just an ordinary variable). Under what you're proposing, how does one actually write their own getter/setter for the property?
Jul 26 2009
prev sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
BLS wrote:

 I think people got it. But it's not a property. Your one-liner seems to
 be equivalent to a field. Except, I guess, that you can't take the
 address.
 
 The whole idea of a property is that it can have non-trivial
 getter/setter functions. Like a read-only property of a Line, that
 returns its length automatically calculated from its two points. Or a
 getter and setter that keep a log of all accesses to the information.
 
 My favorite example is of a Color class, that internally stores its value
 in the RGB model, but has properties to read and change its value through
 the HSV and HSL models as well.
...
Again, what is the difference between your one-liners and simple fields? immutable property uint theAnswer = 42; bool has_cojones; A property is much more sophisticated. The whole point is to write your own setter and getter methods. Only in very few cases do you want a property with simple field semantics. I will give you that Line class I was talking about. Tell me how you can do this with your one-liner: class Line { private: Point _a; Point _b; public: this(Point a, Point b) { _a = a; _b = b; } property float length { auto get() { float absX = abs(_a.x - _b.x); float absY = abs(_a.y - _b.y); return sqrt(absX * absX + absY * absY); } } // insert trivial properties to read/write points } You see, the length property doesn't have its own storage. It deduces its value from the points of the line. -- Michiel Helvensteijn
Jul 27 2009
parent reply BLS <windevguy hotmail.de> writes:
Michiel Helvensteijn wrote:
 BLS wrote:
 
 I think people got it. But it's not a property. Your one-liner seems to
 be equivalent to a field. Except, I guess, that you can't take the
 address.

 The whole idea of a property is that it can have non-trivial
 getter/setter functions. Like a read-only property of a Line, that
 returns its length automatically calculated from its two points. Or a
 getter and setter that keep a log of all accesses to the information.

 My favorite example is of a Color class, that internally stores its value
 in the RGB model, but has properties to read and change its value through
 the HSV and HSL models as well.
...
Again, what is the difference between your one-liners and simple fields? immutable property uint theAnswer = 42; bool has_cojones; A property is much more sophisticated. The whole point is to write your own setter and getter methods. Only in very few cases do you want a property with simple field semantics. I will give you that Line class I was talking about. Tell me how you can do this with your one-liner: class Line { private: Point _a; Point _b; public: this(Point a, Point b) { _a = a; _b = b; } property float length { auto get() { float absX = abs(_a.x - _b.x); float absY = abs(_a.y - _b.y); return sqrt(absX * absX + absY * absY); } } // insert trivial properties to read/write points } You see, the length property doesn't have its own storage. It deduces its value from the points of the line.
I don't agree . 1- In most cases we have to deal with simple field semantics, No ? x,y,z so : immutable property uint theAnswer = 42; is a getter()...... period. your calculated length property is an exception, should be written in standard D code. IMO a property is a simple thing, a color, a weight, or a mass...
Jul 28 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 3:53 PM, BLS<windevguy hotmail.de> wrote:
 Michiel Helvensteijn wrote:
 BLS wrote:

 I think people got it. But it's not a property. Your one-liner seems t=
o
 be equivalent to a field. Except, I guess, that you can't take the
 address.

 The whole idea of a property is that it can have non-trivial
 getter/setter functions. Like a read-only property of a Line, that
 returns its length automatically calculated from its two points. Or a
 getter and setter that keep a log of all accesses to the information.

 My favorite example is of a Color class, that internally stores its
 value
 in the RGB model, but has properties to read and change its value
 through
 the HSV and HSL models as well.
...
Again, what is the difference between your one-liners and simple fields? immutable property uint theAnswer =3D 42; bool has_cojones; A property is much more sophisticated. The whole point is to write your own setter and getter methods. Only in very few cases do you want a property with simple field semantics. I will give you that Line class I was talki=
ng
 about. Tell me how you can do this with your one-liner:

 class Line {
 =A0 =A0private:
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Point _a;
 =A0 =A0 =A0 =A0Point _b;
 =A0 =A0 =A0 =A0public:
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0this(Point a, Point b) { _a =3D a; _b =3D=
b; }
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0property float length {
 =A0 =A0 =A0 =A0 =A0 =A0auto get() {
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0float absX =3D abs(_a.x - _b.x);
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0float absY =3D abs(_a.y - _b.y);
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return sqrt(absX * absX + absY * absY);
 =A0 =A0 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0// insert trivial properties to read/writ=
e points
 }

 You see, the length property doesn't have its own storage. It deduces it=
s
 value from the points of the line.
I don't agree . 1- In most cases we have to deal with simple field semantics, No ? x,y,z so : immutable property uint theAnswer =3D 42; is a getter()...... period=
.
 your calculated length property is an exception, should be written in
 standard D code.

 IMO a property is a simple thing, a color, a weight, or a mass...
How is length not as simple as a color? I don't get it. And consider the case of complex numbers. Either the pair (real,imag) is stored or (modulus,argument) is stored. Neither is more "fundamental" than the other as a representation. Which one do you make a field and which one "standard D code"? --bb
Jul 28 2009
parent reply BLS <windevguy hotmail.de> writes:
Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 3:53 PM, BLS<windevguy hotmail.de> wrote:
 Michiel Helvensteijn wrote:
 BLS wrote:

 I think people got it. But it's not a property. Your one-liner seems to
 be equivalent to a field. Except, I guess, that you can't take the
 address.

 The whole idea of a property is that it can have non-trivial
 getter/setter functions. Like a read-only property of a Line, that
 returns its length automatically calculated from its two points. Or a
 getter and setter that keep a log of all accesses to the information.

 My favorite example is of a Color class, that internally stores its
 value
 in the RGB model, but has properties to read and change its value
 through
 the HSV and HSL models as well.
...
Again, what is the difference between your one-liners and simple fields? immutable property uint theAnswer = 42; bool has_cojones; A property is much more sophisticated. The whole point is to write your own setter and getter methods. Only in very few cases do you want a property with simple field semantics. I will give you that Line class I was talking about. Tell me how you can do this with your one-liner: class Line { private: Point _a; Point _b; public: this(Point a, Point b) { _a = a; _b = b; } property float length { auto get() { float absX = abs(_a.x - _b.x); float absY = abs(_a.y - _b.y); return sqrt(absX * absX + absY * absY); } } // insert trivial properties to read/write points } You see, the length property doesn't have its own storage. It deduces its value from the points of the line.
I don't agree . 1- In most cases we have to deal with simple field semantics, No ? x,y,z so : immutable property uint theAnswer = 42; is a getter()...... period. your calculated length property is an exception, should be written in standard D code. IMO a property is a simple thing, a color, a weight, or a mass...
How is length not as simple as a color? I don't get it. And consider the case of complex numbers. Either the pair (real,imag) is stored or (modulus,argument) is stored. Neither is more "fundamental" than the other as a representation. Which one do you make a field and which one "standard D code"? --bb
hi bill, my fault, I mean distance.. (instead of length) Hope you agree with me that a colour (in the senses of E. Kant ) is something we can'T see as it is. but we gave and give it nevertheless a name : likewise red. Does not mean too much just :RED is a propetry. Now let`s compare that with distance calculation (without drifting too much away) RED is a property, Distance means necessarily a calculation. The question is ergo : Do we want pure behavior or math in our properties. IMO, behavior. This is what property means. so imutable proberty bool killbillv2 = false // is a read only getter .. (However to answer : ref... delegate and you have everything you need)
Jul 28 2009
parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
BLS wrote:
 Bill Baxter wrote:
 How is length not as simple as a color?  I don't get it.

 And consider the case of complex numbers.  Either the pair (real,imag)
 is stored or (modulus,argument) is stored.  Neither is more
 "fundamental" than the other as a representation.  Which one do you
 make a field and which one "standard D code"?

 --bb
hi bill, my fault, I mean distance.. (instead of length) Hope you agree with me that a colour (in the senses of E. Kant ) is something we can'T see as it is. but we gave and give it nevertheless a name : likewise red. Does not mean too much just :RED is a propetry. Now let`s compare that with distance calculation (without drifting too much away) RED is a property, Distance means necessarily a calculation. The question is ergo : Do we want pure behavior or math in our properties. IMO, behavior. This is what property means. so imutable proberty bool killbillv2 = false // is a read only getter .. (However to answer : ref... delegate and you have everything you need)
RED is a calculation if your color is stored in HSV space (or LAB space or CMYK, or...). In this case I'm assuming you are trying to retrieve the red content of a color. Otherwise if RED is some kind of constant, then it is stored in SOME representation. Then whenever you see "color = RED;" there MAY be a representation conversion depending on how the variable/property color does its storage internally. There are many numbers that exist without actually being stored anywhere. They are pretty useful to exploit since they require no memory ;)
Jul 29 2009
prev sibling parent Rainer Deyke <rainerd eldwood.com> writes:
BLS wrote:
 immutable property int i -> becomes :
 
 pure int get_i() nothrow
 {
  return i
 }
I can't figure out the semantics of this. Is 'i' a property, a variable, or both? If it's both, how do you syntactically distinguish between them? -- Rainer Deyke - rainerd eldwood.com
Jul 26 2009
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Nick Sabalausky, el 24 de julio a las 00:39 me escribiste:
  An alternate usage/definition syntax for properties.
 
 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4
 
 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
After reading all the threads again, I think the best proposal is the opGet_foo() / opSet_foo() for diferentiating functions and properties. I think is the more D-ish solution. I don't like the "_name" though, because it adds semantic infomation to the identifier, maybe a more template-like syntax can be used: class X { private int _foo; public string _bar; long opGet(baz)() { return _foo + _bar.lenght; } void opSet(baz)(int x) { assert(x >= _bar.lenght); _foo = x - _bar.lenght; } void f() { auto b = baz; // opGet(baz)() b += 10; baz = b; // opSet(baz)() } } I used an example without trivial properties because... well, you just use member variables for that. That's why I don't see real value in adding default properties getter/setters. I don't see DRY as a real problem either, for non-trivial properties. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- EL PRIMER MONITO DEL MILENIO... -- Crónica TV
Jul 25 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Leandro Lucarella wrote:
 Nick Sabalausky, el 24 de julio a las 00:39 me escribiste:
  An alternate usage/definition syntax for properties.

 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
After reading all the threads again, I think the best proposal is the opGet_foo() / opSet_foo() for diferentiating functions and properties. I think is the more D-ish solution. I don't like the "_name" though, because it adds semantic infomation to the identifier, maybe a more template-like syntax can be used:
That would involve changing template syntax to allow for identifiers to be passed as an argument. Besides, templates can't be used as virtual methods, so they can't be overridden and can't appear in interfaces.
 ...
 
 I used an example without trivial properties because... well, you just use
 member variables for that. That's why I don't see real value in adding
 default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
Jul 26 2009
next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Daniel Keep, el 27 de julio a las 01:09 me escribiste:
 
 
 Leandro Lucarella wrote:
 Nick Sabalausky, el 24 de julio a las 00:39 me escribiste:
  An alternate usage/definition syntax for properties.

 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
After reading all the threads again, I think the best proposal is the opGet_foo() / opSet_foo() for diferentiating functions and properties. I think is the more D-ish solution. I don't like the "_name" though, because it adds semantic infomation to the identifier, maybe a more template-like syntax can be used:
That would involve changing template syntax to allow for identifiers to be passed as an argument. Besides, templates can't be used as virtual methods, so they can't be overridden and can't appear in interfaces.
Syntax don't have to be changed, unless templates are not allowed (syntactically) in interfaces (I'm too lazy to check right now :). And template syntax don't have to change either. This is already valid AFAIK syntax AFAIK. What it has to be changed, is the semantics, because int opGet(foo)(); should be interpreted as a read property instead of a templated function.
 ...
 
 I used an example without trivial properties because... well, you just use
 member variables for that. That's why I don't see real value in adding
 default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
Yes, and...? -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- There is no such thing as right or wrong Only consequences
Jul 26 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Leandro Lucarella wrote:
 Daniel Keep, el 27 de julio a las 01:09 me escribiste:
 Leandro Lucarella wrote:
 Nick Sabalausky, el 24 de julio a las 00:39 me escribiste:
  An alternate usage/definition syntax for properties.

 http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

 Note that there are a few parts marked NEED HELP, that could use assistance 
 from someone with more expertise in this than me.
After reading all the threads again, I think the best proposal is the opGet_foo() / opSet_foo() for diferentiating functions and properties. I think is the more D-ish solution. I don't like the "_name" though, because it adds semantic infomation to the identifier, maybe a more template-like syntax can be used:
That would involve changing template syntax to allow for identifiers to be passed as an argument. Besides, templates can't be used as virtual methods, so they can't be overridden and can't appear in interfaces.
Syntax don't have to be changed, unless templates are not allowed (syntactically) in interfaces (I'm too lazy to check right now :). And template syntax don't have to change either. This is already valid AFAIK syntax AFAIK. What it has to be changed, is the semantics, because int opGet(foo)(); should be interpreted as a read property instead of a templated function.
Ok, I should have said "semantics" instead of syntax. The thing is you're proposing that template syntax doesn't *actually* mean a template if the identifier is "opGet". opGet effectively becomes a keyword; so you may as well just bite the bullet and add "property" as a keyword.
 ...

 I used an example without trivial properties because... well, you just use
 member variables for that. That's why I don't see real value in adding
 default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
Yes, and...?
You have an interface. One of the things it needs to do is provide access to a field. You can't just declare a field; you have to have an accessor. In most situations, the implementation will simply want to expose some internal field.
Jul 26 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Daniel Keep, el 27 de julio a las 02:29 me escribiste:
 Syntax don't have to be changed, unless templates are not allowed
 (syntactically) in interfaces (I'm too lazy to check right now :).
 
 And template syntax don't have to change either. This is already valid
 AFAIK syntax AFAIK. What it has to be changed, is the semantics, because
 int opGet(foo)(); should be interpreted as a read property instead of
 a templated function.
Ok, I should have said "semantics" instead of syntax. The thing is you're proposing that template syntax doesn't *actually* mean a template if the identifier is "opGet". opGet effectively becomes a keyword; so you may as well just bite the bullet and add "property" as a keyword.
Why it is a keyword? I know is a little controversial to change the meaning of template syntax based on the function name (and I think that's a good point for dismissing my proposal) but I really don't get why do you think that it's like adding a keyword. You don't have to make opGet a reserved word, you could use a variable named opGet if you want, the same you can use opCall or the other "magical" method names. I'm not really sure what is worse from a philosophical POV, if changing the template syntax meaning for opGet (opGet(prop)) or extract semantic information from a method name (opGet_prop). I think that the former looks a little cleaner at least =)
 I used an example without trivial properties because... well, you just use
 member variables for that. That's why I don't see real value in adding
 default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
Yes, and...?
You have an interface. One of the things it needs to do is provide access to a field. You can't just declare a field; you have to have an accessor. In most situations, the implementation will simply want to expose some internal field.
So, you think there should be an easy way to define default getter/setters? If that's what you're saying, I didn't saw how that is handled in your proposal, I'm sorry, I'll take a look again. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Un camión lleno de amigos, míos. Cada uno dando vueltas, en su cabeza. Mientras yo, sufro la picadura de mi propia abeja.
Jul 26 2009
prev sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Daniel Keep wrote:

 I used an example without trivial properties because... well, you just
 use member variables for that. That's why I don't see real value in
 adding default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
You do understand that properties with automatic backing storage would probably also not be allowed in interfaces. They'd have the same memory layout problems as fields. -- Michiel Helvensteijn
Jul 26 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Michiel Helvensteijn wrote:
 Daniel Keep wrote:
 
 I used an example without trivial properties because... well, you just
 use member variables for that. That's why I don't see real value in
 adding default properties getter/setters.
interface I { int opGet_value(); } You cannot use fields in an interface.
You do understand that properties with automatic backing storage would probably also not be allowed in interfaces. They'd have the same memory layout problems as fields.
*blink* You wouldn't declare a property with automatic backing in an interface; that would be specifying implementation which you're not allowed to do. I was demonstrating why trivial properties exist in real code. It's the *class* that would declare a property with automatic storage.
Jul 26 2009
parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Daniel Keep wrote:

 You do understand that properties with automatic backing storage would
 probably also not be allowed in interfaces. They'd have the same memory
 layout problems as fields.
*blink*
*blink*
 You wouldn't declare a property with automatic backing in an interface;
 that would be specifying implementation which you're not allowed to do.
 
 I was demonstrating why trivial properties exist in real code.  It's the
 *class* that would declare a property with automatic storage.
Ah, you're talking about the interface to a property, not the property itself. I see what you mean now. My mistake. -- Michiel Helvensteijn
Jul 26 2009