April 02
On Tuesday, April 2, 2024 11:30:39 AM MDT Basile B. via dip.ideas wrote:
> forgot to say you can use a struct filled with anonymous enum members too.
>
> ```d
> struct A
> {
>      enum T x = 0;
>      enum T y = 1;
>      enum T z = 2;
> static if (cond)
>      enum T w = 3;
> }
> ```
>
> However RN I cant confirm that the usage is 100% equivalent. Use of the members is likely but use of the container may not, e.g in std.traits (esp. the EnumMembers template ...).


They aren't equivalent at all, because you haven't declared any actual enums. Even though the keyword enum is used, those are all manifest constants within a struct, whereas an enum declaration declares its own type which will be treated as an enum by the type system, and that affects a number of things, including is experessions. For instance, is(A == enum) would be false, and is(A == struct) would be true, whereas if it were an enum declaration, the opposite would be true. Even if the enum's base type were a struct is(E == struct) would still be false, because the enum itself wouldn't be a struct. It would just implicitly convert to its base type which was a struct.

Similarly, you can't use final switch with such a struct. You need an actual enum.

You also couldn't do something like

    auto foo(A a) {...}

and pass it A.x, because x is a T, not an A.

Now, syntactically, such a struct is very similar to an enum declaration, so you can do stuff like A.x, and it would be syntactically the same, but the types would be different, and the way that the type system treats them would be different.

So, depending on what you're doing, a struct with a bunch of manifest constants might do the trick, but really, all you're doing is putting a bunch of manifest constants within a namespace. You're not declaring an enum type.

- Jonathan M Davis



April 03

On Saturday, 30 March 2024 at 14:57:00 UTC, IchorDev wrote:

>

For an enum type with many members—or many conditionals—this quickly becomes an insane amount of repetition.

The logical solution is to just allow conditional compilation statements inside enums:

enum A{
	x,y,z,
    static if(cond){
		w,
	}
}

I don't think static if fits here. There are already special cases for enums which allow things that don't make sense elsewhere when using a declaration list. In particular, requiring the trailing comma is troublesome.

I think what might be in order is to elevate enums to a more structured type (like Swift does).

Something like:

enum ??? foo {
   case x;
   case y;
   case z;
   // constructors?
   this(int n) { this._value = cast(foo)n; }
   // operators?
   opBinary(...)
   // static if works at a declaration scope!
   static if(cond) {
     case a;
   }
}

The ??? is because I'm assuming it would be too ambiguous with existing syntax. Maybe enum struct?

But enums were basically copied from C (with duct-taped on features), and other modern languages (such as swift) have really considered how enums should be designed.

-Steve

April 03

On Saturday, 30 March 2024 at 14:57:00 UTC, IchorDev wrote:

>

For an enum type with many members—or many conditionals—this quickly becomes an insane amount of repetition.

The logical solution is to just allow conditional compilation statements inside enums:

enum A{
	x,y,z,
    static if(cond){
		w,
	}
}

It would be strange if this was enabled just for enums but not for other listings. Other possibilities that come to mind:

auto fun(int a, float b, static if(cond){char c, bool d,}) => //...

import std.algorithm, std.range, static if(cond){std.conv,};

pragma(msg, "hello", static if(cond){"world!",});

Also I'm not quite sure of the syntax. When you list something with commas, it resembles an expression, since function argument lists and array literals are also listed with commas and expressions. But in D, you can't use if or static if as an expression - for that you have the conditional operator cond ? whenTrue : otherwise. Could this idea would work better with the conditional operator syntax?

enum A{x, y, z, cond? w: ()}

On second thought, maybe not. You can't do this inside an array literal either unless you also have a value for the "else" case, and you also can't list multiple values for one condition except by defining another array literal outside the original one and concatenating them. Maybe it's time to let us use ifs and conditional compilation directives as parts of expressions, so it'd be consistent with your proposal?

There's another possibility for enums specifically. This could also be solved if you could define them with ; separators like you define classes, structs and unions. If you could define an enum by defining an union with no non-zero members it'd solve this one and also give the existing sum type proposals a run for their money.

April 04

On Wednesday, 3 April 2024 at 17:57:31 UTC, Steven Schveighoffer wrote:

>

Something like:

enum ??? foo {
   case x;
   case y;
   case z;
   // constructors?
   this(int n) { this._value = cast(foo)n; }
   // operators?
   opBinary(...)
   // static if works at a declaration scope!
   static if(cond) {
     case a;
   }
}

