January 09, 2009
"Miles" <_______@_______.____> wrote in message news:gk6f9p$1jve$1@digitalmars.com...
> Nick Sabalausky wrote:
>> True, but my main point was, however the language ends up handling the details of property getters/setters, it's not going to be as general as ordinary functions, and thus certain aspects of the syntax can/should be simplified.
>
> In this case, simplifying would be more complex.
>
> Under the hood, when you define getters and setters, you are defining functions, and function overloading is an inherent feature of the language. In fact, the current "property" feature of D already supports many overloaded setters for different types, since they are just normal functions.
>
> For example, consider the property definition:
>
> public property int width {
>   get() { return width; }
>   set(int value) { width = value; }
>   set(float value) { width = value + 0.5; }
> }
>
> That would generate overloaded functions with different signatures, lets say that, under the hood, the compiler generates:
>
> int __get_width();
> int __set_width(int value);
> int __set_width(float value);
>
> Then, when code that accesses the property is compiled, something that looks like
>
> width = x;
>
> will, in fact, be threated as
>
> __set_width(x);
>
> and so, the compiler will choose the appropriate __set_width() function with the signature that matches the above call.
>
> So, restricting a property to have only a single setter will end up creating unnecessary restrictions for something that is already native to the language.
>
>> You're absolutely right that properties need to be able to return an
>> rvalue
>> from an assignment, but I see no reason why that can't or shouldn't be
>> transparent to the person writing the property.
>
> They could, no problem.
>
>> I'm still not 100% convinced that we should be using properties to do
>> type
>> conversions, although I suppose it may have some legitimate uses...
>
> It is not just about type conversions... it is that the feature is already something natural for the language.
>


Ok, you've convinced me on this.


