non empty slices

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jun 2 09:21:03 PDT 2016


On 06/02/2016 05:16 PM, Alex wrote:
> What I mean is: if there would be a possibility to use algebraic types
> here (or maybe some kind of template...), then my types would be able
> (maybe! did not seen anything similar yet...) to choose the proper
> methods for themselves automatically:
> As long as my type has a length > 1 it is handled as a range, if the
> range has the length=1 it is handled as a single element and not as a
> range, if the range has the length=0 it is handled as an absent element.

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.
* The branching in f is guided by the parameter types of f_impl (could 
possibly be extracted, instead of being hardcoded manually).

Tell me if I'm way off.


More information about the Digitalmars-d-learn mailing list