January 18, 2012
On Tue, 17 Jan 2012 13:41:07 -0500, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 01/17/2012 02:14 PM, Alex Rønne Petersen wrote:
>> On 17-01-2012 13:41, Nick Sabalausky wrote:
>>> "Jonathan M Davis"<jmdavisProg@gmx.com> wrote in message
>>> news:mailman.496.1326793835.16222.digitalmars-d@puremagic.com...
>>>> On Tuesday, January 17, 2012 09:07:04 Alex Rønne Petersen wrote:
>>>>> On 17-01-2012 07:48, Andrei Alexandrescu wrote:
>>>>>> I hate I must ask this:
>>>>>>
>>>>>> int[string] aa;
>>>>>> foreach (k; aa.byKey) { ... }
>>>>>>
>>>>>> or
>>>>>>
>>>>>> int[string] aa;
>>>>>> foreach (k; aa.byKey()) { ... }
>>>>>>
>>>>>
>>>>> The "by" in the name is way too awkward for a property. If it was just
>>>>> named "keys" and "values", it would've been perfectly fine to make them
>>>>> properties, but the "by" just looks awkward when you "call" them as
>>>>> properties.
>>>>>
>>>>> As far as efficiency goes, I don't think these perform any work that is
>>>>> heavy enough to warrant not making them properties. (I can't say that
>>>>> same for .dup/.idup... I still don't get why those are properties, at
>>>>> all.)
>>>>
>>>> Agreed. If it were keys and values, then a property would make sense.
>>>> However,
>>>> since it's byKey and byValue, I don't think that it makes as much
>>>> sense. It
>>>> _is_ a bit of a weird case though, since byKey and byValue are neither
>>>> nouns
>>>> nor verbs.
>>>>
>>>
>>> You're all getting hung up on the trivial detail of the names. Look at
>>> the
>>> semantics: They retreive a range associated with the aa, right? Right.
>>> Property. It's a plain old classic getter.
>>>
>>>
>>
>> That doesn't make the name any less bad. Naming is important IMHO. Hence
>> why I'm also complaining about .dup/.idup.
>>
>
> I think the compiler should just allow .dup()/.idup(). It would not break any existing code.

I think the compiler should not be in the business of generating methods or properties that could be trivially handled by the library.

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.

-Steve
January 18, 2012
On Tue, 17 Jan 2012 19:00:38 -0500, Kapps <Kapps@notvalidemail.com> wrote:

