January 18, 2012
On 1/18/12 8:34 AM, Steven Schveighoffer wrote:
> On Wed, 18 Jan 2012 09:13:37 -0500, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 1/18/12 7:44 AM, Steven Schveighoffer wrote:
>>> The solution is easy, just don't start the discussion. Make a decision
>>> (property or no), and that's the end of it. My intuition says that you
>>> will purposely make the *wrong* choice just to try and get others to
>>> complain so you can "be right".
>>
>> Well in this case I am right :o). We did a poor job at designing
>> properties. Anyhow, I honestly asked simply because I found no clear
>> cut decision. My intuition was that byXxx should be a property but I
>> asked Walter whose intuition said it should be a method. So we agreed
>> to ask the newsgroup.
>
> Then I withdraw the "being spiteful" suggestion, it was probably unfair.
>
> But the "I told you" didn't set the tone very well for this discussion :)

Indeed I told you all! Every time we add anything, there's going to be sh... stuff like this.

>> I understand this point. It doesn't reduce the frustration that we
>> have a feature that does not palpably improve the language.
>
> Disagree on both points :) @property with enforcement is the right
> answer, it improves the language significantly, bringing it in line with
> most other property-enabled C-like languages.

This is not an argument. It's good because it's like in other languages where it's supposed to be good. And it's not "the right answer" when there's nothing to be answered.

>>> And if I may add my opinion, byValue and byKey are properties.
>>
>> I agree. The current code has them as properties. My thoughts are, a
>> property should reasonably replace a member variable (of which syntax
>> it mimics). So x.length should be property, x.dup shouldn't. Now byXxx
>> can be considered member variables but only as long as it's not
>> considered an lvalue: r.byKey.popFront() does nothing interesting, but
>> would do if r.byKey were actually a member variable. I think that
>> distinction still does not impair byXxx's right to be a property.
>
> I think the difference between what should be a property and what
> shouldn't is not black and white. There is no easy way to define it.

If that's the case, then there shouldn't be a black-and-white distinction in the language about it.

> The best I can come up with is, if it gets something that is logically a
> piece of the object, then it should be a property (even if it makes a
> copy of that something). If it creates something separate from the
> object, or modifies the object, it should be a method.

The fact that reasonable people disagree, and that choosing one way or another has zero impact on the quality of the code, makes this feature a costly mistake.


Andrei

January 18, 2012
On Wed, 18 Jan 2012 09:40:00 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 1/18/12 8:34 AM, Steven Schveighoffer wrote:
>> On Wed, 18 Jan 2012 09:13:37 -0500, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 1/18/12 7:44 AM, Steven Schveighoffer wrote:
>>>> The solution is easy, just don't start the discussion. Make a decision
>>>> (property or no), and that's the end of it. My intuition says that you
>>>> will purposely make the *wrong* choice just to try and get others to
>>>> complain so you can "be right".
>>>
>>> Well in this case I am right :o). We did a poor job at designing
>>> properties. Anyhow, I honestly asked simply because I found no clear
>>> cut decision. My intuition was that byXxx should be a property but I
>>> asked Walter whose intuition said it should be a method. So we agreed
>>> to ask the newsgroup.
>>
>> Then I withdraw the "being spiteful" suggestion, it was probably unfair.
>>
>> But the "I told you" didn't set the tone very well for this discussion :)
>
> Indeed I told you all! Every time we add anything, there's going to be sh... stuff like this.
>
>>> I understand this point. It doesn't reduce the frustration that we
>>> have a feature that does not palpably improve the language.
>>
>> Disagree on both points :) @property with enforcement is the right
>> answer, it improves the language significantly, bringing it in line with
>> most other property-enabled C-like languages.
>
> This is not an argument. It's good because it's like in other languages where it's supposed to be good. And it's not "the right answer" when there's nothing to be answered.

All of your arguments were subjective "doesn't palpably change the language" "all it does it generate these [in your opinion] useless discussions", why can't mine be?

And you did say you were right, when clearly you are wrong :)

>
>>>> And if I may add my opinion, byValue and byKey are properties.
>>>
>>> I agree. The current code has them as properties. My thoughts are, a
>>> property should reasonably replace a member variable (of which syntax
>>> it mimics). So x.length should be property, x.dup shouldn't. Now byXxx
>>> can be considered member variables but only as long as it's not
>>> considered an lvalue: r.byKey.popFront() does nothing interesting, but
>>> would do if r.byKey were actually a member variable. I think that
>>> distinction still does not impair byXxx's right to be a property.
>>
>> I think the difference between what should be a property and what
>> shouldn't is not black and white. There is no easy way to define it.
>
> If that's the case, then there shouldn't be a black-and-white distinction in the language about it.

