June 30, 2022

On Thursday, 30 June 2022 at 11:03:08 UTC, bauss wrote:

>

On Thursday, 30 June 2022 at 10:58:37 UTC, Mike Parker wrote:

>

On Thursday, 30 June 2022 at 10:51:31 UTC, ryuukk_ wrote:

> >

auto color = orange;
// What is color?

same, it's not .orange therefore it's 1, if it where with the dot, it's compile error telling you to be more explicit

>

auto color = cast(int)orange;
// What is color?

it's not .orange therefore it is your variable, it if were with the dot, it'd take what ever is in the enum, then apply the cast

I don't know it seems pretty obvious to me

This feature is too good to not have

My problem with this is it is not obvious at all to me. When I see .foo, I immediately think "foo is in the parent scope", as that what is what it means right now in D. If we're suddenly seeing .foo at module scope, now I've got a fault in my wiring; .foo suddenly has different meanings depending on the scope in which it's used.

I mean, maybe I could get used to it if I used it. But I don't see myself using it at all.

Not saying I'm against the feature, I just don't understand why auto color = Color.orange is a problem and how Color color = .orange is better. Because of four fewer characters?

What it seems like it's trying to solve is this:

SomeEnum.a | SomeEnum.b | SomeEnum.c

So you could instead do:

.a | .b | .c

But much like you I don't think that's at all clarified, maybe I would settle for something like this:

SomeEnum(a | b | c) as that clearly tells you it's SomeEnum and then it's clear you're picking the values from that, so a, b and c will always be from SomeEnum.

But personally I don't really like that syntax either as it clashes too much with struct ctors and/or function calls.

So I don't have an actual good solution, so I guess in the end I'm not for any changes.

SomeEnum flags = SomeEnum (a | b | c);

Why do i have to be repetitive? the goal is to not be repetitive and be cleaner

SomeEnum flags = .a | .b | .c;

The brain no longer have to read 2x the same stuff, it goes straight to the point, it is explicit and typechecked

June 30, 2022

On Thursday, 30 June 2022 at 15:42:05 UTC, ryuukk_ wrote:

>

On Thursday, 30 June 2022 at 11:03:08 UTC, bauss wrote:

>

On Thursday, 30 June 2022 at 10:58:37 UTC, Mike Parker wrote:

>

[...]

What it seems like it's trying to solve is this:

SomeEnum.a | SomeEnum.b | SomeEnum.c

So you could instead do:

.a | .b | .c

But much like you I don't think that's at all clarified, maybe I would settle for something like this:

SomeEnum(a | b | c) as that clearly tells you it's SomeEnum and then it's clear you're picking the values from that, so a, b and c will always be from SomeEnum.

But personally I don't really like that syntax either as it clashes too much with struct ctors and/or function calls.

So I don't have an actual good solution, so I guess in the end I'm not for any changes.

SomeEnum flags = SomeEnum (a | b | c);

Why do i have to be repetitive? the goal is to not be repetitive and be cleaner

SomeEnum flags = .a | .b | .c;

The brain no longer have to read 2x the same stuff, it goes straight to the point, it is explicit and typechecked

and if you later see a line like

auto flags = .a | .b | .c;

imho it's just much harder to figure out whats going on.
i agree that a short syntax would be good. i'd prefer with() because it makes it easier to understand later.

June 30, 2022

On Thursday, 30 June 2022 at 11:32:42 UTC, ryuukk_ wrote:

>
set_my_flag( MySuperLongName.MyFlagA |  MySuperLongName.MyFlagB | MySuperLongName.MyFlagC | MySuperLongName.MyFlagD | MySuperLongName.MyFlagE | MySuperLongName.MyFlagF );

vs

set_my_flag( .MyFlagA |  .MyFlagB | .MyFlagC | .MyFlagD | .MyFlagE | .MyFlagF );

One could argue to use with

But what about places where it can't be used? and it is counter productive, if the goal is to remove repetition, why introduce more?

Where do you want to use it where it cannot be used?

This works today:

    with(Color)
    final switch(color) {
        case red: writeln("red"); break;
    	case orange: writeln("orange");
    }
    with(MySuperLongName) set_my_flag( MyFlagA |  MyFlagB | MyFlagC | MyFlagD | MyFlagE | MyFlagF);

More clear at the cost of a few more characters to type. Quite acceptable compromise in my view.

June 30, 2022

On Thursday, 30 June 2022 at 17:15:46 UTC, ShadoLight wrote:

>

On Thursday, 30 June 2022 at 11:32:42 UTC, ryuukk_ wrote:

>
set_my_flag( MySuperLongName.MyFlagA |  MySuperLongName.MyFlagB | MySuperLongName.MyFlagC | MySuperLongName.MyFlagD | MySuperLongName.MyFlagE | MySuperLongName.MyFlagF );

vs

set_my_flag( .MyFlagA |  .MyFlagB | .MyFlagC | .MyFlagD | .MyFlagE | .MyFlagF );

One could argue to use with

But what about places where it can't be used? and it is counter productive, if the goal is to remove repetition, why introduce more?