> Is there even a point to having byKey/byValue?
> Once UFCS comes in (and there's already a seemingly working pull request for it), having .keys return a range like byKey/byValue should will be a silent (though more efficient) change for most programs. And in the situations where it's not (namely when you want to store it as an array), just adding a .array at the end would work.

It changes semantics.  For example:

foreach(k; a.keys)
{
   if(shouldRemove(k)) a.remove(k); // this is currently valid
}

-Steve
January 18, 2012
On Tue, 17 Jan 2012 19:02:03 -0500, Nick Sabalausky <a@a.a> wrote:

> "Alvaro" <alvaroDotSegura@gmail.com> wrote in message

>>
>> Oops. Yes, thanks.
>>
>> So, not bad. In those [infrequent, I'd say] cases needing an array one
>> would do:
>>
>>  auto keys = array(aa.keys);
>>
>
> My thoughts exactly. The current .keys made sense back in the days before
> ranges, std.algorithm, etc, but not so much anymore. Vote++

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.

I don't see any way around this...

-Steve
January 18, 2012
On Tue, 17 Jan 2012 18:29:11 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 1/17/12 5:13 PM, Peter Alexander wrote:
>> On 17/01/12 10:11 PM, Jonathan M Davis wrote:
>>> You would need to come up with some really solid arguments why it
>>> should be
>>> thrown out (and what we should do instead) and get both Walter and
>>> Andrei (if
>>> not the community at large) to agree that they not only prefer your
>>> proposal
>>> but that it's worth the issues that the changes are going to cause at
>>> this
>>> stage.
>>
>> There's a few good reasons to throw it out:
>>
>> 1. Avoids pointless discussions like this one. These discussions add
>> nothing, it's just mindless bike shedding.
>
> Yes.

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".

The point of required property semantics is that the name of the function includes whether you need parentheses or not.  a.empty does not have the same tone as a.empty().  The former looks like a field, the latter looks like an action.  It's a subtle bikeshed issue, but so is naming functions anyways!  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.

And if I may add my opinion, byValue and byKey are properties.

>> 2. The -property flag *creates* a new kind of error, but doesn't
>> actually help find real problems with your code. Without properties,
>> member function access would always be a.b(), and this artificial error
>> could be avoided.
>
> Yes! I can't believe we have a check that has _zero_ contribution to improving code.

I think you misunderstand Peter, he is saying we should not have properties *at all* a-la Java.

>> Is it practical or realistic to throw it out at this stage? I don't
>> know. But there are reasons to.
>
> Me neither. If I had my way I'd carefully redo the feature to only require @property on rare cases that would otherwise be ambiguous, and make parens optional everywhere else.

Don't forget my suggestion that void-returning no-arg functions should be able to be called without parens.  There should be no ambiguity (since you can't use it as an accessor).

But I think enforced properties is the right path, which gives all the naming power to the code author, not the code user.

-Steve
January 18, 2012
On Wed, 18 Jan 2012 07:33:45 -0500, Jacob Carlborg <doob@me.com> wrote:

> On 2012-01-18 09:30, sclytrack wrote:
>>
>>>
>>> Is it practical or realistic to throw it out at this stage? I don't
>>> know. But there are reasons to.
>>
>>
>> I hope we are not dropping properties
>> regardless of the syntax of how to call them.
>>
>> Keep @property
>> Keep methods-as-properties
>>
>> ---------------------------------
>> (a) No ()
>>
>> obj.property = "test";
>> string str = obj.property;
>>
>> obj.method = "string";
>> obj.method("first");
>> string str = obj.method;
>> obj.method("first", "second");
>>
>> ---------------------------------
>> (b) Optional () for methods
>>
>> obj.property = "test";
>> string str = obj.property;
>>
>> obj.method = "string";
>> obj.method("first");
>> string str = obj.method;
>> string str = obj.method();
>> obj.method("first", "second");
>>
>> ---------------------------------
>> (c) Mandatory () for methods
>>
>> obj.property = "test";
>> string str = obj.property;
>>
>> obj.method = "string";
>> obj.method("first");
>> string str = obj.method();
>> obj.method("first", "second");
>>
>> ---------------------------------
>> (d) Property and Method separated. (Is this the goal for -property?)
>>
>> obj.property = "test";
>> string str = obj.property;
>>
>> string str = obj.method();
>> obj.method("first");
>> obj.method("first", "second");
>>
>> ---------------------------------
>>
>> Who likes (a) ?
>>
>> Also I think that the @property opDispatch() looks weird.
>
> I would like this:
>
> property:
> 	getter - parentheses are not allowed
> 	setter:
> 		* equal sign is required
> 		* parentheses are not allowed
>
> method:
> 	no parameters - parentheses are optional
> 	parameters:
> 		* parentheses are required
> 		* equal sign is not allowed
>
> Examples:
>
> obj.property; // legal
> obj.property = 1; // legal
> obj.property(); // error
> obj.property(1); // error
>
> obj.method; // legal
> obj.method(); // legal
> obj.method(1); // legal
> obj.method = 1; // error

what about:

int x = obj.method; // passes by your rules, but I think should be illegal

I think the parentheses should only be optional on void-returning methods.

Otherwise, I agree with your list.

-Steve
January 18, 2012
On 1/18/12 7:20 AM, Steven Schveighoffer wrote:
> I think the compiler should not be in the business of generating methods
> or properties that could be trivially handled by the library.

Yes. I'm fighting Walter tooth and nail over that, with pale success.

> 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).


Andrei