The language defines the mechanisms of enforcement, not when to use them.  Any time it's a human interpretation of something, the language has to step back and say "you're the boss, you tell me what to do and I'll enforce it."  The problem with the current situation is that there is no enforcement.  You can suggest a certain usage, and be completely ignored.

I liken it to case sensitivity.  We could say symbol names aren't case sensitive, and that anyone can use any casing to call a function.  But then the author of the function has lost control of what his function names look like.

Since D enforced case sensitivity from the beginning, there is never a post saying "should this function be called isUseless or IsUseless.  Grr... why on earth do we have case sensitivity anyways, it just generates useless discussions!"

But go try to suggest to some language community that has case insensitive symbols that they should add case sensitivity enforcement, and you'll get shit like that.

>
>> The best I can come up with is, if it gets something that is logically a
>> piece of the object, then it should be a property (even if it makes a
>> copy of that something). If it creates something separate from the
>> object, or modifies the object, it should be a method.
>
> The fact that reasonable people disagree, and that choosing one way or another has zero impact on the quality of the code, makes this feature a costly mistake.

The error in that sentence is "has zero impact."  It has an impact, about as significant as choosing a good symbol name.

-Steve
January 18, 2012
On Wednesday, January 18, 2012 08:13:37 Andrei Alexandrescu wrote:
> On 1/18/12 7:44 AM, Steven Schveighoffer wrote:
> > If you think the names of things aren't
> > important, name them whatever you want, but at least you as the author
> > get to choose instead of the user.
> 
> I understand this point. It doesn't reduce the frustration that we have a feature that does not palpably improve the language.

There are those of us who _do_ think that it palpably improves the language. I think that the issue is more that we have a feature that is rather divisive as to whether it's an improvement or not. Some think that it definitely is, and some think it definitely isn't. It's not one of those features where pretty much everyone agrees that it's an improvement.

- Jonathan M Davis
January 18, 2012
Steven Schveighoffer:

> There is one significant problem with changing aa.keys to be a lazy range instead of an array.  This is valid code (and does exist in the wild):
> 
> foreach(k; aa.keys)
> {
>     if(shouldRemove(k))
>        aa.remove(k);
> }
> 
> This would silently start crashing programs if we changed the behavior of keys.

On this topic see also: http://d.puremagic.com/issues/show_bug.cgi?id=4179

Bye,
bearophile
January 18, 2012
On Wed, 18 Jan 2012 08:59:57 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 1/18/12 7:20 AM, Steven Schveighoffer wrote:
>> The only array-specific properties of an array that the compiler should
>> worry about are ptr and length. Everything else should be a library
>> function.
>
> Even ptr and length should be in the library. The slice structure should be defined in object.d. The only business the compiler has is to lower the T[] type syntax and the [ ... ] literal syntax to .object.Slice!T and .object.slice(...) form, and to make sure that typeof(T[]) is not struct (although factually it is).

That is debatable.  The exact semantics of length are not repeatable in the library, where a get is a simple field access, yet a set calls a method.  To achieve the same you would have to require -inline on the compile line.

At that point, we have to say "what does it buy us".  The function to set the length is already a library function, which is changable outside the compiler.  What do we gain besides saying the language is purer?

If we change dup and idup to be library defined, we can get benefits, such as taking advantage of pure being able to implicitly cast to immutable.

-Steve
January 18, 2012
On 1/18/12 12:04 PM, Steven Schveighoffer wrote:
> On Wed, 18 Jan 2012 08:59:57 -0500, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 1/18/12 7:20 AM, Steven Schveighoffer wrote:
>>> The only array-specific properties of an array that the compiler should
>>> worry about are ptr and length. Everything else should be a library
>>> function.
>>
>> Even ptr and length should be in the library. The slice structure
>> should be defined in object.d. The only business the compiler has is
>> to lower the T[] type syntax and the [ ... ] literal syntax to
>> .object.Slice!T and .object.slice(...) form, and to make sure that
>> typeof(T[]) is not struct (although factually it is).
>
> That is debatable. The exact semantics of length are not repeatable in
> the library, where a get is a simple field access, yet a set calls a
> method. To achieve the same you would have to require -inline on the
> compile line.
>
> At that point, we have to say "what does it buy us". The function to set
> the length is already a library function, which is changable outside the
> compiler. What do we gain besides saying the language is purer?

