Jump to page: 1 2
Thread overview
How is `auto` and not `alias` appropriate for alias sequences?
Dec 11, 2015
Shriramana Sharma
Dec 11, 2015
ZombineDev
Dec 11, 2015
Timon Gehr
Dec 11, 2015
ZombineDev
Dec 11, 2015
ZombineDev
Dec 11, 2015
ZombineDev
Dec 12, 2015
Shriramana Sharma
Dec 12, 2015
Shriramana Sharma
Dec 12, 2015
Shriramana Sharma
Dec 12, 2015
Meta
Dec 11, 2015
Timon Gehr
December 11, 2015
Hello. I just found that the following code compiles without any problem:

    struct Foo { int val; string name; }
    Foo foo = {1, "one"};
    auto t = foo.tupleof;

Trying to use `alias` i.o. `auto` above fails.

Now IIUC, trying to take the address of t fails, so it's still a compile- time-only construct without "real" i.e. runtime existence. The tuple is in fact an AliasSeq, no? In which case, I would have thought that `alias` (for compile-time symbols) and not `auto` (for runtime variables) would be the appropriate choice.

Can someone please explain this situation? Thanks.

-- 
Shriramana Sharma, Penguin #395953
December 11, 2015
On Friday, 11 December 2015 at 11:18:39 UTC, Shriramana Sharma wrote:
> Hello. I just found that the following code compiles without any problem:
>
>     struct Foo { int val; string name; }
>     Foo foo = {1, "one"};
>     auto t = foo.tupleof;
>
> Trying to use `alias` i.o. `auto` above fails.
>
> Now IIUC, trying to take the address of t fails, so it's still a compile- time-only construct without "real" i.e. runtime existence. The tuple is in fact an AliasSeq, no? In which case, I would have thought that `alias` (for compile-time symbols) and not `auto` (for runtime variables) would be the appropriate choice.
>
> Can someone please explain this situation? Thanks.

alias can refer to types, templates, template argument lists and compile-time expressions. It can't refer to run-time variables.

auto can refer only to run-time values.

foo is run-time value.

foo.tupleof is also run-time value, like an object of some template instance of std.typecons.Tuple.

The template arguments list of std.typecons.Tuple is a compile-time sequence that you can put in AliasSeq.

typeof(foo.tupleof) is a type list to which you can only refer with alias or use as template arguments for some template.

For example you can put typeof(foo.tupleof) in AliasSeq:
alias FooFieldTypes = AliasSeq!(typeof(foo.tupleof));

http://dpaste.dzfl.pl/decbc38e6e71
December 11, 2015
On 12/11/2015 12:18 PM, Shriramana Sharma wrote:
> Hello. I just found that the following code compiles without any problem:
>
>      struct Foo { int val; string name; }
>      Foo foo = {1, "one"};
>      auto t = foo.tupleof;
>
> Trying to use `alias` i.o. `auto` above fails.
> ...

The alias should compile. This is a compiler bug.
Workaround:

import std.stdio;
alias Seq(T...)=T;

void main(){
    struct Foo{int val;string name;}
    Foo foo={1,"one"};
    alias t=Seq!(foo.tupleof);
}

However, this still might not do what you want. The above alias is the same as alias t=Seq!(Foo.tupleof);. This is a general and arbitrary limitation of alias declarations.


> Now IIUC, trying to take the address of t fails, so it's still a compile-
> time-only construct without "real" i.e. runtime existence. The tuple is in
> fact an AliasSeq, no? In which case, I would have thought that `alias` (for
> compile-time symbols) and not `auto` (for runtime variables) would be the
> appropriate choice.
>
> Can someone please explain this situation? Thanks.
>

The line

auto t=foo.tupleof;

declares two variables and aliases them into a Seq of name 't'.
(It is the same as Seq!(int,string) t=foo.tupleof; )
t[0] and t[1] are two distinct variables. This is also why you were not able take the address of t.


December 11, 2015
On 12/11/2015 03:12 PM, ZombineDev wrote:
>
> alias can refer to types, templates, template argument lists and
> compile-time expressions. It can't refer to run-time variables.

Yes it can.

void main(){
    int x=0;
    alias y=x;
    y=2;
    assert(x==2)
}

It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).
December 11, 2015
On Friday, 11 December 2015 at 14:12:16 UTC, ZombineDev wrote:
> [...]