January 18, 2012
On 2012-01-18 14:47, Steven Schveighoffer wrote:
> On Wed, 18 Jan 2012 07:33:45 -0500, Jacob Carlborg <doob@me.com> wrote:
>
>> On 2012-01-18 09:30, sclytrack wrote:
>>>
>>>>
>>>> Is it practical or realistic to throw it out at this stage? I don't
>>>> know. But there are reasons to.
>>>
>>>
>>> I hope we are not dropping properties
>>> regardless of the syntax of how to call them.
>>>
>>> Keep @property
>>> Keep methods-as-properties
>>>
>>> ---------------------------------
>>> (a) No ()
>>>
>>> obj.property = "test";
>>> string str = obj.property;
>>>
>>> obj.method = "string";
>>> obj.method("first");
>>> string str = obj.method;
>>> obj.method("first", "second");
>>>
>>> ---------------------------------
>>> (b) Optional () for methods
>>>
>>> obj.property = "test";
>>> string str = obj.property;
>>>
>>> obj.method = "string";
>>> obj.method("first");
>>> string str = obj.method;
>>> string str = obj.method();
>>> obj.method("first", "second");
>>>
>>> ---------------------------------
>>> (c) Mandatory () for methods
>>>
>>> obj.property = "test";
>>> string str = obj.property;
>>>
>>> obj.method = "string";
>>> obj.method("first");
>>> string str = obj.method();
>>> obj.method("first", "second");
>>>
>>> ---------------------------------
>>> (d) Property and Method separated. (Is this the goal for -property?)
>>>
>>> obj.property = "test";
>>> string str = obj.property;
>>>
>>> string str = obj.method();
>>> obj.method("first");
>>> obj.method("first", "second");
>>>
>>> ---------------------------------
>>>
>>> Who likes (a) ?
>>>
>>> Also I think that the @property opDispatch() looks weird.
>>
>> I would like this:
>>
>> property:
>> getter - parentheses are not allowed
>> setter:
>> * equal sign is required
>> * parentheses are not allowed
>>
>> method:
>> no parameters - parentheses are optional
>> parameters:
>> * parentheses are required
>> * equal sign is not allowed
>>
>> Examples:
>>
>> obj.property; // legal
>> obj.property = 1; // legal
>> obj.property(); // error
>> obj.property(1); // error
>>
>> obj.method; // legal
>> obj.method(); // legal
>> obj.method(1); // legal
>> obj.method = 1; // error
>
> what about:
>
> int x = obj.method; // passes by your rules, but I think should be illegal

I could go either way with that one. But I think I prefer optional parentheses.

> I think the parentheses should only be optional on void-returning methods.
>
> Otherwise, I agree with your list.
>
> -Steve


-- 
/Jacob Carlborg
January 18, 2012
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.

> The point of required property semantics is that the name of the
> function includes whether you need parentheses or not. a.empty does not
> have the same tone as a.empty(). The former looks like a field, the
> latter looks like an action. It's a subtle bikeshed issue, but so is
> naming functions anyways!

Yes, but the problem is this adds additional bikeshedding for no benefit.

> 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.

> 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.


Andrei
January 18, 2012
On 2012-01-18 14:59, Andrei Alexandrescu wrote:
> On 1/18/12 7:20 AM, Steven Schveighoffer wrote:
>> I think the compiler should not be in the business of generating methods
>> or properties that could be trivially handled by the library.
>
> Yes. I'm fighting Walter tooth and nail over that, with pale success.
>
>> 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).
>
>
> Andrei
>

But a library can't handle common properties like "mangleof" and "stringof"?

-- 
/Jacob Carlborg
January 18, 2012
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 :)

>
>> The point of required property semantics is that the name of the
>> function includes whether you need parentheses or not. a.empty does not
>> have the same tone as a.empty(). The former looks like a field, the
>> latter looks like an action. It's a subtle bikeshed issue, but so is
>> naming functions anyways!
>
> Yes, but the problem is this adds additional bikeshedding for no benefit.
>
>> 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.

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.

>> 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.

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.

-Steve