October 23, 2006

Bill Baxter wrote:
> rm wrote:
>> Reiner Pope wrote:
>>
>>> What's the purpose of the restriction of alias in the specs -- 'Aliases
>>> cannot be used for expressions'; it prevents some useful things like this:
>>>
>>>  int[2] nodes;
>>>  alias nodes[0] left;
>>>  alias nodes[1] right;
>>>
>>> which currently has to be written in a much more hackish way:
>>>
>>>  union {
>>>    int[2] nodes;
>>>    struct {
>>>       int left;
>>>       int right;
>>>    }
>>>  }
>>>
>>> This is less reliable because if you decide to change the datatype of
>>> nodes, you could easily stuff up:
>>
>>
>> you could do this:
>>
>>   template KT(T)
>>   {
>>     union KT
>>     {
>>       T[2] nodes;
>>       struct
>>       {
>>         T left;
>>         T right;
>>       }
>>     }
>>   }
>>
>>   alias KT!(int) K;
>>
>> roel
> 
> Or in this case he's not even after a template, so just
>   union {
>     alias int NodeID;
>     NoteID[2] nodes;
>     struct {
>        NodeID left;
>        NodeID right;
>     }
>   }
> 
> But, I see your point, Reiner.  'alias foo[1] bar' expresses the intent of the programmer more clearly here than union, and doesn't have the typesafety issues.
> 
> --bb

I think this is a typesafe solution:
typeof(node[1]) left;
typeof(node[2]) right;
October 23, 2006
Bill Baxter wrote:
> Walter Bright wrote:
>> RE: errors
>>
>> I wrote those on the assumption they'd be inside a function. As globals, they won't work, but in general things line int[2] shouldn't be globals.
> 
> Those were in a class.

Glad you told me that, because I couldn't duplicate the errors.

The first one works as:

> class Foo
> {
>     int[2] nodes;
>     int left() { return nodes[0]; }
>     int right() { return nodes[1]; }
> }

And the other:

> class Foo
>   {
>     void DoSomething() { }
>   }
> 
>   class FooHandle
>   {
>     Foo myFoo;
>     void DoSomething() { myFoo.DoSomething(); }
>   }

October 23, 2006
All of the below add members or variables to whatever they are in. The alias solution is 100% compile time, and has no effect on the structure layout.

Walter Bright wrote:
> Reiner Pope wrote:
> 
>>   int[2] nodes;
>>   alias nodes[0] left;
>>   alias nodes[1] right;
> 
> 
> How about:
> 
>     auto left = &nodes[0];
>     auto right = &nodes[1];
> 
> Or:
> 
>     auto left = (){ return nodes[0]; }
>     auto right = (){ return nodes[1]; }
> 
>>   class Foo
>>   {
>>     void DoSomething() {...}
>>   }
>>
>>   class FooHandle
>>   {
>>     Foo myFoo;
>>     alias myFoo.DoSomething DoSomething;
>>   }
> 
> 
> Or:
>     auto DoSomething = &myFoo.DoSomething;
> 

This one might be non-doable with the alias as it will almost certainly requirer some translation code.
October 24, 2006
Walter Bright wrote:
> The first one works as:
> 
>> class Foo
>> {
>>     int[2] nodes;
>>     int left() { return nodes[0]; }
>>     int right() { return nodes[1]; }
>> }
Except that this doesn't support writing of the nodes. For that, you would need to write property setters as well, making the code:

class Foo
{
    int[2] nodes;
    int left() { return nodes[0]; }
    int left(int val) { return nodes[0] = val; }
    int right() { return nodes[1]; }
    int right(int val) { return nodes[1] = val; }
}

which is much more verbose than the (impossible) alias version:

class Foo
{
    int[2] nodes;
    alias nodes[0] left;
    alias nodes[1] right;
}

Never worry, I thought I would try to make a mixin that supports it:

template readerWriter(alias b)
{
  private alias typeof(b) T;
  T rw() { return b; }
  T rw(T val) { return b = val; }
}

struct Foo
{
  int[2] stuff;
  mixin readerWriter!(stuff[0]) _left;
  alias _left.rw left;
  mixin readerWriter!(stuff[1]) _right;
  alias _right.rw right;
}

Except for the renaming-of-mixins issue (that argument's for another day), the code would have been pretty simple, except that it doesn't work for pretty much the same reason -- you can't alias this kind of thing.

And, of course, you have all the normal property issues:
  - you can't be sure they'll be inlined
  - you can't do left++
  - you can't do 'auto val = left;'


> 
> And the other:
> 
>> class Foo
>>   {
>>     void DoSomething() { }
>>   }
>>
>>   class FooHandle
>>   {
>>     Foo myFoo;
>>     void DoSomething() { myFoo.DoSomething(); }
>>   }
> 

I agree, there's not much problem with this, but here it's a question of convenience and consistency: we can use alias to forward local functions (presumably because you decided it wouldn't be too hard to do, and changing the signatures is a pain which could be avoided) yet we can't use it to forward non-local functions. In fact, it can get much more complex than that, if you have a lot of overloads, or a function signature which changes a lot:

class MyPrinter
{
  void print(int) {}
  void print(char) {}
  void print(char[]) {}
   ...
}

class PrinterHandle
{
   MyPrinter p;
   alias p.print print;
}

as opposed to

class PrinterHandle2
{
   MyPrinter p;
   void print(int val) { p.print(val); }
   void print(char val) { p.print(val); }
   void print(char[] val) { p.print(val); }
   ...
}

While I do think that (if just for consistency's sake) we shouldn't have this restriction on aliases, I realise that this is a problem of syntactical optimization, and the best approach (again) would be to embody a form of metaprogramming which could support this sort of thing in libraries because this is not the only syntactical inefficiency in the language, and we need some much more extensible way to remove such inefficiencies; I think Nemerle could be a good place to look for such a metaprogramming/macro system.

Cheers,

Reiner
October 24, 2006
Reiner Pope wrote:
> While I do think that (if just for consistency's sake) we shouldn't have this restriction on aliases, I realise that this is a problem of syntactical optimization, and the best approach (again) would be to embody a form of metaprogramming which could support this sort of thing in libraries because this is not the only syntactical inefficiency in the language, and we need some much more extensible way to remove such inefficiencies; I think Nemerle could be a good place to look for such a metaprogramming/macro system.

I agree with all of your points. Whether it is worth adding more to D to account for it basically depends on how often this happens, and how onerous are the workarounds.
1 2
Next ›   Last »