www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How is `auto` and not `alias` appropriate for alias sequences?

reply Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
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
Dec 11 2015
next sibling parent reply ZombineDev <valid_email he.re> writes:
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
Dec 11 2015
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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).
Dec 11 2015
parent reply ZombineDev <valid_email he.re> writes:
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).
Dec 11 2015
parent ZombineDev <valid_email he.re> writes:
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.
Dec 11 2015
prev sibling next sibling parent reply ZombineDev <valid_email he.re> writes:
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
Dec 11 2015
parent Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
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
Dec 11 2015
prev sibling parent reply Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
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
Dec 11 2015
parent reply Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
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
Dec 11 2015
parent Meta <jared771 gmail.com> writes:
On Saturday, 12 December 2015 at 06:15:10 UTC, Shriramana Sharma 
wrote:
 Another twist to this is that the tuple created by .tupleof 
 doesn't really seem to be a new object of type Tuple!()
Correct. There's no relation between Tuple and what .tupleof produces. The notion of what constitutes a "tuple" in D is somewhat complicated.
 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.
It's more or less a type internal to the compiler that shares some of its properties with AliasSeq, but I believe that it's subtly different, such as what you mentioned about it being a "view" on a struct/object.
 Also: what is the use of presenting the members of a 
 struct/class as a tuple? Is it iteration?
Yes, and I also believe that assigning to the .tupleof of a struct/object bypasses protected/private.
Dec 12 2015
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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.
Dec 11 2015