December 14, 2011
On 2011-12-14 13:27:57 +0000, "Regan Heath" <regan@netmail.co.nz> said:

> On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin
> <michel.fortin@michelf.com> wrote:
> 
>> By "code patterns", you mean something like this?
>> 
>> 	struct Foo
>> 	{
>> 		int getBar();
>> 		void setBar(int);
>> 	}
>> 
>> 	void main()
>> 	{
>> 		Foo foo;
>> 		int a = foo.bar;  // calls getBar()
>> 		foo.bar = a;      // calls setBar(a)
>> 	}
> 
> Why not something similar to C# syntax...

I know the basics of the C# property syntax, but how do you take the address of the getter with it? And how do you define array-member properties like you can do with functions? And how do you disambiguate access those array members properties if two imported modules define a property with the same name for an array? It basically has the same undefined areas as the current syntax using @property.

With the code pattern syntax used above:

	&foo.bar; // take the address of the returned value (if returned by ref)
	&foo.getBar; // take the address of the getter
	&foo.setBar; // take the address of the setter


	void getFront(int[] array) { return array[0]; }

	int[] a;
	a.front; // array-member property made from a module-level function

	
	// disambiguated access if two imported modules
	// define the same array-member property
	std.range.getFront(a);
	other.mod.getFront(a);


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

December 14, 2011
On Tue, 13 Dec 2011 18:08:43 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 12/13/11 5:14 PM, Peter Alexander wrote:
>> On 13/12/11 10:17 PM, Vladimir Panteleev wrote:
>>> On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:
>>>> There's a phrase in Romanian that quite applies: "From the lake into
>>>> the well".
>>>
>>> I believe the English version is "Out of the frying pan, into the
>>> fire" :)
>>>
>>> Inconsequential space-filler opinion: I am OK with @property, mainly
>>> because it's a common feature among PLs, it's better than nothing, and
>>> don't know better solutions.
>>
>> In my opinion, it's not better than nothing.
>>
>> What it gives you:
>>
>> 1. A bit of syntactic sugar.
>> 2. The ability to refactor member look up easily.
>>
>> What it costs:
>>
>> 1. Overloads syntax.
>> a. obj.field can now be an arbitrary function call.
>> b. May have arbitrary cost (e.g. T[].length)
>> 2. Complicating the language (proof: this discussion)
>> 3. Another thing to learn.
>> 4. Another thing for tools to process.
>>
>>
>> I don't think the syntax sugar it provides counts for anything really.
>>
>> The ability to refactor member look ups is nice, but I find that this
>> rarely occurs in practice and even when it occurs, it's not hard to
>> replace obj.field with obj.field() or obj.getField().
>>
>> The costs far outweigh the benefits IMO.
>
> We could have inferred property intention from the code pattern, without requiring any keyword. That solution (which was discussed and rejected in this newsgroup) was miles ahead from the drivel of @property we have now.
>
> I noticed there's a tunnel vision phenomenon when it comes to keyword-based solutions: once a special notation is on the table, there's no appreciation for anything else. That's what happened with lazy (another design misfire I'm very unhappy about) and with @property. I literally feel my heart rate getting up when I think of them.

@property wasn't my first choice, there were probably a dozen proposals on the table.  I liked the C# version the best: http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4

But here is the phenomenon I noticed:

N different solutions get proposed, and are debated by the community.  Walter is very vocal about what he doesn't like, but silent on other aspects (presumably because he is considering them?)

All of a sudden Walter picks a solution, then posts a thread to flesh out the details.  After that, it's hard to change his mind.

For the property debate, looking back through the newsgroups, it looks like Walter and you came up with a solution that nobody had proposed and nobody liked.  Then somehow @property was chosen.  Not sure how that happened or what the convincing argument was.

