Defining a static array with values in a range
Meta via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Jan 22 11:33:28 PST 2015
On Thursday, 22 January 2015 at 19:13:46 UTC, Meta wrote:
> On Thursday, 22 January 2015 at 19:12:32 UTC, zeljkog wrote:
>> On 22.01.15 20:05, Meta wrote:
>>> On Thursday, 22 January 2015 at 19:00:47 UTC, zeljkog wrote:
>>>> On 22.01.15 19:26, Meta wrote:
>>>>> On Thursday, 22 January 2015 at 18:23:00 UTC, Meta wrote:
>>>>> Whoops, I forgot to make it a template to force CTFE.
>>>>>
>>>>
>>>> You can force CTFE assigning to manifest constant.
>>>>
>>>> enum t = charRange!...
>>>
>>> By wrapping it in a template the array will always be
>>> generated at
>>> compile time, even if you assign it to a runtime variable.
>>
>> Yes, but then you can not use runtime spec.
>
> OP wanted it to be done at compile time.
A small improvement to ensure the input consists of all ASCII
characters, and support for backward intervals.
import std.stdio;
template charRange(string spec)
{
static processSpec(string spec)
{
import std.algorithm;
import std.ascii;
import std.conv;
import std.range;
import std.string;
return spec.split(',').map!((s)
{
s = s.strip;
assert(s.all!(c => cast(ulong)c < 256),
"Expected all characters in 'spec' to be
ASCII");
auto start = cast(ubyte)s[1..$].front;
auto end = cast(ubyte)s[0..$-1].back;
return start <= end
? iota(start, end + 1)
.map!(c => cast(char)c).array
: iota(end, start + 1)
.retro
.map!(c => cast(char)c).array;
}).join;
}
enum charRange = processSpec(spec);
}
unittest
{
assert(charRange!q{ 'a'..'z', 'A'..'Z', '0'..'9' } ==
charRange!q{ '9'..'0', 'Z'..'A', 'z'..'a' }.reverse);
}
void main(string[] argv)
{
auto t1 = charRange!q{ 'a'..'z', 'A'..'Z', '0'..'9' };
writeln(t1);
auto t2 = charRange!q{ '9'..'0', 'Z'..'A', 'z'..'a' };
writeln(t2);
}
More information about the Digitalmars-d-learn
mailing list