January 22, 2015
On Thursday, January 22, 2015 15:16:07 bearophile via Digitalmars-d-learn wrote:
> Jonathan M Davis:
>
> > but that's easy fixed with some +1's.
>
> But the +1 changes the char to an int.

True, though iota doesn't seem to like to operate on char anyway, so from the little playing around with it I did to answer the OP, it looks like you're forced to use casts for it anyway. And depending, you probably want to cast to ubyte and then convert that to char when you convert the range to an array to avoid the conversion to dchar anyway. So, all around, trying to use iota with char is a bit awkward.

- Jonathan M Davis

January 22, 2015
On Thursday, 22 January 2015 at 17:15:34 UTC, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Thursday, January 22, 2015 15:16:07 bearophile via Digitalmars-d-learn wrote:
>> Jonathan M Davis:
>>
>> > but that's easy fixed with some +1's.
>>
>> But the +1 changes the char to an int.
>
> True, though iota doesn't seem to like to operate on char anyway, so from
> the little playing around with it I did to answer the OP, it looks like
> you're forced to use casts for it anyway. And depending, you probably want
> to cast to ubyte and then convert that to char when you convert the range to
> an array to avoid the conversion to dchar anyway. So, all around, trying to
> use iota with char is a bit awkward.
>
> - Jonathan M Davis

So, at the end of the day (I left working on my Matcher class in the morning waiting an answer for this question), there is nothing to convert ['a'..'d', '0'..'3'] to ['a', 'b', 'c', 'd', '0', '1', '2', '3'] at compile time automatically.
January 22, 2015
tcak:

> So, at the end of the day (I left working on my Matcher class in the morning waiting an answer for this question), there is nothing to convert ['a'..'d', '0'..'3'] to ['a', 'b', 'c', 'd', '0', '1', '2', '3'] at compile time automatically.

Right. The 'a'..'d' is not first class, and you can't invent new syntax.

Bye,
bearophile
January 22, 2015
On Thursday, 22 January 2015 at 17:45:59 UTC, tcak wrote:
> So, at the end of the day (I left working on my Matcher class in the morning waiting an answer for this question), there is nothing to convert ['a'..'d', '0'..'3'] to ['a', 'b', 'c', 'd', '0', '1', '2', '3'] at compile time automatically.

There is rarely never a way to do something in D, if you want to hack around a bit.

import std.stdio;

@property charRange(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;
        auto start = s[1..$].front;
        auto end = s[0..$-1].back;

        return iota(start, end + 1).map!(c => cast(char)c).array;
    }).array.join;

}


void main(string[] argv)
{
    auto t = charRange!q{ 'a'..'z', 'A'..'Z', '0'..'9' };

    //abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
    writeln(t);
}

This is very rough code, as it only works for ASCII codepoints, and it can't do backward intervals, but you get the idea.
January 22, 2015
On Thursday, 22 January 2015 at 18:23:00 UTC, Meta wrote:
Whoops, I forgot to make it a template to force CTFE.

import std.stdio;

template charRange(string spec)
{
    static processInput(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;
            auto start = s[1..$].front;
            auto end = s[0..$-1].back;

            return iota(start, end + 1).map!(c => cast(char)c).array;
        }).array.join;
    }

    enum charRange = processInput(spec);
}


void main(string[] argv)
{
    auto t = charRange!q{ 'a'..'z', 'A'..'Z', '0'..'9' };
    writeln(t);

    readln();
}
January 22, 2015
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!...
January 22, 2015
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.
January 22, 2015
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.
January 22, 2015
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.
January 22, 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);
}
1 2
Next ›   Last »