The ??? is because I'm assuming it would be too ambiguous with existing syntax. Maybe enum struct?

But enums were basically copied from C (with duct-taped on features), and other modern languages (such as swift) have really considered how enums should be designed.

-Steve

How about inheritance?

enum A
{
  x,y,z,
}

static if(cond)
  enum B : A { w }
else
  alias B = A;
April 04

On Thursday, 4 April 2024 at 07:39:36 UTC, Daniel N wrote:

>

How about inheritance?

enum A
{
  x,y,z,
}

static if(cond)
  enum B : A { w }
else
  alias B = A;

Doesn't work the way you'd want it to in this case:

enum A
{
  x,y,z,
}

enum B : A { w }

pragma(msg, typeof(B.x)); // A
April 08

On Wednesday, 3 April 2024 at 17:57:31 UTC, Steven Schveighoffer wrote:

>

I think what might be in order is to elevate enums to a more structured type (like Swift does).

Something like:

enum ??? foo {
   case x;
   case y;
   case z;
   // constructors?
   this(int n) { this._value = cast(foo)n; }
   // operators?
   opBinary(...)
   // static if works at a declaration scope!
   static if(cond) {
     case a;
   }
}

The ??? is because I'm assuming it would be too ambiguous with existing syntax. Maybe enum struct?

But enums were basically copied from C (with duct-taped on features), and other modern languages (such as swift) have really considered how enums should be designed.

-Steve

Swift's enum is a tagged union. I'd love if we got tagged unions, and the enum struct syntax isn't bad either. If D tagged unions could functionally replace enums (i.e. if they could have an arbitrary number of empty cases) then this would be a fine replacement in my opinion. Sadly, no such feature exists yet.

April 25
On 4/2/24 00:00, Paul Backus wrote:
> On Saturday, 30 March 2024 at 14:57:00 UTC, IchorDev wrote:
>> The logical solution is to just allow conditional compilation statements inside enums:
>> ```d
>> enum A{
>>     x,y,z,
>>     static if(cond){
>>         w,
>>     }
>> }
>> ```
> 
> It's not very elegant, but you can do it with a string mixin:
> 
> ```d
> enum string enumMembers = "x, y, z, " ~ (cond ? "w, " : "");
> 
> mixin("enum A { " ~ enumMembers ~ " }");
> ```

A drawback of this approach is that the enum name is only visible after the mixin has been expanded, which can lead to forward reference issues.
October 11

Another use case I ran into was stuff like:

enum MouseButton: ubyte {
    static foreach(i; 1..9)
        mixin("mouse_"~i.stringof~",");
    mouse_left = mouse_1,
    mouse_right = mouse_2,
    mouse_middle = mouse_3;
}

Though it might make more sense specifically for conditional compilation like version(..).

October 15

On Saturday, 30 March 2024 at 14:57:00 UTC, IchorDev wrote:

>

To declare an enum type that may or may not have one or more members depending on conditional compilation statements requires duplicating the entire enum:

static if(cond){
	enum A{
		x,y,z,w,
	}
}else{
	enum A{
		x,y,z,
	}
}

For an enum type with many members—or many conditionals—this quickly becomes an insane amount of repetition.

The logical solution is to just allow conditional compilation statements inside enums:

enum A{
	x,y,z,
    static if(cond){
		w,
	}
}

I use a mixin generator for my types and I can switch between 2 columns (different languages)/names with a static if. For example:

struct ConsArray(Enum, size_t col)
{
  mixin(makeEnum!col);
  E[] list;
  size_t index;

  enum makeEnum(size_t mod) = () {
    size_t num;
    string str = "enum E {";
    static foreach(i, e; EnumMembers!Enum) {
      static if ((i & 1) ^ mod)
        str ~= e.format!"%s = %s,"(num++);
    }
    return str ~ "}";
  }();
//...
}

void main()
{
  enum Names
  { // mod 1, 0
        Andy, Ali,
       Cindy, Cengiz,
       Kenny, Kaan,
       Micky, Mehmet,
       Sunny, Salih
  }
  auto names = ConsArray!(Names, 1)();
  enum nameEn {Andy,Cindy,Kenny,Micky,Sunny}
}

If we wish, I could just give the enum directly with E without declaring a condition on my type. However this gives me error-free matching.

SDB@79

October 26

Indeed why not use manifest constants? Especially mouse buttons and address families are inherently extensible, because they are provided by OS. Variable enum may also force client code to be needlessly versioned to cope with members with conditional existence.