D with experimental features like tuple unpacking

bearophile bearophileHUGS at lycos.com
Thu Mar 21 14:13:35 PDT 2013


UFCS, plus some tweaks to the standard library like this one 
(http://d.puremagic.com/issues/show_bug.cgi?id=8755 ) help write 
D code in a more functional (flow programming, Walter calls it 
component programming) style.

So tuples become more and more useful, and the lack of a syntax 
to unpack them becomes worse. So with time this unpacking syntax 
has bubbled up to become about my top enhancement request.

One good way to show what I mean is to actually show some code 
without and with such hypothetical syntax. The code needs to 
work, to be short, and not to be contrived. This computes the 
Huffman encoding of a dchar[]:


// --------------------------------------
import std.stdio, std.algorithm, std.typecons, 
std.container,std.array;

auto encode(T)(Group!("a == b", T[]) sf) {
     auto heap = sf.map!(s => tuple(s[1], [tuple(s[0], "")]))
                 .array.heapify!q{b < a};

     while (heap.length > 1) {
         auto lo = heap.front;
         heap.removeFront;
         auto hi = heap.front;
         heap.removeFront;

         foreach (ref pair; lo[1])
             pair[1] = '0' ~ pair[1];
         foreach (ref pair; hi[1])
             pair[1] = '1' ~ pair[1];
         heap.insert(tuple(lo[0] + hi[0], lo[1] ~ hi[1]));
     }

     return heap.front[1].schwartzSort!(p => tuple(p[1].length, 
p[0]));
}

void main() {
     auto s = "this is an example for huffman encoding"d;
     foreach (p; s.dup.sort().release.group.encode)
         writefln("'%s'  %s", p.tupleof);
}
// --------------------------------------


sort is followed by () because for unknown reasons we have not 
yet deprecated/removed the broken built-in array sort.


The same code with unpacking syntax:


// --------------------------------------
import std.stdio, std.algorithm, std.typecons, 
std.container,std.array;

auto encode(T)(Group!("a == b", T[]) sf) {
     auto heap = sf.map!(((c, f)) => tuple(f, [tuple(c, "")]))
                 .array.heapify!q{b < a};

     while (heap.length > 1) {
         auto (lof, loa) = heap.front;
         heap.removeFront;
         auto (hif, hia) = heap.front;
         heap.removeFront;

         foreach ((c, ref e); loa)
             e = '0' ~ e;
         foreach ((c, ref e); hia)
             e = '1' ~ e;
         heap.insert(tuple(lof + hif, loa ~ hia));
     }

     return heap.front[1].schwartzSort!(((c, e)) => 
tuple(e.length, c));
}

void main() {
     auto s = "this is an example for huffman encoding"d;
     foreach ((c, e); s.dup.sort().release.group.encode)
         writefln("'%s'  %s", c, e);
}
// --------------------------------------


The noisy [0] [1] are vanished from the encoding function.

In that code tuple unpacking happens in normal assignments:

auto (lof, loa) = heap.front;


Inside function signatures; notice the double (()) needed for a 
lambda:

map!(((c, f)) => ...)


And in foreach:

foreach ((c, ref e); loa)


Walter said that it's hard to predict what bad interactions such 
syntax will have with the other parts of the D syntax. I agree 
with this. On the other hand being frozen with fear isn't enough, 
the partial patch by Hara is getting dust since months. Given the 
importance of this feature, to break this ice and start moving 
forward I suggest to distribute a dmd with this experimental 
feature, and let people use and try it for few months or one year 
or more. Hopefully this will be enough to uncover the problems.

One way to do it is to just distribute a compiled experimental 
dmd with this feature. But this dmd will become quickly obsolete. 
An alternative solution is to use the idea of the Haskell GHC 
compiler, and introduce a compiler switch like 
-experimental=tuple_unpack (it's off on default). Python uses 
"from future import ..." for similar purposes.

I think it's good to have such staging in D for new ideas (I 
think it will be less used than in GHC). Such staging will avoid 
design mistakes like @[]  @() for UDAs and similar. Having a 
feature implemented in a GitHub patch is not enough, because only 
1-5 persons try it for a very short time. And putting a feature 
in DMD to eventually remove it in a successive DMD if it's bad 
(like the built-in regular expression syntax experiment) can't 
work any more at the current advanced stage of the D development.

Bye,
bearophile


More information about the Digitalmars-d mailing list