>> But anyway, even with the possibility of a property handling multiple
>> types,
>> I still don't think it means we can't or shouldn't have a nicely trimmed
>> syntax for the more typical cases:
>>
>> property int x
>> {
>>     set { this = this.new; }
>>     get { return this; }
>>
>>     set char[] { this = StringToInt(this.new); }
>>     get char[] { return IntToString(this); } // If we ever got
>> overload-on-return-value
>> }
>
> Not for getters, please... the type of the getter should be the type of the property, or that would create a lot of complexity for the language (that is also the reason you don't overload functions based on the return type).

Well, like I said, *If* we were to get overload-on-return-value. Not that I'm itching for it or anything. I've just seen the idea discussed before and if it hypothetically were to happen, then the above could work as a getter equivilent.


January 09, 2009
Miles wrote:
> 
> Both the getter and the setter should return an rvalue. Properties exist so that they are interchangeable with real member variables. Something that is possible with member variables MUST also be possible with properties, in a transparent way for any code outside the class.
> 

I agree, though let's not fool ourselves, there is at least one corner case:

property int foo
{
    get{ ... }
    set{ ... }
}

auto bar = &foo;
what happens when someone writes this?

I've tried this in C# and it is simply forbidden.  I am OK with this, though I'd love it if there was a better way.
January 09, 2009
Chad J wrote:
> Miles wrote:
>> Both the getter and the setter should return an rvalue. Properties exist
>> so that they are interchangeable with real member variables. Something
>> that is possible with member variables MUST also be possible with
>> properties, in a transparent way for any code outside the class.
>>
>
> I agree, though let's not fool ourselves, there is at least one corner case:
>
> property int foo
> {
>      get{ ... }
>      set{ ... }
> }
>
> auto bar =&foo;
> what happens when someone writes this?
>
> I've tried this in C# and it is simply forbidden.  I am OK with this,
> though I'd love it if there was a better way.

that's solvable. as I noted in a previous post, a property seems to me to be mainly syntax sugar for a struct like in the following snippet:

class A {
	struct Prop {
		int internal;
		int opCall() { return internal; }
		void opAssign(int value) { internal = value; }
	}
	public Prop prop;
	...
}

void main() {
	auto a = new A;
	int num = a.prop;
	a.prop = 9;
	auto foo = &a.prop; // what happens here?
	...
}

foo can be the address of "prop" (struct instance) in the above code.
this means that:
*foo = ...; is translated to *foo.opAssign(...);
and similarly: auto bar = *foo; will be auto bar = *foo.opCall();

the only issue here is what will be the type of foo if D provides the syntax sugar for all this. maybe define such types as special property types - for a given property "foo" in class "Bar" the type of the property will be "Bar.__fooPropertyType".
January 09, 2009
On 2009-01-09 05:47:26 -0500, Yigal Chripun <yigal100@gmail.com> said:

> that's solvable. as I noted in a previous post, a property seems to me to be mainly syntax sugar for a struct like in the following snippet:
> 
> class A {
> 	struct Prop {
> 		int internal;
> 		int opCall() { return internal; }
> 		void opAssign(int value) { internal = value; }
> 	}
> 	public Prop prop;
> 	...
> }

Hum, that doesn't really work. Getter and setters of the property have access to the whole class scope, and can call functions of that class. If you wanted to extract a property from a class, you'd have to do it by keeping a pointer to the class, not the property's value:

	class A {
		private int internal;
		struct Prop {
			A outerClass;
			int opCall() { return outerClass.internal; }
			void opAssign(int value) { outerClass.internal = value; }
		}
		public Prop prop;
	}


-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

January 09, 2009
Chad J wrote:
> I agree, though let's not fool ourselves, there is at least one corner case:
> 
> property int foo
> {
>     get{ ... }
>     set{ ... }
> }
> 
> auto bar = &foo;
> what happens when someone writes this?

Yes, this is a corner case. If the getter is not set to return an lvalue, that makes as much sense as trying to get a reference from an rvalue, like &5.

> I've tried this in C# and it is simply forbidden.  I am OK with this, though I'd love it if there was a better way.

That is expected behavior. Although able to emulate variables, properties are not variables, and neither functions. They could be seen as a collection of delegates. In some cases, the compiler may allow you to retrieve individual delegates from the property through some syntax, like:

	auto bar = & property(foo).get;
January 09, 2009
Nick Sabalausky wrote:
> Well, like I said, *If* we were to get overload-on-return-value. Not that I'm itching for it or anything. I've just seen the idea discussed before and if it hypothetically were to happen, then the above could work as a getter equivilent.

Ok. But I think such feature would create a mess. For example:

	int    func1() { ... }
	char[] func1() { ... }

	void   func2(int x) { ... }
	void   func2(char[] x) { ... }

	func2(func1());	// what is the expected behavior?

When you are inferring types, you need somewhere to anchor the compiler decision, either on the sender or on the receiver side.
January 09, 2009
Nick Sabalausky wrote:
> This proposal doesn't prevent any of that. Suppose our syntax was like in the example above. I would still be able to do something like this:
> 
> ---------------
> protected int _var;
> public property char[] var
> {
>     // char[] internalValue is still defined,
>     // but gets optimized away since it's never used.
> 
>     get { return ToString(_var); }
>     set { _var = ToInt($); }
> }
> ---------------

The problem I see with this is that it complicates the implementation of properties. Properties are just collections of delegates, perhaps even optimized to contain only a single frame pointer for multiple function pointers. Properties may appear in contexts where you can't have member variables (e.g., interfaces).

> ---------------
> class Foo
> {
>     public property int myProp
>     {
>         get { return internalValue; }
>         set { internalValue = $; }
>     }
> 
>     public bar()
>     {
>         Stdout.formatln("{}", myProp.internalValue);
>     }
> }
> ---------------

Won't work, not like that. For the compiler, that is difficult to distinguish from calling the getter for myProp (that returns an int), and trying to access a member variable called "internalValue" from that int instance.

The compiler could provide some syntax to disambiguate property's members from it's value's members. Perhaps:

	property(myProp).internalValue;

In this case, property(...) tells the compiler to handle the argument as the property itself, without calling the getter. But requiring that syntax just sucks. I find it better to have the value in another variable.
January 09, 2009
Michel Fortin wrote:
> On 2009-01-09 05:47:26 -0500, Yigal Chripun <yigal100@gmail.com> said:
>
>> that's solvable. as I noted in a previous post, a property seems to me
>> to be mainly syntax sugar for a struct like in the following snippet:
>>
>> class A {
>> struct Prop {
>> int internal;
>> int opCall() { return internal; }
>> void opAssign(int value) { internal = value; }
>> }
>> public Prop prop;
>> ...
>> }
>
> Hum, that doesn't really work. Getter and setters of the property have
> access to the whole class scope, and can call functions of that class.
> If you wanted to extract a property from a class, you'd have to do it by
> keeping a pointer to the class, not the property's value:
>
> class A {
> private int internal;
> struct Prop {
> A outerClass;
> int opCall() { return outerClass.internal; }
> void opAssign(int value) { outerClass.internal = value; }
> }
> public Prop prop;
> }
>
>

instead of manually doing it within the struct just do s/struct/class to my code. this will solve it since inner classes have an "outer" pointer to the containing class instance.
I wasn't trying to give the best and most general solution, just to point out that there is a straight forward solution to this.
January 09, 2009

Michiel Helvensteijn wrote:
> [Condensed: syntax sucks, let's introduce more!]

I might be old fashioned (get offa mah lawn!), but I've always found something like the following quite acceptable:

class Foo
{
    mixin(properties
    ("
        rw int bar;
        ro float baz;
        wo Foo zyzzy;
    "));
}

I know I had a CTFE function lying around that would parse that and generate the code for it.  I agree that C# has a nicer syntax for this, but with CTFE/templates and string mixins, we can have whatever syntax we damn well want.

Hell, I used this in a prototype game engine to generate CVars; it'd generate the properties, the backing store, the hooking code, event registration, etc.  One line generated about 10-20 lines of boilerplate for me; C# can't do that!

Why change the language when you can just abuse it's already-existing features? :D

  -- Daniel "downs is my hero"
January 09, 2009
== Quote from Daniel Keep (daniel.keep.lists@gmail.com)'s article
> Why change the language when you can just abuse it's already-existing
> features? :D
>    -- Daniel "downs is my hero"

This is precisely the attitude that left C++ with all of the cruft and baggage it has.  Yes, if something can be implemented *elegantly, efficiently, and with clean syntax* in a library, then it doesn't belong in the core language.  Yes, powerful language features like templates, mixins, operator overloading, etc. are great for abusing when you need something that's not universal enough to be in the core language.

The flip side is that, the more you rely on libraries (whether your personal snippet library or an "official" library) that use hacks like this, the more you're building a house of cards.  When you build hacks on top of other hacks, and build these on top of still more hacks (think STL), you're basically asking ugly syntax, odd corner cases, and the exposure of obscure implementation bugs.  This is why things like arrays, strings and delegates belong in the core language. Since properties are just as universal, I believe the same argument can be made for them.