1. Offer the runtime the possibility of tweaking the efficiency of the abstraction

2. Smaller and simpler compiler

3. Detecting design and implementation bugs in the language (we found a lot while porting the associative arrays)

4. Uniform built-in type behavior and user-defined type behavior, which is a boon for generic code and generally for the language size and understandability

As a related example, look at how simple and efficient byKey and byValue are thanks to migrating hashes into the runtime.


Andrei
January 18, 2012
On Wed, 18 Jan 2012 14:11:16 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 1/18/12 12:04 PM, Steven Schveighoffer wrote:
>> On Wed, 18 Jan 2012 08:59:57 -0500, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 1/18/12 7:20 AM, Steven Schveighoffer wrote:
>>>> The only array-specific properties of an array that the compiler should
>>>> worry about are ptr and length. Everything else should be a library
>>>> function.
>>>
>>> Even ptr and length should be in the library. The slice structure
>>> should be defined in object.d. The only business the compiler has is
>>> to lower the T[] type syntax and the [ ... ] literal syntax to
>>> .object.Slice!T and .object.slice(...) form, and to make sure that
>>> typeof(T[]) is not struct (although factually it is).
>>
>> That is debatable. The exact semantics of length are not repeatable in
>> the library, where a get is a simple field access, yet a set calls a
>> method. To achieve the same you would have to require -inline on the
>> compile line.
>>
>> At that point, we have to say "what does it buy us". The function to set
>> the length is already a library function, which is changable outside the
>> compiler. What do we gain besides saying the language is purer?
>
> 1. Offer the runtime the possibility of tweaking the efficiency of the abstraction

The runtime already implements the abstraction.  All that the compiler does special is glue the property to the function call.

> 2. Smaller and simpler compiler

Maybe relevant for new compilers.

> 3. Detecting design and implementation bugs in the language (we found a lot while porting the associative arrays)

There is only one function to set length.  It's not quite comparable to the entire set of associative array functionality.  Though as someone who has mostly rewritten it, I can say it's not a trivial function, and may still have bugs in it.  However, I don't see changing the entity who glues the property to the function is going to find bugs in the function.

> 4. Uniform built-in type behavior and user-defined type behavior, which is a boon for generic code and generally for the language size and understandability

This I agree with, it makes the language uniformly implemented, which makes things simpler to understand/implement.  But it already works, and works rather well.  This is my point, all we gain is being able to say the language is simpler/purer.

> As a related example, look at how simple and efficient byKey and byValue are thanks to migrating hashes into the runtime.

Not to mention *possible* :)

-Steve
January 18, 2012
"Jacob Carlborg" <doob@me.com> wrote in message news:jf6e7a$1929$1@digitalmars.com...
>
> method:
> no parameters - parentheses are optional

FWIW, I always do a double-take when I see code like:

functionName;
//or
object.functionName;

It sets off all mannar of "no-effect expression!" bells and buzzers in my head every time I look at it, which I then have to silence.



January 18, 2012
Le 17/01/2012 07:48, Andrei Alexandrescu a écrit :
> I hate I must ask this:
>
> int[string] aa;
> foreach (k; aa.byKey) { ... }
>
> or
>
> int[string] aa;
> foreach (k; aa.byKey()) { ... }
>
>
>
> Thanks,
>
> Andrei "I told you" Alexandrescu

I vote for the methods.

Cheers,

Olivier
January 18, 2012
"Nick Sabalausky" <a@a.a> wrote in message news:jf79sh$2l7b$1@digitalmars.com...
> "Jacob Carlborg" <doob@me.com> wrote in message news:jf6e7a$1929$1@digitalmars.com...
>>
>> method:
>> no parameters - parentheses are optional
>
> FWIW, I always do a double-take when I see code like:
>
> functionName;
> //or
> object.functionName;
>
> It sets off all mannar of "no-effect expression!" bells and buzzers in my head every time I look at it, which I then have to silence.
>

Also it doesn't help that using the function name by itself (with no parens or &) can be used to pass a function as a template alias parameter (or just alias a function), instead of passing the result of the function call as the argument.

Plus I've spent time in other langauges where using a function name without parens is the way to refer to a function itself, rather than invoke the function. That's something I very much like: "foo" refers to the function, "foo()" calls the function. Period. End of story. But in D, while "foo()" calls a function, refering to a function is a mess: usually it's "&foo", but if you're aliasing it or passing it as a template alias parameter than it's "foo". But then if you use "foo" in other places, it calls the function instead of referring to it! Bleh!!! Messy, messy.