View mode: basic / threaded / horizontal-split · Log in · Help
April 14, 2012
Calling delegate properties without parens
I have following code:

import std.array, std.range, std.stdio;

struct CommonInputRange(E)
{
    @property bool delegate() empty;
    @property E delegate() front;
    void delegate() popFront;
}

void main(string[] args)
{
    alias CommonInputRange!dchar DCRange;
    static assert(isInputRange!DCRange);
    DCRange dc;
    auto dcr = "abcdefg";
    auto t = dcr.takeExactly(3);
    dc.empty = &t.empty;
    dc.front = &t.front;
    dc.popFront = &t.popFront;

    for ( ; !dc.empty(); dc.popFront())
        writeln(dc.front());
}

As you can see in the for loop, range primitives must be called using 
parens (), otherwise they don't work.

Do you know if there are plans to implement @property for delegates and 
function pointers?
April 14, 2012
Re: Calling delegate properties without parens
On 04/14/12 20:47, Piotr Szturmaj wrote:
> I have following code:
> 
> import std.array, std.range, std.stdio;
> 
> struct CommonInputRange(E)
> {
>     @property bool delegate() empty;
>     @property E delegate() front;
>     void delegate() popFront;
> }
> 
> void main(string[] args)
> {
>     alias CommonInputRange!dchar DCRange;
>     static assert(isInputRange!DCRange);
>     DCRange dc;
>     auto dcr = "abcdefg";
>     auto t = dcr.takeExactly(3);
>     dc.empty = &t.empty;
>     dc.front = &t.front;
>     dc.popFront = &t.popFront;
> 
>     for ( ; !dc.empty(); dc.popFront())
>         writeln(dc.front());
> }
> 
> As you can see in the for loop, range primitives must be called using parens (), otherwise they don't work.
> 
> Do you know if there are plans to implement @property for delegates and function pointers?

@property is for functions masquerading as data, i'm not sure extending it
to pointers and delegates would be a good idea. What you are asking for is
basically syntax sugar for:

  struct CommonInputRange(E)
  {
      bool delegate() _empty;
      @property auto empty() { return _empty(); };
      @property auto empty(typeof(_empty) dg) { _empty = dg; };
      E delegate() _front;
      @property auto front() { return _front(); };
      @property auto front(typeof(_front) dg) { _front = dg; };
      void delegate() popFront;
  }

// [1]

artur

[1] which could also /almost/ be expressed as:

  struct PropDeleg(T) {
     T dg;
     @property auto get() { return dg(); };
     alias get this;
     void opAssign(T d) { dg = d; };
  }

  struct CommonInputRange(E)
  {
     PropDeleg!(bool delegate()) empty;
     PropDeleg!(E delegate()) front;
     void delegate() popFront;
  }

except this one would need an (implicit) conversion to get the same
behavior. IOW it should work everywhere, as long as the result is
assigned to a different type; ie you'd need 
"{ dchar c = dc.front; writeln(c); }" in the above example, because
otherwise the writeln template will accept the struct, but never
really use it, so the dchar conversion does not happen.
April 15, 2012
Re: Calling delegate properties without parens
Artur Skawina wrote:
> @property is for functions masquerading as data, i'm not sure extending it
> to pointers and delegates would be a good idea. What you are asking for is
> basically syntax sugar for:
>
>     struct CommonInputRange(E)
>     {
>         bool delegate() _empty;
>         @property auto empty() { return _empty(); };
>         @property auto empty(typeof(_empty) dg) { _empty = dg; };
>         E delegate() _front;
>         @property auto front() { return _front(); };
>         @property auto front(typeof(_front) dg) { _front = dg; };
>         void delegate() popFront;
>     }
>

Yes, I was thinking about this, but it adds unnecessary overhead. I want 
to call delegates directly.

I think the whole idea is harmless because semantically, from the user 
perspective, delegates and function pointers works just like normal 
functions. So, why not?
April 15, 2012
Re: Calling delegate properties without parens
On Saturday, April 14, 2012 20:47:20 Piotr Szturmaj wrote:
> I have following code:
> 
> import std.array, std.range, std.stdio;
> 
> struct CommonInputRange(E)
> {
>      @property bool delegate() empty;
>      @property E delegate() front;
>      void delegate() popFront;
> }
> 
> void main(string[] args)
> {
>      alias CommonInputRange!dchar DCRange;
>      static assert(isInputRange!DCRange);
>      DCRange dc;
>      auto dcr = "abcdefg";
>      auto t = dcr.takeExactly(3);
>      dc.empty = &t.empty;
>      dc.front = &t.front;
>      dc.popFront = &t.popFront;
> 
>      for ( ; !dc.empty(); dc.popFront())
>          writeln(dc.front());
> }
> 
> As you can see in the for loop, range primitives must be called using
> parens (), otherwise they don't work.
> 
> Do you know if there are plans to implement @property for delegates and
> function pointers?

