Jump to page: 1 2
Thread overview
Making enum join variadic
May 01, 2014
Nordlöw
May 01, 2014
bearophile
May 02, 2014
Artur Skawina
May 02, 2014
Nordlöw
May 02, 2014
Nordlöw
May 02, 2014
Philippe Sigaud
May 02, 2014
Nordlöw
May 02, 2014
Nordlöw
May 02, 2014
Meta
May 02, 2014
Nordlöw
May 02, 2014
Nordlöw
May 02, 2014
Artur Skawina
May 02, 2014
Meta
May 02, 2014
Artur Skawina
May 02, 2014
Nordlöw
May 01, 2014
How can I make `join` variadic (by filling in njoin) in the following code?

import std.stdio: writeln;
import std.traits;

string enumsHelper(S...)(S s)
{
    typeof(return) r;
    foreach (i, e; s)
    {
        if (i >= 1)
            r ~= ", ";
        r ~= e;
    }
    return r;
}

/** Join/Chain/Concatenate/Unite Enums $(D E1), $(D E2), ... into $(D E).
    See also: http://forum.dlang.org/thread/f9vc6p$1b7k$1@digitalmars.com
*/
template join(string E, E1, E2)
{
    const join = ("enum " ~ E ~ " { " ~
                   enumsHelper(__traits(allMembers, E1)) ~ "," ~
                   enumsHelper(__traits(allMembers, E2)) ~ " }"
        );
}

template njoin(string E, Ei...)
{
    import std.algorithm: map;
    enum string njoin = "enum " ~ E ~ " { " ~ "" ~ " } ";
}

void main(string[] args)
{
    enum E1 { A, B, C }
    enum E2 { E, F, G }
    mixin(join!("E12", E1, E2));
    E12 e12;
    writeln(e12.min, ",", e12.max);
}
May 01, 2014
Nordlöw:

> How can I make `join` variadic (by filling in njoin) in the following code?

When you have a D tuple (not Phobos tuple), and it contains values all of the same type, you can turn it into an array with just:

[mytuple]

Once you have an array of strings, you can use the normal phobos function to join the strings as you desire.

Bye,
bearophile
May 02, 2014
On 05/02/14 00:24, "Nordlöw" via Digitalmars-d-learn wrote:
> How can I make `join` variadic (by filling in njoin) in the following code?

   import std.array, std.range, std.algorithm;
   import std.stdio;

   template Njoin(ES...) {
      mixin({
         string r = "enum Njoin { ";
         foreach (E; ES)
            r ~= [__traits(allMembers, E), " "].join(",");
         return r ~ "}";
      }());
   }

   void main(string[] args)
   {
       enum E1 { A, B, C }
       enum E2 { E, F, G }
       alias E12 = Njoin!(E1, E2);
       E12 e12;
       writeln(e12.min, ",", e12.max);
   }

artur
May 02, 2014
> artur

Thx!

Here's my final version that compiles and run:

import std.stdio: writeln;
import traits_ex: isEnum;
import std.typetuple: allSatisfy;

/** Join/Chain/Concatenate/Unite Enums $(D E1), $(D E2), ... into $(D E).
    See also: http://forum.dlang.org/thread/f9vc6p$1b7k$1@digitalmars.com
*/
template join(ES...) if (allSatisfy!(isEnum, ES)) {
    mixin({
            string r = "enum join { ";
            foreach (E; ES) {
                import std.range: join;
                r ~= [__traits(allMembers, E), " "].join(",");
            }
            return r ~ "}";
        }());
}

unittest
{
    enum E1 { a, b, c }
    enum E2 { e, f, g }
    enum E3 { h, i, j}
    alias E1_ = join!(E1);
    alias E12 = join!(E1, E2);
    alias E123 = join!(E1, E2, E3);
    writeln(E123.min, ",", E123.max);
}

Some final questions:

- Is join a good naming for this? Is chain better?
- Is it better to be verbose with joinEnums?
- What other useful enum algorithms are you missing?
- Should this perhaps go into Phobos? If so in what module? std.algorithm, range, traits?
May 02, 2014
Its up: https://github.com/nordlow/justd/blob/master/enums.d
May 02, 2014
On Fri, May 2, 2014 at 12:59 PM, "Nordlöw" <digitalmars-d-learn@puremagic.com> wrote:

> Some final questions:
>
> - Is join a good naming for this? Is chain better?
> - Is it better to be verbose with joinEnums?

I'd be verbose. It's an uncommon operation, bound to surprise a reader a bit.It's better to type a few more letters.

I did not try to compile it, but what happens if the enum elements have the same name ? The same min/max/values ?

Like this:

enum E1 { a, b, c }

alias E111 = join!(E1, E1, E1);



> - What other useful enum algorithms are you missing?
> - Should this perhaps go into Phobos? If so in what module? std.algorithm, range, traits?

I would put it in std.typecons, since it's a type constructor

May 02, 2014
> I'd be verbose. It's an uncommon operation, bound to surprise a reader
> a bit.It's better to type a few more letters.

See update.

> I did not try to compile it, but what happens if the enum elements
> have the same name ? The same min/max/values ?
>
> Like this:
>
> enum E1 { a, b, c }
>
> alias E111 = join!(E1, E1, E1);

This should give a better error message, than current mixin error.
I'll work on that.

> I would put it in std.typecons, since it's a type constructor

Ok.

Thx!
May 02, 2014
On Friday, 2 May 2014 at 12:45:44 UTC, Nordlöw wrote:
>> I'd be verbose. It's an uncommon operation, bound to surprise a reader
>> a bit.It's better to type a few more letters.
>
> See update.
>
>> I did not try to compile it, but what happens if the enum elements
>> have the same name ? The same min/max/values ?
>>
>> Like this:
>>
>> enum E1 { a, b, c }
>>
>> alias E111 = join!(E1, E1, E1);
>
> This should give a better error message, than current mixin error.
> I'll work on that.
>
>> I would put it in std.typecons, since it's a type constructor
>
> Ok.
>
> Thx!

Here's my try at detecting member names collision at compile time:

template MemberNamesUnion(E...) if (allSatisfy!(isEnum, E))
{
    bool[string] allMembers;   // used to detect member collisions
    mixin({
            string r = "enum MemberNamesUnion { ";
            foreach (T; E) {
                import std.range: join;
                foreach (member; __traits(allMembers, T)) {
                    static assert (member in allMembers, "Member collision");
                    allMembers[member] = true;
                }
                r ~= [__traits(allMembers, T)].join(",") ~ ",";
            }
            return r ~ " }";
        }());
}

It fails as

enums.d(25,46): Error: static variable allMembers cannot be read at compile time
enums.d(25,21):        while evaluating: static assert("a" in allMembers)

Is there a solution to this problem?
May 02, 2014
On Friday, 2 May 2014 at 13:38:39 UTC, Nordlöw wrote:
> enums.d(25,46): Error: static variable allMembers cannot be read at compile time
> enums.d(25,21):        while evaluating: static assert("a" in allMembers)
>
> Is there a solution to this problem?

Associative arrays are not CTFE-able.
May 02, 2014
On Friday, 2 May 2014 at 14:36:16 UTC, Meta wrote:
> On Friday, 2 May 2014 at 13:38:39 UTC, Nordlöw wrote:
>> enums.d(25,46): Error: static variable allMembers cannot be read at compile time
>> enums.d(25,21):        while evaluating: static assert("a" in allMembers)
>>
>> Is there a solution to this problem?
>
> Associative arrays are not CTFE-able.

So that leaves me with using an array of bool and rank() then, I guess...
« First   ‹ Prev
1 2