Совсем недавно, 14 ноября 2006 года, увидел свет D версии 0.174. Как водится,
что-то пофикшено, что-то выброшено (хороший, вероятно подарочек тем, кто на D уже начал писать). А вот среди добавленого оказалась
поддержка туплов. Которая в сочетании с
variadic templates делает программирование на шаблонах в D гооораздо привлекательнее, чем в C++
Например, стандартные пакеты
std.traits и
std.typetuple уже содержат то, что в C++ достигается килобайтами кода из Boost-a. Красота однако, аж слюньки текут.
Не все, однако, мне понятно и не все, имхо, еще чисто с этими нововедениями. Например, в процитированном ниже коде из описания туплов приходится реализовывать шаблон CurryAll дважды. Вальтер Брайт объясняет это тем, что невозможно перегрузить один и тот же шаблон двумя одинаковыми списками аргументов, поэтому в первый добавляется параметр Dummy. Чем-то напоминает сегоднящние workaround-ды для C++ с помощью SFINAE (хотя в обсуждениях на форуме Брайт высказался, что возможно в будущем это дело будет упрощено). Так же странно, что для копирования элементов из args в Foo.args_m приходится прибегать к поэлементному копированию. Обычное присваивание (пока?) не работает.
Так же много еще не сделано. В частности, нет возможности возвращать туплы из функции.
В общем, по своим языковым изыскам D лично для меня все привлекательнее и привлекательнее, чем C++ (особенно скорость его компиляции). Но когда же, черт побери, стабильная версия выйдет!!! Так ведь и C++0x быстрее, чем D 1.0 stable появится
(
Кстати, среди нововведений версии 0.174 есть ключик командной строки -v1, который включает поддержку совместимости с версией 1.0 языка. Значит ли это, что 1.0 уже была? ).
А вот пример из описания туплов D:
R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args)
{
struct Foo
{
typeof(dg) dg_m;
U args_m;
R bar()
{
return dg_m(args_m);
}
}
Foo* f = new Foo;
f.dg_m = dg;
foreach (i, arg; args)
f.args_m[i] = arg;
return &f.bar;
}
R delegate() CurryAll(R, U...)(R delegate(U) dg, U args)
{
struct Foo
{
typeof(dg) dg_m;
U args_m;
R bar()
{
return dg_m(args_m);
}
}
Foo* f = new Foo;
f.dg_m = dg;
foreach (i, arg; args)
f.args_m[i] = arg;
return &f.bar;
}
void main()
{
static int plus(int x, int y, int z)
{
return x + y + z;
}
auto plus_two = CurryAll(&plus, 2, 3, 4);
printf("%d\n", plus_two());
assert(plus_two() == 9);
int minus(int x, int y, int z)
{
return x + y + z;
}
auto minus_two = CurryAll(&minus, 7, 8, 9);
printf("%d\n", minus_two());
assert(minus_two() == 24);
}