Thread overview
Recursive aliases?
Apr 21, 2012
Mehrdad
Apr 21, 2012
Tobias Pankrath
Apr 28, 2012
Stewart Gordon
Apr 23, 2012
Timon Gehr
Apr 27, 2012
bcs
April 21, 2012
alias int delegate(out ItemGetter next) ItemGetter;

We currently can't do the above^ in D, but what do people think about allowing it?
i.e. More specifically, I think an alias expression should be able to refer to the identifier (unless it doesn't make sense, like including a struct inside itself).
(It would require a look-ahead.) 

April 21, 2012
On Saturday, 21 April 2012 at 19:46:29 UTC, Mehrdad wrote:
> alias int delegate(out ItemGetter next) ItemGetter;
>
> We currently can't do the above^ in D, but what do people think about allowing it?
> i.e. More specifically, I think an alias expression should be able to refer to the identifier (unless it doesn't make sense, like including a struct inside itself).
> (It would require a look-ahead.)

I've needed exactly this thing once.Or should I say: I needed
this exactly once*?



* Though I don't code very much in D.
April 23, 2012
On Sat, 21 Apr 2012 15:46:29 -0400, Mehrdad <wfunction@hotmail.com> wrote:

> alias int delegate(out ItemGetter next) ItemGetter;
>
> We currently can't do the above^ in D, but what do people think about allowing it?
> i.e. More specifically, I think an alias expression should be able to refer to the identifier (unless it doesn't make sense, like including a struct inside itself).
> (It would require a look-ahead.)

It doesn't work.

If I do this:

alias int delegate() dtype;

alias int delegate(dtype d) ddtype;

pragma(msg, ddtype.stringof);

I get:

int delegate(int delegate() d)

Note how it's not:

int delegate(dtype d)

Why?  Because alias does not create a new type.  It's a new symbol that *links* to the defined type.

How shall the compiler expand your example so it can know the type?  It works for classes because classes are a new type which do not need to have another type backing it.

The solution?  Well, there are two possible ones.  One is you create a ficticious type (or use void *) and cast when inside the delegate.  The other is to not use delegates, but use types instead.  Either a struct or a class/interface will do, something for the compiler to anchor on.

-Steve
April 23, 2012
On 04/23/2012 01:44 PM, Steven Schveighoffer wrote:
> On Sat, 21 Apr 2012 15:46:29 -0400, Mehrdad <wfunction@hotmail.com> wrote:
>
>> alias int delegate(out ItemGetter next) ItemGetter;
>>
>> We currently can't do the above^ in D, but what do people think about
>> allowing it?
>> i.e. More specifically, I think an alias expression should be able to
>> refer to the identifier (unless it doesn't make sense, like including
>> a struct inside itself).
>> (It would require a look-ahead.)
>
> It doesn't work.
>
> If I do this:
>
> alias int delegate() dtype;
>
> alias int delegate(dtype d) ddtype;
>
> pragma(msg, ddtype.stringof);
>
> I get:
>
> int delegate(int delegate() d)
>
> Note how it's not:
>
> int delegate(dtype d)
>
> Why? Because alias does not create a new type. It's a new symbol that
> *links* to the defined type.
>
> How shall the compiler expand your example so it can know the type?

Basically the same way it detects recursive aliases. It is not really an implementation problem, but it would add a special case (don't expand recursive aliases). In general, it would get a little bit challenging to resolve recursive types in a reliable way:

typeof(dg) delegate(typeof(dg(dg)(dg)), typeof(dg(dg)) = typeof(dg(dg(dg))).init) dg; // type safe!

Implementing those infinite types would be a fun exercise though :o)

> It works for classes because classes are a new type which do not need to
> have another type backing it.
>
> The solution? Well, there are two possible ones. One is you create a
> ficticious type (or use void *) and cast when inside the delegate. The
> other is to not use delegates, but use types instead. Either a struct or
> a class/interface will do, something for the compiler to anchor on.
>
> -Steve

Sure, but it shouldn't be necessary. There is no reason why it could not work except for the added complexity.

April 27, 2012
On 04/23/2012 04:44 AM, Steven Schveighoffer wrote:
> On Sat, 21 Apr 2012 15:46:29 -0400, Mehrdad <wfunction@hotmail.com> wrote:
>
>> alias int delegate(out ItemGetter next) ItemGetter;
>>
>> We currently can't do the above^ in D, but what do people think about
>> allowing it?
>> i.e. More specifically, I think an alias expression should be able to
>> refer to the identifier (unless it doesn't make sense, like including
>> a struct inside itself).
>> (It would require a look-ahead.)
>
> It doesn't work.
>
> If I do this:
>
> alias int delegate() dtype;
>
> alias int delegate(dtype d) ddtype;
>
> pragma(msg, ddtype.stringof);
>
> I get:
>
> int delegate(int delegate() d)
>
> Note how it's not:
>
> int delegate(dtype d)
>
> Why? Because alias does not create a new type. It's a new symbol that
> *links* to the defined type.
>

The only problem is that the text representation of the type contains it's self as a proper sub-string. As far as the compiler is concerned, this should be no harder to handle than a linked list node or the curiously recurring template pattern.

Another use for it would be one of the cleaner state machine implementations I've ever seen:


alias foo delegate() foo;

foo = start();
while ((foo = foo())) {}


April 28, 2012
On 21/04/2012 21:11, Tobias Pankrath wrote:
<snip>
> I've needed exactly this thing once.Or should I say: I needed
> this exactly once*?
<snip>

I don't know.  Which do you mean?

"I've needed exactly this thing once" - "exactly" is modifying "this thing" - means you needed this feature as opposed to some other possibly similar feature.

"I needed this exactly once" - "exactly" is modifying "once" - means you needed it once upon a time and then never again.

Stewart.