Where do you want to use it where it cannot be used?

This works today:

    with(Color)
    final switch(color) {
        case red: writeln("red"); break;
    	case orange: writeln("orange");
    }
    with(MySuperLongName) set_my_flag( MyFlagA |  MyFlagB | MyFlagC | MyFlagD | MyFlagE | MyFlagF);

More clear at the cost of a few more characters to type. Quite acceptable compromise in my view.

Now it is harder to see the function, 'with' is nice when you need to pull in a symbol into a scope

It is not nice when you just want to call a function with your enum

Other languages who have it didn't go with a 'with' for a reason, it adds unecessary noise

You don't do:

with(int) set_my_int(5 + 6 + 7 + 8 + 9 +10);

It kills the intent to make things simpler and logical, functions expect Enum, we give its value

Function expect int? we give a value

June 30, 2022

On Thursday, 30 June 2022 at 16:25:35 UTC, The Zealot wrote:

>

On Thursday, 30 June 2022 at 15:42:05 UTC, ryuukk_ wrote:

>

On Thursday, 30 June 2022 at 11:03:08 UTC, bauss wrote:

>

On Thursday, 30 June 2022 at 10:58:37 UTC, Mike Parker wrote:

>

[...]

What it seems like it's trying to solve is this:

SomeEnum.a | SomeEnum.b | SomeEnum.c

So you could instead do:

.a | .b | .c

But much like you I don't think that's at all clarified, maybe I would settle for something like this:

SomeEnum(a | b | c) as that clearly tells you it's SomeEnum and then it's clear you're picking the values from that, so a, b and c will always be from SomeEnum.

But personally I don't really like that syntax either as it clashes too much with struct ctors and/or function calls.

So I don't have an actual good solution, so I guess in the end I'm not for any changes.

SomeEnum flags = SomeEnum (a | b | c);

Why do i have to be repetitive? the goal is to not be repetitive and be cleaner

SomeEnum flags = .a | .b | .c;

The brain no longer have to read 2x the same stuff, it goes straight to the point, it is explicit and typechecked

and if you later see a line like

auto flags = .a | .b | .c;

imho it's just much harder to figure out whats going on.
i agree that a short syntax would be good. i'd prefer with() because it makes it easier to understand later.

I already explained in earlier replies

If you use auto, how can the compiler expect you to use an enum called MyEnum? it doesn't make sense, for that case, it falls back to the current behavior, it searches for the parent scope

If no variable found, then it is compile error, undefined symbols a, b, c

June 30, 2022
On 6/30/2022 2:08 AM, Ogi wrote:
> I was under impression that this is a deliberate (although questionable) design to avoid some bugs rather some technical limitation.

It is deliberate, not a bug. The rationale is the common C practice:

  enum XX { XXabc, XXdef, XXghi };

where the programmer is using a workaround for a scoped name.
June 30, 2022
On 6/30/2022 2:19 AM, bauss wrote:
> I don't think D could ever settle on a single rule here that a majority would agree upon.

C++ threw in the towel and added scoped enums with a somewhat different syntax. Now C++ has two different kinds of enums.

Having too many choices is not good language design.
June 30, 2022
On 6/30/2022 8:41 AM, ryuukk_ wrote:
>      Color color = .orange; <--- it obviously pick orange, it already expect an enum

That is top-down type inference. D is designed to be bottom-up type inference. Because of overloading, having both top-down and bottom-up in play would be very confusing and likely a rich source of confusing bugs. People find overloading confusing enough already.
July 01, 2022

On Thursday, 30 June 2022 at 20:32:49 UTC, ryuukk_ wrote:

>

You don't do:

with(int) set_my_int(5 + 6 + 7 + 8 + 9 +10);

It's funny that in fact I like this really. It's much more readable than casting to the desired type. E.g. you might have wished every literal to be float:

with(float) foo(5 + 6 + 7 + 8 + 9 + 10);

Unfortunately that doesn't work, so we have to live with

foo(cast(float)5 + 6 + 7 + 8 + 9 + 10);

or

foo(5.0f + 6 + 7 + 8 + 9 + 10);

which looks short, but you don't know if the compiler will use float or double or real because of the strange propagation rules.

or cast every literal:

foo(5.0f + 6.0f + 7.0f + 8.0f + 9.0f + 10.0f);

Much worse if you want byte:

foo(cast(byte)5 + 6 + 7 + 8 + 250);

calls foo with int :-(
Here even casting each literal doesn't work, you have to cast the result. I really wish

with(byte) foo(5 + 6 + 7 + 8 + 9 + 10);

would work.

July 01, 2022

On Friday, 1 July 2022 at 04:53:01 UTC, Walter Bright wrote:

>

On 6/30/2022 2:19 AM, bauss wrote:

>

I don't think D could ever settle on a single rule here that a majority would agree upon.

C++ threw in the towel and added scoped enums with a somewhat different syntax. Now C++ has two different kinds of enums.

Having too many choices is not good language design.

C and D don't have an enumeration type. enum class gave C++ a somewhat type safe enumeration type. It is very useful.