www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Concat enum of strings into one string

reply Andrey <saasecondbox yandex.ru> writes:
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?
Aug 14 2018
next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
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
Aug 14 2018
parent Andrey <saasecondbox yandex.ru> writes:
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?
Aug 14 2018
prev sibling parent reply Timoses <timosesu gmail.com> writes:
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(" "));
Aug 14 2018
parent reply Andrey <saasecondbox yandex.ru> writes:
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.
Aug 14 2018
next sibling parent Timoses <timosesu gmail.com> writes:
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
Aug 14 2018
prev sibling next sibling parent reply vit <vit vit.vit> writes:
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(" "));
Aug 14 2018
parent Andrey <saasecondbox yandex.ru> writes:
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.
Aug 15 2018
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Aug 14 2018