Jump to page: 1 2
Thread overview
enum pointers or class references limitation
Aug 30, 2017
Dmitry Olshansky
Aug 30, 2017
Timon Gehr
Aug 31, 2017
Dmitry Olshansky
Aug 31, 2017
Nicholas Wilson
Aug 31, 2017
Ali Çehreli
Sep 01, 2017
Dmitry Olshansky
Sep 01, 2017
Ali Çehreli
Sep 01, 2017
Q. Schroll
Sep 01, 2017
Q. Schroll
Sep 01, 2017
Timon Gehr
Sep 01, 2017
Timon Gehr
Sep 01, 2017
Timon Gehr
August 30, 2017
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?

August 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.
August 31, 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?
August 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:
>> 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?

I think Timon is referring to:

enum int[] foo = [1,2,3];

auto bar = foo;
auto baz = foo;

assert(!(bar is baz)); // Passes
August 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)); // Passes

Even better:

    enum int[] foo = [1,2,3];
    assert(!(foo is foo)); // Passes

Ali

September 01, 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 think Timon is referring to:
>>
>> enum int[] foo = [1,2,3];
>>
>> auto bar = foo;
>> auto baz = foo;
>>
>> assert(!(bar is baz)); // Passes
>
> Even better:
>
>     enum int[] foo = [1,2,3];
>     assert(!(foo is foo)); // Passes
>

I guess

assert(!([1,2,3] is [1,2,3]));

Which is exactly what enum expands to and totally expected. Where is the surprise?
> Ali


September 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:
>> 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)); // Passes
>>
>> Even better:
>>
>>     enum int[] foo = [1,2,3];
>>     assert(!(foo is foo)); // Passes
>>
>
> I guess
>
> assert(!([1,2,3] is [1,2,3]));
>
> Which is exactly what enum expands to and totally expected. Where is the
> surprise?

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.)

Ali

September 01, 2017
On Friday, 1 September 2017 at 21:08:20 UTC, Ali Çehreli wrote:
> [snip]
> > assert(!([1,2,3] is [1,2,3]));
> >
> > Which is exactly what enum expands to and totally expected.
> Where is the
> > surprise?

This is not a surprise. Array literals are not identical.

> 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.

September 02, 2017
On 01.09.2017 20:48, Dmitry Olshansky wrote:
> On Thursday, 31 August 2017 at 14:28:57 UTC, Ali Çehreli wrote:
>> 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)); // Passes
>>
>> Even better:
>>
>>     enum int[] foo = [1,2,3];
>>     assert(!(foo is foo)); // Passes
>>
> 
> I guess
> 
> assert(!([1,2,3] is [1,2,3]));
> 
> Which is exactly what enum expands to and totally expected.

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.

> Where 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.
September 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.
« First   ‹ Prev
1 2