April 15, 2019
On Monday, 15 April 2019 at 12:25:38 UTC, XavierAP wrote:
> On Monday, 15 April 2019 at 10:34:42 UTC, Anton Fediushin wrote:
>> On Monday, 15 April 2019 at 10:06:30 UTC, XavierAP wrote:
>>> [snip]
>>
>> Isn't this how subtyping works for integers and other types? For example, you have subtyped an integer and added some new methods to it?
>
> Yes (leaving aside whether stuff is private or nested) but you are using the types' relationship the other way around. You have:
>
> static assert(is(Enum : internal));
>
> But you are defining and calling fun() as if it were the other way around (internal : Enum)

Thank you, I understand now! I think I'd have to stick with UFCS method
April 15, 2019
On Monday, 15 April 2019 at 13:38:33 UTC, Anton Fediushin wrote:
>
> This does work unless I want to use it like this:
> ```
> fun(Enum.foo);
> ---
> Error: function fun(Enum e) is not callable using argument types (internal)
> cannot pass argument foo of type internal to parameter Enum e
> ```

This is correct. And you enforced this behavior as you said

> Enum.internal is private to make it inaccessible from any other place. All I want is a way to have > an enum that I could extend with my own methods.

So... either you pass the internals of Enum somewhere, or you don't...
April 15, 2019
Le 15/04/2019 à 10:39, Anton Fediushin via Digitalmars-d-learn a écrit :
> This seems to work just fine for assigning and comparisons but passing Enum as a function argument does not work:
> ```
> void fun(Enum e) {}
> 
> fun(Enum.foo);
> ---
> Error: function fun(Enum e) is not callable using argument types (internal)
> Cannot pass argument foo of type internal to parameter Enum e.
> ```

I don't understand why you just don't call fun with an Enum (struct) param, since that is how fun is defined. This works by me (see call in main):

struct Enum {
  private {
    enum internal {
      foo,
      bar
    }
    internal m_enum;
  }
  this (internal i) { m_enum = i; }
  alias m_enum this;
  string toString() {
    switch (this.m_enum) {
        case internal.foo : return "FOO" ;
        case internal.bar : return "BAR" ;
        default : assert(0) ;
    }
  }
}

void fun (Enum e) {
    writeln(e) ;
}

void main() {
    auto e = Enum(Enum.foo) ;
    fun(e) ;	// -> "FOO"
}

