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