byKey and byValue: properties or methods?

Timon Gehr timon.gehr at gmx.ch
Thu Jan 19 09:33:15 PST 2012


On 01/19/2012 03:47 PM, Peter Alexander wrote:
> On 19/01/12 12:51 AM, Timon Gehr wrote:
>> On 01/19/2012 01:41 AM, Peter Alexander wrote:
>>> On 18/01/12 12:52 AM, Timon Gehr wrote:
>>>> On 01/18/2012 01:40 AM, Jonathan M Davis wrote:
>>>>> On Tuesday, January 17, 2012 19:31:25 bearophile wrote:
>>>>>> Nick Sabalausky:
>>>>>>> Without properties, member function access *ANY* many value
>>>>>>> accesses are "a.b()". Is this member value a plain-old-var or a
>>>>>>> function?
>>>>>>> Who knows! It's a leeked out implementation detail, hooray!
>>>>>>
>>>>>> I have a partially related question.
>>>>>>
>>>>>> Currently this code compiles even with -property:
>>>>>>
>>>>>> void main() {
>>>>>> int[int] aa = [1:2];
>>>>>> auto byval = aa.byValue();
>>>>>> }
>>>>>>
>>>>>> But I think byValue is a property, so isn't it right to give a
>>>>>> compilation
>>>>>> error if you add () after the name of a property?
>>>>>
>>>>> Definitely a bug. Strict enforcement requires that parens be used on
>>>>> all
>>>>> function calls and that no properties use parens. If you use parens on
>>>>> them,
>>>>> that would mean that you're using them on the return value of the
>>>>> property
>>>>> (e.g. opCall) - and in fact, that's one of the main reasons that
>>>>> @property was
>>>>> added in the first place, since without enforcement, property
>>>>> functions which
>>>>> return a delegate result in an ambiguity.
>>>>>
>>>>> - Jonathan M Davis
>>>>
>>>> A related and way more embarrassing problem is that lazy function
>>>> parameters have the same issue.
>>>>
>>>> This program prints nothing:
>>>> import std.stdio;
>>>> void foo(lazy void delegate() dg){
>>>> dg();
>>>> }
>>>> void main(){
>>>> foo({writeln("hello");});
>>>> }
>>>
>>> Perhaps I'm wrong, but this issue is different.
>>>
>>> The code you have written is something that would be written by someone
>>> that doesn't understand how lazy works.
>>
>> It is written by someone who understands how it should work.
>>
>>> You have to use () to un-lazy
>>
>> What would 'un-lazying' be and what is supposed to be its effect?
>
> Under the hood, lazy is just a delegate with different syntax.
>

It is more than that, type checking works differently for lazy values 
compared to scoped delegates.

> void foo(lazy int x) {}
> int a;
> foo(a++);
>
> Essentially translates to:
>
> void foo(int delegate() x) {}
> int a;
> foo( { return a++; } );
>
> Inside foo, you have to do x() to evaluate the delegate, just like
> normals delegates. x on its own without parens would just be the
> delegate variable. If you had a lazy delegate parameter then that is
> like a delegate that returns a delegate, so you have to do x()() to
> evaluate the returned delegate.

I know what is under the hood, but I don't really care. Lazy is just 
another storage class, and as such it has no business changing the 
syntax using which the value is accessed.

>
>>> it, and then () again to invoke the delegate. There is no ambiguity like
>>> there is with property delegates.
>>
>> The code has exactly the same semantics whether or not you write the
>> parens after a lazy variable except for the case when it is a delegate
>> or function pointer.
>
> I was not aware of this. I believe this is a bug (or at least a design
> flaw).

Parens should be removed completely from lazy values. They don't add a 
lot while being inconsistent with how other STCs work.


More information about the Digitalmars-d mailing list