How to enumerate a sequence?

Simen Kjærås simen.kjaras at gmail.com
Wed Feb 27 13:38:55 UTC 2019


On Wednesday, 27 February 2019 at 13:15:06 UTC, Victor Porton 
wrote:
> .enumerate does not work for compile-time sequences. Consider 
> for the sake of discussion the following nonsense (I know it 
> cannot be done without enumerate) code:
>
> import std.meta;
> import std.range;
>
> string join(Fields...)() {
>   enum f(size_t i) = __traits(identifier, Fields[i]);
>   return staticMap!f(Fields.enumerate).join('\n'); // does not 
> compile because of .enumerate
> }
>
> void main(string[] args)
> {
>     string r = join!(int, float)();
> }
>
> How to make it compile?

Sadly, we cannot treat all compile-time values the same way we do 
run-time values. In this case, that's evident with Fields being 
an AliasSeq, not an array or other range. Since enumerate and 
join operate on ranges, they get confused when you give them an 
AliasSeq.

You also are probably not giving enough information about what 
you're actually trying to do. First, __traits(identifier, 
Fields[0]) simply fails to compile with the given arguments, 
since int doesn't have an identifier. Second, it's very unclear 
why you need an int index, since you're not using it in a way you 
couldn't easier do without. Here's how I would implement your 
join function wihout any further knowledge of these questions:

// Moved outside join due to the thrice-damned issue 5710
enum getIdentifier(T...) = __traits(identifier, T[0]);
string join(Fields...)() {
     import std.range : join;
     import std.meta : staticMap;

     alias names = staticMap!(getIdentifier, Fields);
     return [names].join('\n');
}

However, since you seem adamant you need the index as an int or 
size_t:

string join(Fields...)() {
     import std.range : join, iota;
     import std.meta : staticMap, aliasSeqOf;

     enum getIdentifier(size_t i) = __traits(identifier, 
Fields[i]);

     alias numbers = aliasSeqOf!(Fields.length.iota);
     return [staticMap!(getIdentifier, numbers)].join('\n');
}

Also, fixed the calling code so it has actual identifiers:

void main(string[] args)
{
     int i;
     float f;
     string r = join!(i, f)();
}

--
   Simen


More information about the Digitalmars-d-learn mailing list