front returns an element in the range. In your case, it's returning a 
delegate, because you have a range of delegates. If front returned a class or 
struct with a member function called foo, which you wanted to call, then you'd 
be doing something like

for(; !dc.empty; dc.popFront())
   writeln(dc.front.foo());

But in your case, it's a delegate, so operating on that delegate means calling 
it, which means using the parens. dc.front just gives you the delegate, and it 
would be horrible if it did anything else. If front also called the delegate, 
the doing something like

auto arr = arr(dc);

would call each and every one of the delegates in the range, because it uses 
front to access the element _without calling it_. If there were some way to 
indicate that a delegate was called with property syntax, then you could no 
longer distinguish between simply returning the delegate and returning and 
call it.

Not to mention, properties are supposed to be an abstraction that mimicks 
member variables. That makes no sense whatsoever with a delegate. And in this 
case, the member variable which _is_ being mimicked (front) happens to be a 
delegate. So, it makes perfect sense that you'd have to use parens on it to 
actually call it.

- Jonathan M Davis
April 15, 2012
Re: Calling delegate properties without parens
On 04/15/12 03:01, Piotr Szturmaj wrote:
> Artur Skawina wrote:
>> @property is for functions masquerading as data, i'm not sure extending it
>> to pointers and delegates would be a good idea. What you are asking for is
>> basically syntax sugar for:
>>
>>     struct CommonInputRange(E)
>>     {
>>         bool delegate() _empty;
>>         @property auto empty() { return _empty(); };
>>         @property auto empty(typeof(_empty) dg) { _empty = dg; };
>>         E delegate() _front;
>>         @property auto front() { return _front(); };
>>         @property auto front(typeof(_front) dg) { _front = dg; };
>>         void delegate() popFront;
>>     }
>>
> 
> Yes, I was thinking about this, but it adds unnecessary overhead. I want to call delegates directly.

The compiler has to implement it internally exactly like that anyway. D's design
relies on such code being efficient - there is no preprocessor, no inline 
attribute and no macros. The trivial functions have to be inlined, if that
doesn't happen it's a compiler bug. Once inlined, there's no overhead.

> I think the whole idea is harmless because semantically, from the user perspective, delegates and function pointers works just like normal functions. So, why not?

I can see it being confusing and don't see much benefit - that's all. The current
syntax is just a little more verbose, and mixins could be used if this scheme had
to be used on a larger scale.

artur
April 15, 2012
Re: Calling delegate properties without parens
Artur Skawina wrote:
> On 04/15/12 03:01, Piotr Szturmaj wrote:
>> Artur Skawina wrote:
>>> @property is for functions masquerading as data, i'm not sure extending it
>>> to pointers and delegates would be a good idea. What you are asking for is
>>> basically syntax sugar for:
>>>
>>>      struct CommonInputRange(E)
>>>      {
>>>          bool delegate() _empty;
>>>          @property auto empty() { return _empty(); };
>>>          @property auto empty(typeof(_empty) dg) { _empty = dg; };
>>>          E delegate() _front;
>>>          @property auto front() { return _front(); };
>>>          @property auto front(typeof(_front) dg) { _front = dg; };
>>>          void delegate() popFront;
>>>      }
>>>
>>
>> Yes, I was thinking about this, but it adds unnecessary overhead. I want to call delegates directly.
>
> The compiler has to implement it internally exactly like that anyway. D's design
> relies on such code being efficient - there is no preprocessor, no inline
> attribute and no macros. The trivial functions have to be inlined, if that
> doesn't happen it's a compiler bug. Once inlined, there's no overhead.

I wondered if properties can be inlined that way. But you have conviced 
me that indeed, inlining should help here. So, I'll use proxy 
properties. Thanks for your advice.
April 15, 2012
Re: Calling delegate properties without parens
Jonathan M Davis wrote:
> On Saturday, April 14, 2012 20:47:20 Piotr Szturmaj wrote:
>>
>> struct CommonInputRange(E)
>> {
>>       @property bool delegate() empty;
>>       @property E delegate() front;
>>       void delegate() popFront;
>> }
>
> front returns an element in the range. In your case, it's returning a
> delegate, because you have a range of delegates.

Gah. That explains everything... Thanks!
Top | Discussion index | About this forum | D home