digitalmars.D - How is `auto` and not `alias` appropriate for alias sequences?
- Shriramana Sharma (13/13) Dec 11 2015 Hello. I just found that the following code compiles without any problem...
- ZombineDev (15/28) Dec 11 2015 alias can refer to types, templates, template argument lists and
- Timon Gehr (10/12) Dec 11 2015 Yes it can.
- ZombineDev (4/19) Dec 11 2015 Yeah, I forgot to add that it can refer to symbols. Using this
- ZombineDev (7/30) Dec 11 2015 To clarify: By using alias you can refer to one symbol through
- ZombineDev (33/34) Dec 11 2015 In short, the current D terminology calls:
- Shriramana Sharma (5/10) Dec 11 2015 Excellent explanation. I keep looking for a "Like" or "Upvote" button on...
- Shriramana Sharma (25/36) Dec 11 2015 In which case, why should taking its address fail? If I try to do:
- Shriramana Sharma (20/20) Dec 11 2015 Another twist to this is that the tuple created by .tupleof doesn't real...
- Meta (11/18) Dec 12 2015 Correct. There's no relation between Tuple and what .tupleof
- Timon Gehr (19/31) Dec 11 2015 The alias should compile. This is a compiler bug.
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. --
Dec 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
Dec 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).
Dec 11 2015
On Friday, 11 December 2015 at 14:25:45 UTC, Timon Gehr wrote:On 12/11/2015 03:12 PM, ZombineDev wrote: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).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
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: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.On 12/11/2015 03:12 PM, ZombineDev wrote: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).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
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 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
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 -> TupleExcellent explanation. I keep looking for a "Like" or "Upvote" button on this forum. :-) Thanks! --
Dec 11 2015
ZombineDev wrote: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; --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 stillauto can refer only to run-time values. foo is run-time value.
Dec 11 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? --
Dec 11 2015
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
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