digitalmars.D.learn - Alias type with different initialiser.
- Bastiaan Veelo (29/29) Feb 13 2017 Hi,
- Daniel Kozak via Digitalmars-d-learn (2/31) Feb 13 2017 https://dlang.org/phobos/std_typecons.html#.Typedef
- Bastiaan Veelo (42/43) Feb 13 2017 Thanks for the pointers. Both Typedef and Proxy create types that
- John Colvin (43/48) Feb 13 2017 Why not use a constructor instead of static opCall? Also, it's
- John Colvin (2/7) Feb 13 2017
- Bastiaan Veelo (7/14) Feb 14 2017 What is the difference between
- John Colvin (4/21) Feb 14 2017 just a more modern style. I think the old style would have been
- Bastiaan Veelo (65/73) Feb 14 2017 I don't know, this comes from
- John Colvin (21/94) Feb 14 2017 The docs are just trying to illustrate that opCall is only used
- Bastiaan Veelo (4/7) Feb 14 2017 Yes, I think there is high chance it will be part of Phobos, if
- Jonathan M Davis via Digitalmars-d-learn (5/9) Feb 14 2017 And there's actually a decent chance that at some point, it will become
- Daniel Kozak via Digitalmars-d-learn (20/59) Feb 13 2017 or you can use Proxy
Hi, In Extended Pascal, you can derive from a basic type and change the default initialiser like so: type int1 = integer value 1; var i : int1; ii : int1 value 2; assert(i = 1); assert(ii = 2); I have it working in D, but it seems a little clumsy. Is there a better way? struct initial(T, T val) { private T _payload = val; alias _payload this; static initial opCall(T v) { initial s; s._payload = v; return s; } } unittest { alias initial!(int, 1) int1; int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); }
Feb 13 2017
Dne 13.2.2017 v 16:28 Bastiaan Veelo via Digitalmars-d-learn napsal(a):Hi, In Extended Pascal, you can derive from a basic type and change the default initialiser like so: type int1 = integer value 1; var i : int1; ii : int1 value 2; assert(i = 1); assert(ii = 2); I have it working in D, but it seems a little clumsy. Is there a better way? struct initial(T, T val) { private T _payload = val; alias _payload this; static initial opCall(T v) { initial s; s._payload = v; return s; } } unittest { alias initial!(int, 1) int1; int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); }https://dlang.org/phobos/std_typecons.html#.Typedef
Feb 13 2017
On Monday, 13 February 2017 at 16:40:02 UTC, Daniel Kozak wrote:https://dlang.org/phobos/std_typecons.html#.TypedefThanks for the pointers. Both Typedef and Proxy create types that don't mix with the base type, which I want to the contrary. So I guess I'll go with struct Initial(T, T val) { private T _payload = val; alias _payload this; static Initial opCall(T v) { Initial s; s._payload = v; return s; } static T init() { return val; } } unittest { alias Initial!(int, 1) int1; int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); assert(ii.init == 1); assert(int1.init == 1); void f(int val) { assert(val == 1); } f(i); int i0; assert(i0 == 0); i = i0; assert(i == 0); assert(i.init == 1); i0 = ii; assert(i0 == 2); assert(i0.init == 0); }
Feb 13 2017
On Monday, 13 February 2017 at 22:16:36 UTC, Bastiaan Veelo wrote:On Monday, 13 February 2017 at 16:40:02 UTC, Daniel Kozak wrote:Why not use a constructor instead of static opCall? Also, it's generally a bad idea to define `.init` for any type as code generally expects this to be the compiler-generated property (e.g. a value of type Initial!(int, 1) not of type int). So, perhaps like this: struct Initial(T, T val) { private T _payload = val; alias _payload this; this(T v) { _payload = v; } enum initial = val; } unittest { alias Initial!(int, 1) int1; static assert(int1.initial == 1); // typeof(int1.initial) == int static assert(int1.init == 1); // typeof(int1.init) == typeof(int1) int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); assert(ii.init == 1); assert(int1.init == 1); void f(int val) { assert(val == 1); } f(i); int i0; assert(i0 == 0); i = i0; assert(i == 0); assert(i.init == 1); i0 = ii; assert(i0 == 2); assert(i0.init == 0); }https://dlang.org/phobos/std_typecons.html#.TypedefThanks for the pointers. Both Typedef and Proxy create types that don't mix with the base type, which I want to the contrary. So I guess I'll go with
Feb 13 2017
On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:[ snip ]sorry, made a typo, that should have beenalias int1 = Initial!(int, 1); static assert(int1.initial == 1); // typeof(int1.initial) == int static assert(int1.init == 1); // typeof(int1.init) == int1
Feb 13 2017
On Tuesday, 14 February 2017 at 01:31:10 UTC, John Colvin wrote:On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:What is the difference between alias Initial!(int, 1) int1; and alias int1 = Initial!(int, 1); ? Or was the typo in the comments alone? Thanks.[ snip ]sorry, made a typo, that should have beenalias int1 = Initial!(int, 1); static assert(int1.initial == 1); // typeof(int1.initial) == int static assert(int1.init == 1); // typeof(int1.init) == int1
Feb 14 2017
On Tuesday, 14 February 2017 at 10:49:19 UTC, Bastiaan Veelo wrote:On Tuesday, 14 February 2017 at 01:31:10 UTC, John Colvin wrote:just a more modern style. I think the old style would have been deprecated if it wasn't for how much old code used it.On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:What is the difference between alias Initial!(int, 1) int1; and alias int1 = Initial!(int, 1); ? Or was the typo in the comments alone? Thanks.[ snip ]sorry, made a typo, that should have beenalias int1 = Initial!(int, 1); static assert(int1.initial == 1); // typeof(int1.initial) == int static assert(int1.init == 1); // typeof(int1.init) == int1
Feb 14 2017
On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:Why not use a constructor instead of static opCall?I don't know, this comes from http://dlang.org/spec/struct.html#dynamic_struct_init. Your constructor looks a lot better. Am I missing a test case where static opCall would be called, but not the constructor? Why do the docs use static opCall?Also, it's generally a bad idea to define `.init` for any type as code generally expects this to be the compiler-generated property (e.g. a value of type Initial!(int, 1) not of type int).Thanks. I can't remember what confused me to think that typeof(int1.init) had to be int.enum initial = val;[...]static assert(int1.initial == 1); // typeof(int1.initial) == intThese lines have no purpose beyond illustration, right? I now have the following, featuring the novel Scherkl-Nielsen self-important lookup: /** Creates an type that is mostly $(PARAM T), only with a different initial value of $(PARAM val). */ struct Initial(T, T val) { private T _payload = val; alias _payload this; this(T v) { _payload = v; } // https://dlang.org/blog/2017/02/13/a-new-import-idiom/ private template from(string moduleName) { mixin("import from = " ~ moduleName ~ ";"); } void toString(scope void delegate(const(char)[]) sink, from!"std.format".FormatSpec!char fmt) { import std.array : appender; import std.format : formatValue; auto w = appender!string(); formatValue(w, _payload, fmt); sink(w.data); } } unittest { alias int1 = Initial!(int, 1); static assert(int1.init == 1); // typeof(int1.init) == int1 int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); assert(ii.init == 1); assert(int1.init == 1); void f(int val) { assert(val == 1); } f(i); int i0; assert(i0 == 0); i = i0; assert(i == 0); assert(i.init == 1); i0 = ii; assert(i0 == 2); assert(i0.init == 0); import std.string; assert(format("%6d", ii) == " 2"); }
Feb 14 2017
On Tuesday, 14 February 2017 at 11:34:22 UTC, Bastiaan Veelo wrote:On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:The docs are just trying to illustrate that opCall is only used for initialisation if the initialiser is of a different type. Constructors are always used for initialisation if they are there, they completely hide static opCall in that context. static opCall can return anything of any type, constructors implicitly return a reference to `this`. A constructor is the way to initialise a type and some code - such as std.conv.emplace - actually calls the constructor manually (it's accessible via .__ctor) to do so. static opCall doesn't necessarily represent an initialiser function, so generic code won't necessarily know to use it. Overall, static opCall is rarely the solution you need.Why not use a constructor instead of static opCall?I don't know, this comes from http://dlang.org/spec/struct.html#dynamic_struct_init. Your constructor looks a lot better. Am I missing a test case where static opCall would be called, but not the constructor? Why do the docs use static opCall?they check that the implementation does have a member .initial and that it is equal to the value we requested as the initialiser. It also enforces that it is accessible at compile-time.Also, it's generally a bad idea to define `.init` for any type as code generally expects this to be the compiler-generated property (e.g. a value of type Initial!(int, 1) not of type int).Thanks. I can't remember what confused me to think that typeof(int1.init) had to be int.enum initial = val;[...]static assert(int1.initial == 1); // typeof(int1.initial) == intThese lines have no purpose beyond illustration, right?I now have the following, featuring the novel Scherkl-Nielsen self-important lookup: /** Creates an type that is mostly $(PARAM T), only with a different initial value of $(PARAM val). */ struct Initial(T, T val) { private T _payload = val; alias _payload this; this(T v) { _payload = v; } // https://dlang.org/blog/2017/02/13/a-new-import-idiom/ private template from(string moduleName) { mixin("import from = " ~ moduleName ~ ";"); } void toString(scope void delegate(const(char)[]) sink, from!"std.format".FormatSpec!char fmt) { import std.array : appender; import std.format : formatValue; auto w = appender!string(); formatValue(w, _payload, fmt); sink(w.data); } } unittest { alias int1 = Initial!(int, 1); static assert(int1.init == 1); // typeof(int1.init) == int1 int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); assert(ii.init == 1); assert(int1.init == 1); void f(int val) { assert(val == 1); } f(i); int i0; assert(i0 == 0); i = i0; assert(i == 0); assert(i.init == 1); i0 = ii; assert(i0 == 2); assert(i0.init == 0); import std.string; assert(format("%6d", ii) == " 2"); }I would recommend making `template from(string moduleName)` global (maybe in a utils module?), there's no reason for it to be a member of Initial.
Feb 14 2017
Thanks again. On Tuesday, 14 February 2017 at 14:08:31 UTC, John Colvin wrote:I would recommend making `template from(string moduleName)` global (maybe in a utils module?), there's no reason for it to be a member of Initial.Yes, I think there is high chance it will be part of Phobos, if chosen in favour of DIP 1005.
Feb 14 2017
On Monday, February 13, 2017 22:59:11 John Colvin via Digitalmars-d-learn wrote:Also, it's generally a bad idea to define `.init` for any type as code generally expects this to be the compiler-generated property (e.g. a value of type Initial!(int, 1) not of type int).And there's actually a decent chance that at some point, it will become illegal precisely because of the problems that it causes to allow it. - Jonathan M Davis
Feb 14 2017
Dne 13.2.2017 v 17:40 Daniel Kozak napsal(a):Dne 13.2.2017 v 16:28 Bastiaan Veelo via Digitalmars-d-learn napsal(a):or you can use Proxy https://dlang.org/phobos/std_typecons.html#.Proxy struct initial(T, T val) { private T _payload = val; mixin Proxy!_payload; this(T v) { _payload = v; } } unittest { alias initial!(int, 1) int1; int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); }Hi, In Extended Pascal, you can derive from a basic type and change the default initialiser like so: type int1 = integer value 1; var i : int1; ii : int1 value 2; assert(i = 1); assert(ii = 2); I have it working in D, but it seems a little clumsy. Is there a better way? struct initial(T, T val) { private T _payload = val; alias _payload this; static initial opCall(T v) { initial s; s._payload = v; return s; } } unittest { alias initial!(int, 1) int1; int1 i; assert(i == 1); int1 ii = 2; assert(ii == 2); }https://dlang.org/phobos/std_typecons.html#.Typedef
Feb 13 2017