In short, the current D terminology calls:
compile-time lists -> AliasSeq (http://dlang.org/phobos/std_meta#AliasSeq)
run-time values of type lists -> Tuple (http://dlang.org/phobos/std_typecons#.Tuple)

Another example:

Tuple!(int, string)(3, "apples") obj;

obj is a run-time tuple of the integer 3 and the string "apples".

The template arguments int and string are a type list (and a special case of an alias sequence).

alias Point2D = Tuple!(int, "x", int, "" ~ 'y');

auto point_a = Point2D(3, 4);
auto point_b = Point2D(1, -7);

Point2D is an alias to the type Tuple!(int, "x", int, "" ~ 'y'), which is a template instance of the Tuple(Specs...) template.

The (int, "x", int, "" ~ 'y') template arguments have both types and compile-time expressions among them and that's why we call it an alias sequence and not just a type list.

point_a and point_b are tuples of two ints and are run-time values.

You can put the template arguments used for Point2D in a AliasSeq:

alias Point3DTemplateArgs = AliasSeq!(float, "x", int, "y", double, "z");

And you can use those template args to make a new instance of the Tuple template:

alias Point3D = Tuple!(Point3DTemplateArgs);

Some runtime values can also be computed at compile-time and you can use them for enums.

http://dpaste.dzfl.pl/a05cf181331d (I think that only the output of "2:" is inconsistent.)

Also I found this article, which maybe helpful: http://dlang.org/ctarguments.html
December 11, 2015
On Friday, 11 December 2015 at 14:25:45 UTC, Timon Gehr wrote:
> On 12/11/2015 03:12 PM, ZombineDev wrote:
>>
>> alias can refer to types, templates, template argument lists and
>> compile-time expressions. It can't refer to run-time variables.
>
> Yes it can.
>
> void main(){
>     int x=0;
>     alias y=x;
>     y=2;
>     assert(x==2)
> }
>
> It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).

Yeah, I forgot to add that it can refer to symbols. Using this featue, you can implement a pass by name function (in addition to pass by value and pass by reference / address).
December 11, 2015
On Friday, 11 December 2015 at 14:56:01 UTC, ZombineDev wrote:
> On Friday, 11 December 2015 at 14:25:45 UTC, Timon Gehr wrote:
>> On 12/11/2015 03:12 PM, ZombineDev wrote:
>>>
>>> alias can refer to types, templates, template argument lists and
>>> compile-time expressions. It can't refer to run-time variables.
>>
>> Yes it can.
>>
>> void main(){
>>     int x=0;
>>     alias y=x;
>>     y=2;
>>     assert(x==2)
>> }
>>
>> It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).
>
> Yeah, I forgot to add that it can refer to symbols. Using this featue, you can implement a pass by name function (in addition to pass by value and pass by reference / address).

To clarify: By using alias you can refer to one symbol through another name.
So alias can refer to variables, but not to values.
Currently, I think this is restricted to only symbols of run-time variables in the same scope (same function, same class, etc.) - only one level of indirection.
December 12, 2015
ZombineDev wrote:

> In short, the current D terminology calls:
> compile-time lists -> AliasSeq
> (http://dlang.org/phobos/std_meta#AliasSeq)
> run-time values of type lists -> Tuple
> (http://dlang.org/phobos/std_typecons#.Tuple)

Excellent explanation. I keep looking for a "Like" or "Upvote" button on this forum. :-) Thanks!

-- 
Shriramana Sharma, Penguin #395953
December 12, 2015
ZombineDev wrote:

>>struct Foo { int val; string name; }
>>Foo foo = {1, "one"};
>>auto t = foo.tupleof;
>>
>> Trying to use `alias` i.o. `auto` above fails.
>>
>> Now IIUC, trying to take the address of t fails, so it's still
> 
> auto can refer only to run-time values.
> 
> foo is run-time value.

In which case, why should taking its address fail? If I try to do:

auto tp = &t;

I'm getting:

Error: tuple(__t_field_0, __t_field_1) is not an lvalue

What the!? *After* I assign it to a variable, it still says it's not an lvalue? I mean I understand if I can't take the address of a compiler- created temporary rvalue, but why can't I take its address even after I assign it to a newly created variable? Does the variable t have an address in memory or not?

I understand that:

alias t2 = foo.tupleof;

doesn't work since you cannot give an alias to an rvalue temporary, since t2 would be pointing to nothing after the (immediate) destruction of the temporary tuple object. But I can still do:

alias t2 = t;

So why can't I do:

auto tp = &t;

???

Note that the following, which should be equivalent, works:

    alias FooTuple = Tuple!(int, string);
    FooTuple footu = FooTuple(1, "one");
    auto ttp = &footu;

-- 
Shriramana Sharma, Penguin #395953
December 12, 2015
Another twist to this is that the tuple created by .tupleof doesn't really seem to be a new object of type Tuple!() but rather a "view" of sorts onto the original object itself in the form of a tuple, else the example provided at http://dlang.org/spec/class.html i.e.:

class Foo { int x; long y; }
void test(Foo foo)
{
    foo.tupleof[0] = 1; // set foo.x to 1
    foo.tupleof[1] = 2; // set foo.y to 2
    foreach (x; foo.tupleof)
        write(x);       // prints 12
}

wouldn't be able to set values to the original class instance via whatever .tupleof generates.

So the exact nature of the object produced by .tupleof is still a mystery to me. Would be good if someone threw more light on it.

Also: what is the use of presenting the members of a struct/class as a tuple? Is it iteration?

-- 
Shriramana Sharma, Penguin #395953
« First   ‹ Prev
1 2