Choice ranges?

Artur Skawina art.08.09 at gmail.com
Sat Mar 29 10:19:00 PDT 2014


On 03/29/14 16:31, Timon Gehr wrote:
> On 03/29/2014 01:37 AM, Artur Skawina wrote:
>> You can wrap the range in a common one. When the above approach isn't
>> enough, there's always the next level:
> 
> (Note that your code does not actually compile.)

Of course it compiles -- with the compiler version I happen to use...

The compiler situation is one of the main reasons I gave up on D 
about a year ago. Every release introduces a new dialect. This may
not be such a big problem for trivial toy programs, but for anything
else it means that the only practical approach is locking the toolchain
down and never looking forward.
Sometimes this means that the examples I post won't work -- I don't
have any newer D compiler to check with, sorry.

The reason I'm still around here is that while D has tons of problems,
there is no better alternative available, for now.

I decided to revisit that DynRange implementation today, to see just how
concise and readable it could be made, while still resulting in absolutely
optimal codegen. The result was this:

   struct DynRange(R, F...) {
      size_t n;
      union { mixin(fmtStmts!(q{ typeof(F[$d](R.init)) r$d; }, F)); }

      this(R r, size_t n) {
         this.n = n;
         mixin(fmtSwitch!("n", q{ $d: r$d = F[$d](r); break; }, F));
      }

      mixin switchDispatch!("n", q{ $d: return r$d.$member $args; }, F);
   }

   // [1]

artur


[1] // The generic helpers used:

   template evalExpMap(string C, string F, A...) {
      enum evalExpMap = {
         import std.array, std.conv;
         string s, l, t;
         static if (is(typeof(A))) alias B = typeof(A);
                else               alias B = A;
         foreach (I, _; B) {
            auto r = replace(replace(F, "$s", A[I].stringof),
                                        "$d", to!string(I));
            l ~= (I?", ":"") ~ r;
            s ~=               r ~ ";\n";
            t ~=               r ~ " ";
         }
         return replace(replace(replace(C, "$...;", s), "$...,", l), "$...", t);
      }();
   }
   template fmtStmts(string FMT, A...) { alias fmtStmts = evalExpMap!("$...", FMT, A); }
   template fmtSwitch(string EXP, string FMT, A...) {
      alias fmtSwitch = evalExpMap!("switch ("~EXP~") { $... default: assert(0); }", "case "~FMT, A);
   }

   // fmtDispatch: A helper that keeps all the @property boilerplate in one place.
   mixin template switchDispatch(string EXPR, string CODE, T...) {
      template opDispatch(string M) {
         import std.array;
         enum C = replace(CODE, "$member", M);
         @property auto ref opDispatch()()
          if (is(typeof(function { mixin(fmtSwitch!(EXPR, replace(C, "$args", ""), T)); }))) {
            mixin(fmtSwitch!(EXPR, replace(C, "$args", ""), T));
         }
         @property auto ref opDispatch(A...)(A a)
          if (is(typeof(function { mixin(fmtSwitch!(EXPR, replace(C, "$args", "=a"), T)); }))) {
            mixin(fmtSwitch!(EXPR, replace(C, "$args", "=a"), T));
         }
         auto ref opDispatch(A...)(A a)
          if (is(typeof(function { mixin(fmtSwitch!(EXPR, replace(C, "$args", "(a)"), T)); }))) {
            mixin(fmtSwitch!(EXPR, replace(C, "$args", "(a)"), T));
         }
      }
   }



More information about the Digitalmars-d-learn mailing list