[And I wouldn't make the enum (little e) private, this just risks complicating code, also eg in testing, I would just not export it.]

-- 
diniz {la vita e estranj}
April 15, 2019
On Monday, 15 April 2019 at 08:39:24 UTC, Anton Fediushin wrote:
> Hello! I am currently trying to add a custom `toString` method to an enum so that:
> 1. Enum members would still have numeric values and can be easily compared (things like `enum a { foo = "FOO", bar = "BAR”}` won't do, I want `a.foo < a.bar)`)
> 2. More custom methods can be implemented in the future
>
> Obvious solution is to wrap an enum in a structure and utilize 'alias this' for subtyping like this:
> ```
> struct Enum {
>   private {
>     enum internal {
>       foo,
>       bar
>     }
>     internal m_enum;
>   }
>   this(internal i) { m_enum = i; }
>   alias m_enum this;
>   string toString() {
>     // custom implementation of toString
>   }
> }
> ```
>
> This seems to work just fine for assigning and comparisons but passing Enum as a function argument does not work:
> ```
> void fun(Enum e) {}
>
> fun(Enum.foo);
> ---
> Error: function fun(Enum e) is not callable using argument types (internal)
> Cannot pass argument foo of type internal to parameter Enum e.
> ```
>
> Of course, I could just define a bunch of functions that accept my enum as the first argument and call them using UFCS but it'd require to explicitly specify functions instead of D taking care of that (toString() for structures is called automagically by functions like writeln) and those functions would hang around here and there totally unorganized. I prefer to keep functions inside of structures and classes.
>
> If there are other ways of achieving the same *and* keeping code clean and organized, please share.
>
> Thank you in advance,
> Anton.

yes,

import std.stdio, std.meta, std.traits, std.conv;

enum _MyEnum : int { a,b,c}

struct _Enum(T)
{
   T value;
   alias value this;
   // generate static field members
   static foreach(e, v; EnumMembers!T)
   {
     pragma(msg, "static MyEnum "~to!string(v)~" = MyEnum(T."~to!string(v)~");");
     mixin("static MyEnum "~to!string(v)~" = cast(MyEnum)(T."~to!string(v)~");");
   }
}

alias _Enum!_MyEnum MyEnum;

void foo(MyEnum e)
{
   writeln(to!int(e));
}
void main()
{
    foo(MyEnum.a);
    foo(MyEnum.b);
    foo(MyEnum.c);
}

https://run.dlang.io/is/WOcLrZ

Note that value is never used, it just makes the cast work and treats the struct as an enum. Not sure if there is a way around that.





April 15, 2019
On Monday, 15 April 2019 at 08:39:24 UTC, Anton Fediushin wrote:
> Hello! I am currently trying to add a custom `toString` method to an enum so that:
> 1. Enum members would still have numeric values and can be easily compared (things like `enum a { foo = "FOO", bar = "BAR”}` won't do, I want `a.foo < a.bar)`)
> 2. More custom methods can be implemented in the future
>
> Obvious solution is to wrap an enum in a structure and utilize 'alias this' for subtyping like this:
> ```
> struct Enum {
>   private {
>     enum internal {
>       foo,
>       bar
>     }
>     internal m_enum;
>   }
>   this(internal i) { m_enum = i; }
>   alias m_enum this;
>   string toString() {
>     // custom implementation of toString
>   }
> }
> ```
>
> This seems to work just fine for assigning and comparisons but passing Enum as a function argument does not work:
> ```
> void fun(Enum e) {}
>
> fun(Enum.foo);
> ---
> Error: function fun(Enum e) is not callable using argument types (internal)
> Cannot pass argument foo of type internal to parameter Enum e.
> ```
>
> Of course, I could just define a bunch of functions that accept my enum as the first argument and call them using UFCS but it'd require to explicitly specify functions instead of D taking care of that (toString() for structures is called automagically by functions like writeln) and those functions would hang around here and there totally unorganized. I prefer to keep functions inside of structures and classes.
>
> If there are other ways of achieving the same *and* keeping code clean and organized, please share.
>
> Thank you in advance,
> Anton.


Should have been

struct _Enum(T)
{
	T value;
	alias value this;
	static foreach(e, v; EnumMembers!T)
		mixin("static T "~to!string(v)~" = cast(_Enum)(T."~to!string(v)~");");
}

April 15, 2019
On Monday, 15 April 2019 at 14:11:05 UTC, diniz wrote:
> Le 15/04/2019 à 10:39, Anton Fediushin via Digitalmars-d-learn a écrit :
>> [snip]
>
> I don't understand why you just don't call fun with an Enum (struct) param, since that is how fun is defined. This works by me (see call in main):
>
> struct Enum {
>   private {
>     enum internal {
>       foo,
>       bar
>     }
>     internal m_enum;
>   }
>   this (internal i) { m_enum = i; }
>   alias m_enum this;
>   string toString() {
>     switch (this.m_enum) {
>         case internal.foo : return "FOO" ;
>         case internal.bar : return "BAR" ;
>         default : assert(0) ;
>     }
>   }
> }
>
> void fun (Enum e) {
>     writeln(e) ;
> }
>
> void main() {
>     auto e = Enum(Enum.foo) ;
>     fun(e) ;	// -> "FOO"
> }
>
> [And I wouldn't make the enum (little e) private, this just risks complicating code, also eg in testing, I would just not export it.]

`fun(Enum(Enum.foo));` would obviously work but `fun(Enum.foo);` would not. `Enum(Enum` is just redundant, I was looking for a solution that would make code cleaner.

I don't see a problem marking internal enum as private because it isn't accessed outside of the struct

April 15, 2019
On Monday, 15 April 2019 at 14:20:57 UTC, Alex wrote:
> On Monday, 15 April 2019 at 08:39:24 UTC, Anton Fediushin wrote:
>> Hello! I am currently trying to add a custom `toString` method to an enum so that:
>> 1. Enum members would still have numeric values and can be easily compared (things like `enum a { foo = "FOO", bar = "BAR”}` won't do, I want `a.foo < a.bar)`)
>> 2. More custom methods can be implemented in the future
>>
>> Obvious solution is to wrap an enum in a structure and utilize 'alias this' for subtyping like this:
>> ```
>> struct Enum {
>>   private {
>>     enum internal {
>>       foo,
>>       bar
>>     }
>>     internal m_enum;
>>   }
>>   this(internal i) { m_enum = i; }
>>   alias m_enum this;
>>   string toString() {
>>     // custom implementation of toString
>>   }
>> }
>> ```
>>
>> This seems to work just fine for assigning and comparisons but passing Enum as a function argument does not work:
>> ```
>> void fun(Enum e) {}
>>
>> fun(Enum.foo);
>> ---
>> Error: function fun(Enum e) is not callable using argument types (internal)
>> Cannot pass argument foo of type internal to parameter Enum e.
>> ```
>>
>> Of course, I could just define a bunch of functions that accept my enum as the first argument and call them using UFCS but it'd require to explicitly specify functions instead of D taking care of that (toString() for structures is called automagically by functions like writeln) and those functions would hang around here and there totally unorganized. I prefer to keep functions inside of structures and classes.
>>
>> If there are other ways of achieving the same *and* keeping code clean and organized, please share.
>>
>> Thank you in advance,
>> Anton.
>
> yes,
>
> import std.stdio, std.meta, std.traits, std.conv;
>
> enum _MyEnum : int { a,b,c}
>
> struct _Enum(T)
> {
>    T value;
>    alias value this;
>    // generate static field members
>    static foreach(e, v; EnumMembers!T)
>    {
>      pragma(msg, "static MyEnum "~to!string(v)~" = MyEnum(T."~to!string(v)~");");
>      mixin("static MyEnum "~to!string(v)~" = cast(MyEnum)(T."~to!string(v)~");");
>    }
> }
>
> alias _Enum!_MyEnum MyEnum;
>
> void foo(MyEnum e)
> {
>    writeln(to!int(e));
> }
> void main()
> {
>     foo(MyEnum.a);
>     foo(MyEnum.b);
>     foo(MyEnum.c);
> }
>
> https://run.dlang.io/is/WOcLrZ
>
> Note that value is never used, it just makes the cast work and treats the struct as an enum. Not sure if there is a way around that.

Thank you, this is the solution I have been looking for!
April 15, 2019
On Monday, 15 April 2019 at 20:36:09 UTC, Anton Fediushin wrote:
> On Monday, 15 April 2019 at 14:20:57 UTC, Alex wrote:
>> On Monday, 15 April 2019 at 08:39:24 UTC, Anton Fediushin wrote:
>>> Hello! I am currently trying to add a custom `toString` method to an enum so that:
>>> 1. Enum members would still have numeric values and can be easily compared (things like `enum a { foo = "FOO", bar = "BAR”}` won't do, I want `a.foo < a.bar)`)
>>> 2. More custom methods can be implemented in the future
>>>
>>> Obvious solution is to wrap an enum in a structure and utilize 'alias this' for subtyping like this:
>>> ```
>>> struct Enum {
>>>   private {
>>>     enum internal {
>>>       foo,
>>>       bar
>>>     }
>>>     internal m_enum;
>>>   }
>>>   this(internal i) { m_enum = i; }
>>>   alias m_enum this;
>>>   string toString() {
>>>     // custom implementation of toString
>>>   }
>>> }
>>> ```
>>>
>>> This seems to work just fine for assigning and comparisons but passing Enum as a function argument does not work:
>>> ```
>>> void fun(Enum e) {}
>>>
>>> fun(Enum.foo);
>>> ---
>>> Error: function fun(Enum e) is not callable using argument types (internal)
>>> Cannot pass argument foo of type internal to parameter Enum e.
>>> ```
>>>
>>> Of course, I could just define a bunch of functions that accept my enum as the first argument and call them using UFCS but it'd require to explicitly specify functions instead of D taking care of that (toString() for structures is called automagically by functions like writeln) and those functions would hang around here and there totally unorganized. I prefer to keep functions inside of structures and classes.
>>>
>>> If there are other ways of achieving the same *and* keeping code clean and organized, please share.
>>>
>>> Thank you in advance,
>>> Anton.
>>
>> yes,
>>
>> import std.stdio, std.meta, std.traits, std.conv;
>>
>> enum _MyEnum : int { a,b,c}
>>
>> struct _Enum(T)
>> {
>>    T value;
>>    alias value this;
>>    // generate static field members
>>    static foreach(e, v; EnumMembers!T)
>>    {
>>      pragma(msg, "static MyEnum "~to!string(v)~" = MyEnum(T."~to!string(v)~");");
>>      mixin("static MyEnum "~to!string(v)~" = cast(MyEnum)(T."~to!string(v)~");");
>>    }
>> }
>>
>> alias _Enum!_MyEnum MyEnum;
>>
>> void foo(MyEnum e)
>> {
>>    writeln(to!int(e));
>> }
>> void main()
>> {
>>     foo(MyEnum.a);
>>     foo(MyEnum.b);
>>     foo(MyEnum.c);
>> }
>>
>> https://run.dlang.io/is/WOcLrZ
>>
>> Note that value is never used, it just makes the cast work and treats the struct as an enum. Not sure if there is a way around that.
>
> Thank you, this is the solution I have been looking for!

Yes, it is quite nice. D should simply allow enums to act as structs, they are effectively the same.[meaning they should should allow methods having methods]

You might want to add a little more functionality. I screwed up the code when generalizing it, here is a bit better version:

https://run.dlang.io/is/yyuy77

Using the struct you can leverage all the power of op's such as dispatching, assignment, etc.

Essentially one is just using a standard struct but using enum's to define the names and values(since they are auto filled).

D should just do away with enums and allow one to create a enum struct, e.g.,

struct S
{
    enum : int
    {
       a,b,c
    }
}

Of which enum S : int { a,b,c } is short hand when one does not want to add new functionality or D could just treat enum like a struct by allowing methods inside the enum.

The code I created essentially emulates this, one can make the enum internal and private to hide it.
1 2
Next ›   Last »