October 03, 2008
Bill Baxter wrote:
> On Fri, Oct 3, 2008 at 9:37 AM, Bill Baxter <wbaxter@gmail.com> wrote:
>> ... except these extras do have the same issue that plain property
>> assignment does.  They would open up a new class of things that are
>> valid code but don't behave as expected.  writefln += 5.
>>
> 
> Doh, obviously writefln is a bad example there.  Imagine a function
> that takes an int, tries to do something that many times, then returns
> an int indicating how many times it actually managed to do it.
> 
> --bb

How about this? Start trusting programmers not to do nonsensical things. With the possible exception of downs, whose code is delightfully opaque while being wonderfully readable.
October 03, 2008
Andrei Alexandrescu wrote:
> Bruno Medeiros wrote:
>> Andrei Alexandrescu wrote:
>>> Bruno Medeiros wrote:
>>>> Andrei Alexandrescu wrote:
>>>>> Bill Baxter wrote:
>>>>>> On Tue, Sep 30, 2008 at 4:08 AM, KennyTM~ <kennytm@gmail.com>
>>>>>> wrote:
>>>>>>> I think the distinction of with and without () is pretty stylistic, because the same argument can even be applied to
>>>>>>> operator overloading (does a=b means pointing the variable
>>>>>>> a to b, or calling a.opAssign(b)?)
>>>>>>>
>>>>>>> For me, I would use () if the function do modify the object
>>>>>>> itself.
>>>>>>
>>>>>> I think the counter-argument to what I just said is that if
>>>>>> properties had to be declared explicitly then at least we
>>>>>> would know that .y is either a field or else something the
>>>>>> designer *intended* to behave like a property.  Which does
>>>>>> tell us something.  It most likely means that it's not an
>>>>>> extremely heavy-weight operation, just a lightweight accessor
>>>>>> with maybe a little logic on top.  That could be wrong, but in that case it's the class designer's fault for misleading
>>>>>> us.
>>>>>
>>>>> So the logic is:
>>>>>
>>>>> "A field can be accessed with a.b, but not with a.b().
>>>>> Therefore if someone writes a.b, it may be a field or code, but
>>>>> it someone writes a.b() it will always be code. Given that a
>>>>> field is cheap and code ranges from cheap to expensive, good
>>>>> style is to have a.b always refer to cheap stuff, and a.b()
>>>>> always refer to not-expected-to-be-cheap stuff."
>>>>>
>>>>> I agree with that logic. It makes for a nice convention. (That
>>>>>  convention is already broken by the built-in dup and sort, but
>>>>> let past mistakes be past mistakes.) My response to that is
>>>>> that concerns of keeping the language simple and of
>>>>> facilitating generic code are counterarguments that should be
>>>>> weighed in as well.
>>>>>
>>>>
>>>> In what way does that convention/style go against facilitating generic code?
>>>
>>> A generic function writing obj.symbol cannot work across objects
>>> that implement symbol as a computed property vs. a field.
>>>
>>>
>>> Andrei
>>
>> I'm not following. If 'obj.symbol' is syntactically available and is
>>  valid code, shouldn't the generic function work ok regardless of
>> whether 'symbol' is a computed property or a field?
> 
> What I meant is very simple. Generic code benefits from unified syntax.
> Going with one convention across the board would make generic code
> simpler. Going with the convention that expensive stuff is with "()" and cheap stuff is without "()" differentiates usage.
> 

Ah, got it now. I misunderstood the original "So the logic is:" post.
But I don't think the idea (from Bill and others) was to omit "()" for all cheap stuff functions, but only for those explicitly made to behave as properties/fields. That way would not hurt generic code, it would be the same as the status quo in that regard.


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
Andrei Alexandrescu wrote:
> Bill Baxter wrote:
>> On Fri, Oct 3, 2008 at 3:16 AM, Fawzi Mohamed <fmohamed@mac.com> wrote:
>>
>>> This is a very nice feature to have.
>>> D reaches this with a minimal change to the language:
>>> optional parenthesis, and setter functions.
>>>
>>> ...
>>> It does have some limitation (no +=,-=,...) but is very compact, and simple
>>> to explain.
>>
>> Fortunately this is an orthogonal issue.  This could (and should IMO)
>> be fixed independent of the current discussion.
> 
> Yah, overloaded ops are due for an overhaul. I'm almost afraid to ask... any ideas? :o)
> 
> One goal is to fix opIndexAssign and make it work similar to the way it works in arrays, e.g. a[b] += c. Indexing into hash tables is a good test bed.
> 
> 
> Andrei

