Thread overview
Concat enum of strings into one string
Aug 14, 2018
Andrey
Aug 14, 2018
Mike Franklin
Aug 14, 2018
Andrey
Aug 14, 2018
Timoses
Aug 14, 2018
Andrey
Aug 14, 2018
Timoses
Aug 14, 2018
vit
Aug 15, 2018
Andrey
Aug 14, 2018
Jonathan M Davis
August 14, 2018
Hello,
I have a enum:

enum Type : string
{
    One = "Q1",
    Two = "W2",
    Three = "R3"
}

I want to concat it in compile-time:

enum result = doConcat!Type();

And get this result:

writeln(result); // output: "Q1 W2 R3"

Delimiter here is space symbol.
How do do it?
August 14, 2018
On Tuesday, 14 August 2018 at 13:42:04 UTC, Andrey wrote:
> Hello,
> I have a enum:
>
> enum Type : string
> {
>     One = "Q1",
>     Two = "W2",
>     Three = "R3"
> }
>
> I want to concat it in compile-time:
>
> enum result = doConcat!Type();
>
> And get this result:
>
> writeln(result); // output: "Q1 W2 R3"
>
> Delimiter here is space symbol.
> How do do it?

I think you just need to use the concatenation operator `~`.

enum Type : string
{
    One = "Q1",
    Two = "W2",
    Three = "R3"
}

enum concatenation = Type.One ~ " " ~ Type.Two ~ " " ~ Type.Three;

void main()
{
    import std.stdio: writeln;
    writeln(concatenation);
}

Mike
August 14, 2018
On Tuesday, 14 August 2018 at 13:45:48 UTC, Mike Franklin wrote:
> I think you just need to use the concatenation operator `~`.
>
> enum Type : string
> {
>     One = "Q1",
>     Two = "W2",
>     Three = "R3"
> }
>
> enum concatenation = Type.One ~ " " ~ Type.Two ~ " " ~ Type.Three;
>
> void main()
> {
>     import std.stdio: writeln;
>     writeln(concatenation);
> }
>
> Mike

Hmm, and to do it automatically, not manually?
August 14, 2018
On Tuesday, 14 August 2018 at 13:42:04 UTC, Andrey wrote:
> Hello,
> I have a enum:
>
> enum Type : string
> {
>     One = "Q1",
>     Two = "W2",
>     Three = "R3"
> }
>
> I want to concat it in compile-time:
>
> enum result = doConcat!Type();
>
> And get this result:
>
> writeln(result); // output: "Q1 W2 R3"
>
> Delimiter here is space symbol.
> How do do it?

Here's one version:

template StringEnumValues(alias Enum)
{
    import std.traits : EnumMembers;
    string[] StringEnumValues()
    {
        string[] enumValues;
     	static foreach (member; EnumMembers!Enum)
            enumValues ~= member;
        return enumValues;
    }
}

import std.string : join;
pragma(msg, StringEnumValues!Type.join(" "));
August 14, 2018
On Tuesday, 14 August 2018 at 14:07:23 UTC, Timoses wrote:
> Here's one version:
>
> template StringEnumValues(alias Enum)
> {
>     import std.traits : EnumMembers;
>     string[] StringEnumValues()
>     {
>         string[] enumValues;
>      	static foreach (member; EnumMembers!Enum)
>             enumValues ~= member;
>         return enumValues;
>     }
> }
>
> import std.string : join;
> pragma(msg, StringEnumValues!Type.join(" "));

Thank you. Hmm, I thought that standard library already has this stuff.
August 14, 2018
On Tuesday, 14 August 2018 at 14:37:33 UTC, Andrey wrote:
> Thank you. Hmm, I thought that standard library already has this stuff.

There might be more elegant solutions and I'd be happy to see some more. I'm always just digging into std.traits [1] and Traits spec part [2] and try to fumble things together somehow until I get what I want. It's good practice (as in training/accustomization, not as in method...), but perhaps also a sign that there's an area for improvement.

[1] https://dlang.org/phobos/std_traits.html
[2] https://dlang.org/spec/traits.html
August 14, 2018
On Tuesday, 14 August 2018 at 14:37:33 UTC, Andrey wrote:
> On Tuesday, 14 August 2018 at 14:07:23 UTC, Timoses wrote:
>> Here's one version:
>>
>> template StringEnumValues(alias Enum)
>> {
>>     import std.traits : EnumMembers;
>>     string[] StringEnumValues()
>>     {
>>         string[] enumValues;
>>      	static foreach (member; EnumMembers!Enum)
>>             enumValues ~= member;
>>         return enumValues;
>>     }
>> }
>>
>> import std.string : join;
>> pragma(msg, StringEnumValues!Type.join(" "));
>
> Thank you. Hmm, I thought that standard library already has this stuff.


import std.traits : EnumMembers;
import std.string : join;
import std.algorithm : map;

pragma(msg, [EnumMembers!Type].map!(x => cast(string)x).join(" "));
August 14, 2018
On Tuesday, August 14, 2018 8:37:33 AM MDT Andrey via Digitalmars-d-learn wrote:
> On Tuesday, 14 August 2018 at 14:07:23 UTC, Timoses wrote:
> > Here's one version:
> >
> > template StringEnumValues(alias Enum)
> > {
> >
> >     import std.traits : EnumMembers;
> >     string[] StringEnumValues()
> >     {
> >
> >         string[] enumValues;
> >
> >         static foreach (member; EnumMembers!Enum)
> >
> >             enumValues ~= member;
> >
> >         return enumValues;
> >
> >     }
> >
> > }
> >
> > import std.string : join;
> > pragma(msg, StringEnumValues!Type.join(" "));
>
> Thank you. Hmm, I thought that standard library already has this stuff.

Phobos isn't generally going to have super-specific stuff like a function for taking an enum type and giving you a string containing the names of all of its members separated by a single space. Rather, it has building blocks for doing stuff like that. EnumMembers is one of those building blocks, and as vit showed in his post, its possible to use map instead of a loop like is done here. So, getting compact code is often a question of figuring out which building blocks get you what you want. But it's frequently the case that you need several traits, functions, and/or templates to get where you want to go. For metaprogramming, std.traits and std.meta are the main places to look, whereas for operating on runtime values (or using CTFE instead of template metaprogramming), std.range and std.algorithm are the main places to look, though depending on what you're doing, pretty much anywhere in Phobos could be useful. It's just that std.range and std.algorithm are where the most generic stuff is (as opposed to something like std.string which is specific to strings or std.file which has file-specific operations).

At first, you're likely to end up with code that looks more like what Timoses suggested, and over time, it will become easier to come up with solutions closer to what vit suggested, and it probably won't be uncommon to start off with a more verbose solution and then end up with a more compact one later when you figure out how a particular piece of Phobos can be used to solve the problem in less space. But there's enough in Phobos (even std.algorithm alone) that it's not all that hard to not realize that something that's perfect for your problem is in there. It is usually a building block towards the solution though rather than a function that does exactly what you want at the high level.

- Jonathan M Davis



August 15, 2018
On Tuesday, 14 August 2018 at 16:03:05 UTC, vit wrote:
> import std.traits : EnumMembers;
> import std.string : join;
> import std.algorithm : map;
>
> pragma(msg, [EnumMembers!Type].map!(x => cast(string)x).join(" "));

Thank you!

Jonathan M Davis, I understood.