On Thursday, 2 June 2016 at 16:21:03 UTC, ag0aep6g wrote:
On 06/02/2016 05:16 PM, Alex wrote:

I may be getting what you're up to. Maybe not.

So we start with something like this (using arrays instead of arbitrary ranges to keep things simple):


    import std.stdio: writeln;
    void main()
    {
        f([]);
        f([1]);
        f([1, 2]);
    }
    void f(int[] a)
    {
        if (a.length == 0) f_none(a);
        else if (a.length == 1) f_one(a);
        else f_many(a);
    }
    void f_none(int[] a)
    {
        writeln("nothing to see here");
    }
    void f_one(int[] a)
    {
        assert(a.length == 1);
        writeln("exactly one: ", a[0]);
    }
    void f_many(int[] a)
    {
        assert(a.length >= 2);
        writeln("at least two: ", a[0 .. 2]);
    }


And instead you'd like something more like this:


    import std.stdio: writeln;
    import std.variant: Algebraic;

    void main()
    {
        f([]);
        f([1]);
        f([1, 2]);
    }

    void f(int[] arr)
    {
        A a = arrayToA(arr);
        foreach (T; A.AllowedTypes)
        {
            if (T* p = a.peek!T) f_impl(*p);
        }
    }

    void f_impl(Empty e) { writeln("nothing to see here"); }
    void f_impl(int a) { writeln("exactly one: ", a); }
void f_impl(Many!int a) { writeln("at least two: ", a[0 .. 2]); }

    struct Empty {}
    struct Many(T)
    {
        T[] arr;
        alias arr this;
        /* Somehow it's enforced here that arr.length >= 2. */
    }

    alias A = Algebraic!(Empty, int, Many!int);
    A arrayToA(int[] a)
    {
        A result;
        switch (a.length)
        {
            case 0: result = Empty.init; break;
            case 1: result = a[0]; break;
            default: result = Many!int(a);
        }
        return result;
    }


And the advantages of it are:
* Don't need asserts in the different `f_impl`s.
Yes.

* The branching in f is guided by the parameter types of f_impl (could possibly be extracted, instead of being hardcoded manually).
Yes! :)


Tell me if I'm way off.
You totally hit the point!
The cool thing about the Algebraic is as I expected, that it doesn't change it's type... And the hard thing is, that I'm not used to its Empty, Many, ... things yet. But the question remains how to keep this @nogc? I wonder at the line with peek... and why it is not just returning the value...

Reply via email to