Agh, this was a clear and good opportunity to fork a new thread.

-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
Andrei Alexandrescu wrote:
> Sean Kelly wrote:
>> == Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)'s article
>>> Bruno Medeiros wrote:
>>>> I don't understand that. You stated "It violates economy of syntax.", so
>>>>  it violates your Principle 1 of language design. So how can you be
>>>> happy with that (apart from the assignment issue)? Does fixing this
>>>> problem violate some other principle or concern of yours?
>>> I think keeping the language simple is also a good goal.
>>
>> I apologize if this has been brought up before, but I'm not sure that simplicity
>> is a good thing if it can result in unpredictable behavior.  For example:
>>
>>     import std.stdio;
>>
>>     class C
>>     {
>>         this( bool delegate() p )
>>         {
>>             version( a )
>>                 cond = p;
>>             version( b )
>>                 ptr = p;
>>         }
>>         version( a )
>>         {
>>             bool delegate() cond;
>>         }
>>         version( b )
>>         {
>>             bool delegate() ptr;
>>             bool delegate() cond() { return ptr; }
>>         }
>>     }
>>
>>     void main()
>>     {
>>         bool test() { writefln( "hi" ); return false; }
>>         auto c = new C( &test );
>>         if( c.cond() )
>>             writefln( "true" );
>>     }
>>
>> Running version=a prints "hi" while version=b prints "true."  If there were
>> some way in the language to say "cond() is a property" then this issue would
>> not be silently introduced when changing cond from a variable to a method.
> 
> Oh how I am with you on this. I've always thought mentioning a delegate name should NOT EVER evaluate the delegate. Walter definitely took the wrong turn down that alley there. And guess what. He got ambushed by the "lazy" keyword right there. I told Walter to not do that "lazy" keyword, he disregarded, but the time will come when that stone will be turned.
> 
> 
> Andrei

Hold it right there! Are you saying that the existence of 'lazy' somehow required, or helped justify the existence of the omittable parenthesis functionality? How is that?
I think you are accusing innocents ('lazy') or wrongdoing. 'lazy' has nothing to do with the omittable parenthesis functionality, I think they are completely orthogonal. Prove me wrong otherwise.

-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
On 2008-10-02 21:13:16 +0200, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

> Sean Kelly wrote:
>> == Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)'s article
>>> Bruno Medeiros wrote:
>>>> I don't understand that. You stated "It violates economy of syntax.", so
>>>>  it violates your Principle 1 of language design. So how can you be
>>>> happy with that (apart from the assignment issue)? Does fixing this
>>>> problem violate some other principle or concern of yours?
>>> I think keeping the language simple is also a good goal.
>> 
>> I apologize if this has been brought up before, but I'm not sure that simplicity
>> is a good thing if it can result in unpredictable behavior.  For example:
>> 
>>     import std.stdio;
>> 
>>     class C
>>     {
>>         this( bool delegate() p )
>>         {
>>             version( a )
>>                 cond = p;
>>             version( b )
>>                 ptr = p;
>>         }
>>         version( a )
>>         {
>>             bool delegate() cond;
>>         }
>>         version( b )
>>         {
>>             bool delegate() ptr;
>>             bool delegate() cond() { return ptr; }
>>         }
>>     }
>> 
>>     void main()
>>     {
>>         bool test() { writefln( "hi" ); return false; }
>>         auto c = new C( &test );
>>         if( c.cond() )
>>             writefln( "true" );
>>     }
>> 
>> Running version=a prints "hi" while version=b prints "true."  If there were
>> some way in the language to say "cond() is a property" then this issue would
>> not be silently introduced when changing cond from a variable to a method.
> 
> Oh how I am with you on this. I've always thought mentioning a delegate name should NOT EVER evaluate the delegate.

