Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Piotr Szturmaj | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Piotr Szturmaj | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Piotr Szturmaj | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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!
|
Copyright © 1999-2021 by the D Language Foundation