digitalmars.D - enum pointers or class references limitation
- Dmitry Olshansky (26/26) Aug 30 2017 The subj is not (any longer) supported by compiler. In fact it
- Timon Gehr (5/39) Aug 30 2017 I think the underlying reason why it does not work is that dynamic array...
- Dmitry Olshansky (6/15) Aug 31 2017 Well from my point of view enum is just evaluate this expression
- Nicholas Wilson (7/23) Aug 31 2017 I think Timon is referring to:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/10) Aug 31 2017 Even better:
- Dmitry Olshansky (5/18) Sep 01 2017 I guess
- =?UTF-8?Q?Ali_=c3=87ehreli?= (10/31) Sep 01 2017 In the surprising case foo is a symbol, seemingly of a variable. Failing...
- Q. Schroll (13/28) Sep 01 2017 That's a good reason to unrecommend/disallow enums with
- Q. Schroll (14/17) Sep 01 2017 While
- Timon Gehr (7/27) Sep 01 2017 This is called string pooling. This passed too:
- Timon Gehr (9/44) Sep 01 2017 It can be useful to have enums with indirections available for
- Timon Gehr (38/62) Sep 01 2017 I know what it does and do expect it. I still consider it problematic.
The subj is not (any longer) supported by compiler. In fact it used to produce wrong code sometimes and now it just plainly rejects it. It's freaking inconvenient because I can't deploy new compile-time std.regex w/o it. The example: enum ctr = ctRegex!"blah"; after my changes must be: static immutable ctr = ctRegex!"blah"; Howeever I divised a trick to get equivalent functionality as follows: template ctRegexImpl(alias pattern, string flags=[]) { static immutable staticRe = ...; struct Wrapper { property auto getRe(){ return staticRe; } alias getRe this; } enum wrapper = Wrapper(); } public enum ctRegex(alias pattern, alias flags=[]) = ctRegexImpl!(pattern, flags).wrapper; Now ctRegex returns a neat forwarding struct that bypasses the strange limitation. The question remains though - why can't compiler do it automatically?
Aug 30 2017
On 30.08.2017 11:36, Dmitry Olshansky wrote:The subj is not (any longer) supported by compiler. In fact it used to produce wrong code sometimes and now it just plainly rejects it. It's freaking inconvenient because I can't deploy new compile-time std.regex w/o it. The example: enum ctr = ctRegex!"blah"; after my changes must be: static immutable ctr = ctRegex!"blah"; Howeever I divised a trick to get equivalent functionality as follows: template ctRegexImpl(alias pattern, string flags=[]) { static immutable staticRe = ...; struct Wrapper { property auto getRe(){ return staticRe; } alias getRe this; } enum wrapper = Wrapper(); } public enum ctRegex(alias pattern, alias flags=[]) = ctRegexImpl!(pattern, flags).wrapper; Now ctRegex returns a neat forwarding struct that bypasses the strange limitation. The question remains though - why can't compiler do it automatically?I think the underlying reason why it does not work is that dynamic array manifest constants are messed up. I.e. class reference `enum`s are disallowed in order to avoid having to make a decision for either inconsistent or insane semantics.
Aug 30 2017
On Wednesday, 30 August 2017 at 12:28:10 UTC, Timon Gehr wrote:On 30.08.2017 11:36, Dmitry Olshansky wrote:[..]The subj is not (any longer) supported by compiler. In fact it used to produce wrong code sometimes and now it just plainly rejects it.I think the underlying reason why it does not work is that dynamic array manifest constants are messed up. I.e. class reference `enum`s are disallowed in order to avoid having to make a decision for either inconsistent or insane semantics.Well from my point of view enum is just evaluate this expression at the usage site. So any array or class instance will be created anew at the point of usage. What are the problems with enums and dynamic arrays?
Aug 31 2017
On Thursday, 31 August 2017 at 08:40:03 UTC, Dmitry Olshansky wrote:On Wednesday, 30 August 2017 at 12:28:10 UTC, Timon Gehr wrote:I think Timon is referring to: enum int[] foo = [1,2,3]; auto bar = foo; auto baz = foo; assert(!(bar is baz)); // PassesOn 30.08.2017 11:36, Dmitry Olshansky wrote:[..]The subj is not (any longer) supported by compiler. In fact it used to produce wrong code sometimes and now it just plainly rejects it.I think the underlying reason why it does not work is that dynamic array manifest constants are messed up. I.e. class reference `enum`s are disallowed in order to avoid having to make a decision for either inconsistent or insane semantics.Well from my point of view enum is just evaluate this expression at the usage site. So any array or class instance will be created anew at the point of usage. What are the problems with enums and dynamic arrays?
Aug 31 2017
On 08/31/2017 01:52 AM, Nicholas Wilson wrote:I think Timon is referring to: enum int[] foo = [1,2,3]; auto bar = foo; auto baz = foo; assert(!(bar is baz)); // PassesEven better: enum int[] foo = [1,2,3]; assert(!(foo is foo)); // Passes Ali
Aug 31 2017
On Thursday, 31 August 2017 at 14:28:57 UTC, Ali Çehreli wrote:On 08/31/2017 01:52 AM, Nicholas Wilson wrote:I guess assert(!([1,2,3] is [1,2,3])); Which is exactly what enum expands to and totally expected. Where is the surprise?I think Timon is referring to: enum int[] foo = [1,2,3]; auto bar = foo; auto baz = foo; assert(!(bar is baz)); // PassesEven better: enum int[] foo = [1,2,3]; assert(!(foo is foo)); // PassesAli
Sep 01 2017
On 09/01/2017 11:48 AM, Dmitry Olshansky wrote:On Thursday, 31 August 2017 at 14:28:57 UTC, Ali Çehreli wrote:In the surprising case foo is a symbol, seemingly of a variable. Failing the 'is' test is surprising in that case. I've just remembered that the actual surprising case is the following explicit check: assert(!(foo.ptr is foo.ptr)); // Passes I find it surprising because it looks like an entity does not have a well-behaving .ptr. (Aside: I think your code might be surprising to at least newcomers as well.) AliOn 08/31/2017 01:52 AM, Nicholas Wilson wrote:I guess assert(!([1,2,3] is [1,2,3])); Which is exactly what enum expands to and totally expected. Where is the surprise?I think Timon is referring to: enum int[] foo = [1,2,3]; auto bar = foo; auto baz = foo; assert(!(bar is baz)); // PassesEven better: enum int[] foo = [1,2,3]; assert(!(foo is foo)); // Passes
Sep 01 2017
On Friday, 1 September 2017 at 21:08:20 UTC, Ali Çehreli wrote:[snip]This is not a surprise. Array literals are not identical.assert(!([1,2,3] is [1,2,3])); Which is exactly what enum expands to and totally expected.Where is thesurprise?In the surprising case foo is a symbol, seemingly of a variable. Failing the 'is' test is surprising in that case. I've just remembered that the actual surprising case is the following explicit check: assert(!(foo.ptr is foo.ptr)); // Passes I find it surprising because it looks like an entity does not have a well-behaving .ptr. (Aside: I think your code might be surprising to at least newcomers as well.)That's a good reason to unrecommend/disallow enums with indirections. The compiler should recommend/suggest using static immutable instead as it does not have such oddities. The only advantage of enum is being guaranteed to be known at compile-time and they can be templatized (can be also done for static immutable via eponymous template). I'd vote for a warning/error when the type of an enum has indirections together with a pragma to switch the warning off for the rare case you know exactly what you do. Just as Scott Meyers said: make it easy to use correctly and hard to use incorrectly. Today it's easy to use incorrectly.
Sep 01 2017
On Friday, 1 September 2017 at 23:13:50 UTC, Q. Schroll wrote:[..] Just as Scott Meyers said: make it easy to use correctly and hard to use incorrectly. Today it's easy to use incorrectly.While enum foo = [1,2,3]; assert(foo is foo); fails, enum bla = "123"; assert(foo is foo); passes. Enhancement request submitted: https://issues.dlang.org/show_bug.cgi?id=17799 Unfortunately after I found out the second one does not have to do with mutability. Making foo immutable(int)[] does not change anything. It only works for const(char)[], immutable(char)[], and probably w/dchar friends. That's odd.
Sep 01 2017
On 02.09.2017 01:37, Q. Schroll wrote:On Friday, 1 September 2017 at 23:13:50 UTC, Q. Schroll wrote:This is called string pooling. This passed too: void main(){ assert("123" is "123"); } D (at least sometimes) allows the identities of different immutable locations to become conflated.[..] Just as Scott Meyers said: make it easy to use correctly and hard to use incorrectly. Today it's easy to use incorrectly.While enum foo = [1,2,3]; assert(foo is foo); fails, enum bla = "123"; assert(foo is foo); passes. Enhancement request submitted: https://issues.dlang.org/show_bug.cgi?id=17799 Unfortunately after I found out the second one does not have to do with mutability. Making foo immutable(int)[] does not change anything. It only works for const(char)[], immutable(char)[], and probably w/dchar friends. That's odd.
Sep 01 2017
On 02.09.2017 01:13, Q. Schroll wrote:On Friday, 1 September 2017 at 21:08:20 UTC, Ali Çehreli wrote:It can be useful to have enums with indirections available for metaprogramming, for intermediate data typed as mutable that is not necessarily required while running the program, yet can be read during compilation.[snip]This is not a surprise. Array literals are not identical.assert(!([1,2,3] is [1,2,3])); Which is exactly what enum expands to and totally expected.Where is thesurprise?In the surprising case foo is a symbol, seemingly of a variable. Failing the 'is' test is surprising in that case. I've just remembered that the actual surprising case is the following explicit check: assert(!(foo.ptr is foo.ptr)); // Passes I find it surprising because it looks like an entity does not have a well-behaving .ptr. (Aside: I think your code might be surprising to at least newcomers as well.)That's a good reason to unrecommend/disallow enums with indirections.The compiler should recommend/suggest using static immutable instead as it does not have such oddities.It types your data as immutable.The only advantage of enum is being guaranteed to be known at compile-timeThat is not an advantage of enum, as the same is true for static immutable.and they can be templatized (can be also done for static immutable via eponymous template). I'd vote for a warning/error when the type of an enum has indirections together with a pragma to switch the warning off for the rare case you know exactly what you do. Just as Scott Meyers said: make it easy to use correctly and hard to use incorrectly. Today it's easy to use incorrectly.Note that enums with indirections are already disallowed, except for dynamic arrays.
Sep 01 2017
On 01.09.2017 20:48, Dmitry Olshansky wrote:On Thursday, 31 August 2017 at 14:28:57 UTC, Ali Çehreli wrote:I know what it does and do expect it. I still consider it problematic. It's conceivable that someone just wants an enum slice to statically allocated array data (or a enum struct instance that has a field that is a statically allocated array, etc.). The enum/array literal design makes this impossible.On 08/31/2017 01:52 AM, Nicholas Wilson wrote:I guess assert(!([1,2,3] is [1,2,3])); Which is exactly what enum expands to and totally expected.I think Timon is referring to: enum int[] foo = [1,2,3]; auto bar = foo; auto baz = foo; assert(!(bar is baz)); // PassesEven better: enum int[] foo = [1,2,3]; assert(!(foo is foo)); // PassesWhere is the surprise?My main point is that I don't see why a ctRegex should runtime-allocate a class instance at each usage site. (And if it does not, the difference to array literals is not so easy to justify.) But, there are a number of perhaps surprising behaviors of array literals at compile time that come to mind, some, but not all closely related to the issue at hand: struct S{ int[] x; } static assert(S([1,2,3]) is S([1,2,3])); // ok auto x = S([1,2,3]), y = S([1,2,3]); struct C{ int[] x; this(int[] x){ this.x=x; } } static assert(new C([1,2,3]).x is new C([1,2,3]).x); // ok static assert((){ auto c=new C([1,2,3]); auto d=new C([1,2,3]); assert(c.x is d.x); c.x[0]=2; assert(c.x !is d.x); return true; }()); // ok enum s = S([1,2,3]); immutable t = S([1,2,3]); enum u = t; void main() nogc{ assert(x is y); // fails // auto v = s; // error: gc allocation auto w1 = t; // ok // auto w2 = u; // error (!) } Basically, I think implicitly making expressions confused about their aliasing is just not a good idea. You can see that your: 'enum is just evaluate this expression at the usage site' is not the full story as otherwise w1 and w2 would behave the same.
Sep 01 2017