But you will notice in that discussion that many of the solutions did not involve keywords, and all were given equal air time (I don't see tunnel vision).

Thread: http://dfeed.kimsufi.thecybershadow.net/discussion/post/h53g3i$elk$1@digitalmars.com

I personally don't mind @property, even if there are better solutions.  It's not as horrible as you say IMO.

-Steve
December 14, 2011
I don't mind @property, usually I just create one property block for a
class, e.g.:
@property
{
    // funcs..
}
December 14, 2011
On Wed, 14 Dec 2011 13:50:09 -0000, Michel Fortin <michel.fortin@michelf.com> wrote:

> On 2011-12-14 13:27:57 +0000, "Regan Heath" <regan@netmail.co.nz> said:
>
>> On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin
>> <michel.fortin@michelf.com> wrote:
>>
>>> By "code patterns", you mean something like this?
>>>  	struct Foo
>>> 	{
>>> 		int getBar();
>>> 		void setBar(int);
>>> 	}
>>>  	void main()
>>> 	{
>>> 		Foo foo;
>>> 		int a = foo.bar;  // calls getBar()
>>> 		foo.bar = a;      // calls setBar(a)
>>> 	}
>>  Why not something similar to C# syntax...
>
> I know the basics of the C# property syntax, but how do you take the address of the getter with it?

I hadn't given this a lot of thought.  But, here goes.. :)

The compiler (whatever the syntax used) will generate the get/set functions internally.  So, it will technically be possible to take the address of both the getter and setter.

Using my suggested syntax there is only 1 property name 'bar' and typically the function called is determined by the usage, e.g.

Foo foo;
int a = foo.bar; // getter called
foo.bar = 4;     // setter called

So, what happens when we take the address..

Foo foo;
int delegate(void) getter = &foo.bar;  // takes the address of the getter
void delegate(in) setter = &foo.bar;   // takes the address of the setter

I think that works, what do you reckon?

> And how do you define array-member properties like you can do with functions?

I don't think we should call these "properties".  What we're actually doing is adding members to built in types which can have any number of arguments and are therefore they're not strictly "properties".  I think part of the confusion around properties comes from conflating these two ideas into one and calling them both "properties".

> And how do you disambiguate access those array members properties if two imported modules define a property with the same name for an array?

I'd like to split the "adding array members" feature away from "properties" and look at it again, specifically due to problem cases like this.  For example, in this case we could require the use of () for "adding array members" while for actual properties (user defined, on user defined types, using a c# like syntax or similar) we could require () not to be used.  I think that pretty much avoids the whole can of worms, doesn't it?

Regan

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
December 14, 2011
On 14/12/11 8:16 AM, Timon Gehr wrote:
> On 12/14/2011 12:35 AM, Peter Alexander wrote:
>> On 13/12/11 11:11 PM, Timon Gehr wrote:
>>> On 12/14/2011 12:14 AM, Peter Alexander wrote:
>>>> On 13/12/11 10:17 PM, Vladimir Panteleev wrote:
>>>>> On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu
>>>>> wrote:
>>>>>> There's a phrase in Romanian that quite applies: "From the lake into
>>>>>> the well".
>>>>>
>>>>> I believe the English version is "Out of the frying pan, into the
>>>>> fire" :)
>>>>>
>>>>> Inconsequential space-filler opinion: I am OK with @property, mainly
>>>>> because it's a common feature among PLs, it's better than nothing, and
>>>>> don't know better solutions.
>>>>
>>>> In my opinion, it's not better than nothing.
>>>>
>>>> What it gives you:
>>>>
>>>> 1. A bit of syntactic sugar.
>>>> 2. The ability to refactor member look up easily.
>>>>
>>>> What it costs:
>>>>
>>>> 1. Overloads syntax.
>>>> a. obj.field can now be an arbitrary function call.
>>>> b. May have arbitrary cost (e.g. T[].length)
>>>
>>> ??? T[].length is a field access, not a property function. It takes a
>>> small constant amount of time.
>>
>> Assigning to the length of an array may reallocate it, which is not a
>> small, nor constant amount of time.
>>
>> int[] a;
>> ...
>> a.length = n; // may invoke a GC allocation + O(n) memcpy
>
> OK, I see, thanks. I don't think it is problematic in this particular
> case though.

Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies.

Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with.

An example of this I encountered in practice was in Unity3D's libraries.

http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html

The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror.

"Each invocation of texture property allocates a new Texture2D."

That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this:

WWW www = ...;

for (int i = 0; i < www.texture.width; ++i)
    for (int j = 0; j < www.texture.height; ++j)
        buffer[i][j] = www.texture.GetPixel(i, j);

For a small 100x100 texture, that code allocates over 10,000, 100x100 textures.

Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.



December 14, 2011
On 12/14/2011 09:39 PM, Peter Alexander wrote:
> On 14/12/11 8:16 AM, Timon Gehr wrote:
>> On 12/14/2011 12:35 AM, Peter Alexander wrote:
>>> On 13/12/11 11:11 PM, Timon Gehr wrote:
>>>> On 12/14/2011 12:14 AM, Peter Alexander wrote:
>>>>> On 13/12/11 10:17 PM, Vladimir Panteleev wrote:
>>>>>> On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu
>>>>>> wrote:
>>>>>>> There's a phrase in Romanian that quite applies: "From the lake into
>>>>>>> the well".
>>>>>>
>>>>>> I believe the English version is "Out of the frying pan, into the
>>>>>> fire" :)
>>>>>>
>>>>>> Inconsequential space-filler opinion: I am OK with @property, mainly
>>>>>> because it's a common feature among PLs, it's better than nothing,
>>>>>> and
>>>>>> don't know better solutions.
>>>>>
>>>>> In my opinion, it's not better than nothing.
>>>>>
>>>>> What it gives you:
>>>>>
>>>>> 1. A bit of syntactic sugar.
>>>>> 2. The ability to refactor member look up easily.
>>>>>
>>>>> What it costs:
>>>>>
>>>>> 1. Overloads syntax.
>>>>> a. obj.field can now be an arbitrary function call.
>>>>> b. May have arbitrary cost (e.g. T[].length)
>>>>
>>>> ??? T[].length is a field access, not a property function. It takes a
>>>> small constant amount of time.
>>>
>>> Assigning to the length of an array may reallocate it, which is not a
>>> small, nor constant amount of time.
>>>
>>> int[] a;
>>> ...
>>> a.length = n; // may invoke a GC allocation + O(n) memcpy
>>
>> OK, I see, thanks. I don't think it is problematic in this particular
>> case though.
>
> Well, it is a little. It makes it difficult to scan code looking for GC
> allocations, or even scan code looking for inefficiencies.
>
> Obviously I know now that I have to look for .length assignments on
> arrays, but it can be quite horrific when looking at code that uses
> third party libraries that you aren't familiar with.
>

Oh yes, certainly. That is what I meant by 'in this particular case': Because the .length on arrays is built into the language, you know that it must allocate as soon as you have a sufficiently good mental model of how dynamic arrays work. (and anyone who wants to write effective D code that uses dynamic arrays should)

> An example of this I encountered in practice was in Unity3D's libraries.
>
> http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html
>
> The WWW class has a 'texture' property. A small sentence in the middle
> of its documentation reveals the horror.
>
> "Each invocation of texture property allocates a new Texture2D."
>
> That's right. Every time you read WWW.texture, it allocates a large
> chunk of memory. In my particular case, I was copying the pixels from
> the texture into another array, something like this:
>
> WWW www = ...;
>
> for (int i = 0; i < www.texture.width; ++i)
> for (int j = 0; j < www.texture.height; ++j)
> buffer[i][j] = www.texture.GetPixel(i, j);
>
> For a small 100x100 texture, that code allocates over 10,000, 100x100
> textures.
>
> Luckily, that was horrific enough to prompt me to investigate, but a
> less obvious problem would have likely slipped past me unnoticed.
>

oO. That is quite an API design problem there.


December 14, 2011
Peter Alexander:

> Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies.
> 
> Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with.

A proposed idea to help is to add a compilation switch that produces a list of all heap allocation points in the current compilation unit (in Bugzilla there is a related issue that asks for a list of just heap allocations of closures).

Bye,
bearophile
December 14, 2011
On Wed, 14 Dec 2011 15:39:55 -0500, Peter Alexander <peter.alexander.au@gmail.com> wrote:

> On 14/12/11 8:16 AM, Timon Gehr wrote:
>> On 12/14/2011 12:35 AM, Peter Alexander wrote:
>>> On 13/12/11 11:11 PM, Timon Gehr wrote:
>>>> On 12/14/2011 12:14 AM, Peter Alexander wrote:
>>>>> On 13/12/11 10:17 PM, Vladimir Panteleev wrote:
>>>>>> On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu
>>>>>> wrote:
>>>>>>> There's a phrase in Romanian that quite applies: "From the lake into
>>>>>>> the well".
>>>>>>
>>>>>> I believe the English version is "Out of the frying pan, into the
>>>>>> fire" :)
>>>>>>
>>>>>> Inconsequential space-filler opinion: I am OK with @property, mainly
>>>>>> because it's a common feature among PLs, it's better than nothing, and
>>>>>> don't know better solutions.
>>>>>
>>>>> In my opinion, it's not better than nothing.
>>>>>
>>>>> What it gives you:
>>>>>
>>>>> 1. A bit of syntactic sugar.
>>>>> 2. The ability to refactor member look up easily.
>>>>>
>>>>> What it costs:
>>>>>
>>>>> 1. Overloads syntax.
>>>>> a. obj.field can now be an arbitrary function call.
>>>>> b. May have arbitrary cost (e.g. T[].length)
>>>>
>>>> ??? T[].length is a field access, not a property function. It takes a
>>>> small constant amount of time.
>>>
>>> Assigning to the length of an array may reallocate it, which is not a
>>> small, nor constant amount of time.
>>>
>>> int[] a;
>>> ...
>>> a.length = n; // may invoke a GC allocation + O(n) memcpy
>>
>> OK, I see, thanks. I don't think it is problematic in this particular
>> case though.
>
> Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies.
>
> Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with.
>
> An example of this I encountered in practice was in Unity3D's libraries.
>
> http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html
>
> The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror.
>
> "Each invocation of texture property allocates a new Texture2D."
>
> That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this:
>
> WWW www = ...;
>
> for (int i = 0; i < www.texture.width; ++i)
>      for (int j = 0; j < www.texture.height; ++j)
>          buffer[i][j] = www.texture.GetPixel(i, j);
>
> For a small 100x100 texture, that code allocates over 10,000, 100x100 textures.
>
> Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.

Yes, but length as a read property does not allocate anything (nor does reducing the length).  In fact, length as a read property reduces to a field access (it is a language builtin, after all).

Would you expect that setting the length of an array to a *larger* size would not allocate?  Your example shows something that doesn't look like it should be costly, but it actually is.  Expanding length *looks* costly (and it is).

You do have a point that it shouldn't necessarily be a property.  I also don't think dup, reverse, or sort should be array properties.  But these are pieces of the language that have been there forever.  To change them now would be disruptive for very little gain.

-Steve
December 14, 2011
Steven Schveighoffer:

> I also don't think dup, reverse, or sort should be array properties.  But these are pieces of the language that have been there forever.  To change them now would be disruptive for very little gain.

sort and reverse properties will be deprecated and later removed.

Bye,
bearophile
December 14, 2011
On 14/12/11 8:59 PM, Steven Schveighoffer wrote:
> On Wed, 14 Dec 2011 15:39:55 -0500, Peter Alexander
> <peter.alexander.au@gmail.com> wrote:
>
>> On 14/12/11 8:16 AM, Timon Gehr wrote:
>>> On 12/14/2011 12:35 AM, Peter Alexander wrote:
>>>> On 13/12/11 11:11 PM, Timon Gehr wrote:
>>>>> On 12/14/2011 12:14 AM, Peter Alexander wrote:
>>>>>> On 13/12/11 10:17 PM, Vladimir Panteleev wrote:
>>>>>>> On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu
>>>>>>> wrote:
>>>>>>>> There's a phrase in Romanian that quite applies: "From the lake
>>>>>>>> into
>>>>>>>> the well".
>>>>>>>
>>>>>>> I believe the English version is "Out of the frying pan, into the
>>>>>>> fire" :)
>>>>>>>
>>>>>>> Inconsequential space-filler opinion: I am OK with @property, mainly
>>>>>>> because it's a common feature among PLs, it's better than
>>>>>>> nothing, and
>>>>>>> don't know better solutions.
>>>>>>
>>>>>> In my opinion, it's not better than nothing.
>>>>>>
>>>>>> What it gives you:
>>>>>>
>>>>>> 1. A bit of syntactic sugar.
>>>>>> 2. The ability to refactor member look up easily.
>>>>>>
>>>>>> What it costs:
>>>>>>
>>>>>> 1. Overloads syntax.
>>>>>> a. obj.field can now be an arbitrary function call.
>>>>>> b. May have arbitrary cost (e.g. T[].length)
>>>>>
>>>>> ??? T[].length is a field access, not a property function. It takes a
>>>>> small constant amount of time.
>>>>
>>>> Assigning to the length of an array may reallocate it, which is not a
>>>> small, nor constant amount of time.
>>>>
>>>> int[] a;
>>>> ...
>>>> a.length = n; // may invoke a GC allocation + O(n) memcpy
>>>
>>> OK, I see, thanks. I don't think it is problematic in this particular
>>> case though.
>>
>> Well, it is a little. It makes it difficult to scan code looking for
>> GC allocations, or even scan code looking for inefficiencies.
>>
>> Obviously I know now that I have to look for .length assignments on
>> arrays, but it can be quite horrific when looking at code that uses
>> third party libraries that you aren't familiar with.
>>
>> An example of this I encountered in practice was in Unity3D's libraries.
>>
>> http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html
>>
>> The WWW class has a 'texture' property. A small sentence in the middle
>> of its documentation reveals the horror.
>>
>> "Each invocation of texture property allocates a new Texture2D."
>>
>> That's right. Every time you read WWW.texture, it allocates a large
>> chunk of memory. In my particular case, I was copying the pixels from
>> the texture into another array, something like this:
>>
>> WWW www = ...;
>>
>> for (int i = 0; i < www.texture.width; ++i)
>> for (int j = 0; j < www.texture.height; ++j)
>> buffer[i][j] = www.texture.GetPixel(i, j);
>>
>> For a small 100x100 texture, that code allocates over 10,000, 100x100
>> textures.
>>
>> Luckily, that was horrific enough to prompt me to investigate, but a
>> less obvious problem would have likely slipped past me unnoticed.
>
> Yes, but length as a read property does not allocate anything (nor does
> reducing the length). In fact, length as a read property reduces to a
> field access (it is a language builtin, after all).

Length reading is fine.

> Would you expect that setting the length of an array to a *larger* size
> would not allocate? Your example shows something that doesn't look like
> it should be costly, but it actually is. Expanding length *looks* costly
> (and it is).

It's not that I wouldn't expect it (I would), but at a glance (i.e. without thinking about it) you wouldn't notice it. It just looks like a member assignment.

It's like overloading operator& in C++. It takes something that had one meaning and changes it into something else without a change in syntax. It's essentially the syntactic version of function hijacking.

> You do have a point that it shouldn't necessarily be a property. I also
> don't think dup, reverse, or sort should be array properties. But these
> are pieces of the language that have been there forever. To change them
> now would be disruptive for very little gain.

Agreed.

1 2 3 4 5 6 7 8 9 10 11
Next ›   Last »