Using inference to build immutable data structures without using casts

bearophile via Digitalmars-d digitalmars-d at puremagic.com
Fri Oct 10 02:56:05 PDT 2014


Walter Bright:

> https://www.reddit.com/r/programming/comments/2ilsij/function_purity_and_immutable_data_structure/

A problem is caused by with(){} that creates a scope. If I want
to write the literal of an immutable array of many enumerations I
have to repeat the enum name many times, this is the opposite of
DRY:

void main() {
      enum Seq { A, B, C, D, E, F, G, H }
      immutable Seq[2][] seqs =
              [[Seq.A, Seq.C], [Seq.A, Seq.D], [Seq.A, Seq.E],
               [Seq.B, Seq.D], [Seq.B, Seq.E], [Seq.B, Seq.F],
               [Seq.C, Seq.D], [Seq.D, Seq.E], [Seq.E, Seq.F],
               [Seq.G, Seq.C], [Seq.G, Seq.D], [Seq.G, Seq.E],
               [Seq.H, Seq.D], [Seq.H, Seq.E], [Seq.H, Seq.F]];
}


To avoid the repeating "Seq." I can use with() but now it can't
be immutable:

void main() {
      Seq[2][] seqs;
      with (Seq) seqs =
          [[A, C], [A, D], [A, E],
           [B, D], [B, E], [B, F],
           [C, D], [D, E], [E, F],
           [G, C], [G, D], [G, E],
           [H, D], [H, E], [H, F]];
}

I can define it immutable only if I use a global name:

immutable Seq[2][] seqs;
pure nothrow @safe static this() {
      with (Seq) seqs =
          [[A, C], [A, D], [A, E],
           [B, D], [B, E], [B, F],
           [C, D], [D, E], [E, F],
           [G, C], [G, D], [G, E],
           [H, D], [H, E], [H, F]];
}
void main() {}


There is also this possibility, but for me it's too much hairy to
be used in real code:

void main() {
      enum Seq { A, B, C, D, E, F, G, H }
      immutable Seq[2][] seqs = {
          with (Seq) {
              Seq[2][] local =
                  [[A, C], [A, D], [A, E],
                   [B, D], [B, E], [B, F],
                   [C, D], [D, E], [E, F],
                   [G, C], [G, D], [G, E],
                   [H, D], [H, E], [H, F]];
              return local;
          }
      }();
}

A solution seems to add a "static with" to D (usable at module
scope too), that doesn't create a new scope:

void main() {
      enum Seq { A, B, C, D, E, F, G, H }
      static with(Seq) immutable Seq[2][] seqs =
          [[A, C], [A, D], [A, E],
           [B, D], [B, E], [B, F],
           [C, D], [D, E], [E, F],
           [G, C], [G, D], [G, E],
           [H, D], [H, E], [H, F]];
}

Bye,
bearophile


More information about the Digitalmars-d mailing list