I think here the problem is different
c.cond() in version a evaluates the delegate
in version b
c.cond() is interpreted as the the omittable parenthesis of the accessor method, and returns the delegate.
As (as you want, and I think is reasonable) the delegate is not evaluated. In if it is then interpreted as a logical and gives true (as it is a valid delegate, not null).
c.cond()() would give false.
So actually automatically evaluating the delegate would actually fix this particular problem (but would indeed introduce many other problems, like how to then get the delegate).

> Walter definitely took the wrong turn down that alley there. And guess what. He got ambushed by the "lazy" keyword right there. I told Walter to not do that "lazy" keyword, he disregarded, but the time will come when that stone will be turned.
> 
> 
> Andrei


October 03, 2008
Andrei Alexandrescu wrote:
> Bruno Medeiros wrote:
>> Andrei Alexandrescu wrote:
>>> Bruno Medeiros wrote:
>>>> Sergey's argument (which is much more objective than subjective) is not strictly against omitting parenthesis, but rather against ambiguity (the dual possible ways to call zero-args functions), which as has been shown, creates various possibilities for bugs when you mix functions that return delegates. This ambiguity problem would also be resolved if omitting parenthesis would be *the only way* of calling functions with zero-args.
>>>
>>> Yah, he made great points. There are ambiguities. The counter-argument is that that would make the syntax of calling functions with no arguments inconsistent with the syntax of calling function with arguments. The "()" is a degenerate case of "(a, b, c)". So it's hard to keep everybody happy.
>>>
>>
>> Yes, if we solved the ambiguity problem that way, we would make a lot of people unhappy (myself included). But if we solved the problem the *other way* (forbidding omittable parenthesis for normal zero-args function), it would make, that I know of, only one person unhappy (you).
> 
> So there is a cabal. I knew it! :o)
> 

If there is a cabal, it's a pretty lame one... Walter's Inner Circle are the ones with all the power! :o)

> I'm not that sure about "lot" and "one", and numbers-based arguments aren't that strong to begin with. Language design is complex and full of tradeoffs. In each decision there are consequences. If we require "()" then we must come with a separate thing for properties - an addition to the language. Then many people (maybe even including some the "lot" of people you mentioned) will cry foul: "where's my simple language?" etc. Maybe some people will say, hey, you were already there with the omittable "()" and the "=" thing, why didn't you just make the latter less trigger happy and we'd be home free?
> 

Yes, we would need an alternate mechanism for properties - an addition to the language. And it's quite true that it's likely there would be disagreement in the "lot of people" about that. But there is only one way to be sure, so we could at least try! Would you and Walter at least consider this, and see if we could find an alternative that satisfies a fair number of people? Try without compromise.

In fact, I'm also not a fan of those complex property mechanisms, à lá C#. I think a fair candidate would be Bill Baxter's proposal, the 'property' keyword:

  property int foo() { return _foo; };
  property void foo(int foo) { _foo = foo; };

The property keyword would make a function callable *only* as a property syntax (either as reading, 'bar = foo;', or as writing, 'foo = 42;'). A function signature which was not adequate for property access would be compile-time error.
This proposal fixes the ambiguities issues, and require *minimal changes* to the language, both in terms of syntax and semantics!


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
On 2008-10-03 12:05:17 +0200, Bruno Medeiros <brunodomedeiros+spam@com.gmail> said:

> Andrei Alexandrescu wrote:
>> Sean Kelly wrote:
>>> == Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)'s article
>>>> Bruno Medeiros wrote:
>>>>> I don't understand that. You stated "It violates economy of syntax.", so
>>>>>  it violates your Principle 1 of language design. So how can you be
>>>>> happy with that (apart from the assignment issue)? Does fixing this
>>>>> problem violate some other principle or concern of yours?
>>>> I think keeping the language simple is also a good goal.
>>> 
>>> I apologize if this has been brought up before, but I'm not sure that simplicity
>>> is a good thing if it can result in unpredictable behavior.  For example:
>>> 
>>>     import std.stdio;
>>> 
>>>     class C
>>>     {
>>>         this( bool delegate() p )
>>>         {
>>>             version( a )
>>>                 cond = p;
>>>             version( b )
>>>                 ptr = p;
>>>         }
>>>         version( a )
>>>         {
>>>             bool delegate() cond;
>>>         }
>>>         version( b )
>>>         {
>>>             bool delegate() ptr;
>>>             bool delegate() cond() { return ptr; }
>>>         }
>>>     }
>>> 
>>>     void main()
>>>     {
>>>         bool test() { writefln( "hi" ); return false; }
>>>         auto c = new C( &test );
>>>         if( c.cond() )
>>>             writefln( "true" );
>>>     }
>>> 
>>> Running version=a prints "hi" while version=b prints "true."  If there were
>>> some way in the language to say "cond() is a property" then this issue would
>>> not be silently introduced when changing cond from a variable to a method.
>> 
>> Oh how I am with you on this. I've always thought mentioning a delegate name should NOT EVER evaluate the delegate. Walter definitely took the wrong turn down that alley there. And guess what. He got ambushed by the "lazy" keyword right there. I told Walter to not do that "lazy" keyword, he disregarded, but the time will come when that stone will be turned.
>> 
>> 
>> Andrei
> 
> Hold it right there! Are you saying that the existence of 'lazy' somehow required, or helped justify the existence of the omittable parenthesis functionality? How is that?
> I think you are accusing innocents ('lazy') or wrongdoing. 'lazy' has nothing to do with the omittable parenthesis functionality, I think they are completely orthogonal. Prove me wrong otherwise.

I think that he meant that lazy automatically evaluates a delegate, and that he thinks it is wrong.
He said it because he thought that the problem shown by Sean was connected with automatically evaluating a delegate, which it is not, but let's not start another sub-thread...

Fawzi

October 03, 2008
Fawzi Mohamed wrote:
> Here comes another person that would be unhappy without omittable parenthesis.
> 
> Having properties is a very useful thing, one should be able to make a public field of a structure private and controlling access via methods with minimal or no changes to the external code.
> 

Like I said before to Andrei, the idea wasn't simply to drop the omittable parenthesis call, but also to find an alternate property mechanism.


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
Steven Schveighoffer wrote:
> "Bruno Medeiros" wrote
>> Andrei Alexandrescu wrote:
>>> Eiffel also has properties
>>> that are obtained via syntactic conventions (getX and setX implement
>>> property x)
>> Hum, interesting, I just replied in another part of the thread with a suggestion that is just like that (and didn't know about it).
> 
> In fact, C++.net did something similar in that if you defined a property x in C#, it really defined two hidden functions, get_x() and set_x() that could be called from C++.
> 
> But the new C++.net is much better, you can actually use and define real properties.
> 
> I consider this type of thing a hack, that probably shouldn't be used since we are talking about a developing language and not something that has decades of real-world use.  I personally think it was one of those Microsoft marketing things where they made C++.net so it could interact with other languages, but made it so ugly that you perceived C# as being soo much better ;)  But that's just the cynic in me.
> 
> All that is needed is a keyword to signify that a function is really a property, kind of like 'pure', and enforce the rules that have been discussed.  Since D2 is already getting new keywords and is almost backwards-incompatible with existing D1 code, I don't see this as a huge issue.
> 

Just for the record, I didn't present that suggestion because it didn't require a new keyword. I think that's a very weak concern, and as I've said before, I find Walter's current obsession with keyword economy outdated and silly (example: "enum", among others).

-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
October 03, 2008
Andrei Alexandrescu wrote:
> 
> If you want to discuss language design mistakes, why don't you discuss a real mistake - the infamous "lazy"? Having a storage class change the way a type is used - now that's the perfect example of the tail wagging the dog. Ambiguity, confusion, non-scalability, and sheer nonsense - you can have it all with lazy. Lazy should be either fixed or honorably discharged pronto.
> 
> 
> Andrei
> 

What's the problem with lazy? I mean, concretely?
Are you trying to see lazy as a type modifier, and thus see it as broken type modifier? Perhaps that's the issue, don't see it as a type modifier! I see lazy as a construct in the same category as '...': a syntax that changes the way a function call processes its arguments. Just because 'lazy' is a word and not a series of symbols doesn't mean it should be interpreted as a type constructor.


-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D