Сегодня вышли новые версии компиляторов DMD – 1.053 и 2.047. В новых версиях большое количество баг-фиксов. Среди которых и исправление бага 3521. В news-группе digitalmars.D.announce Вальтер Брайт сказал, что этот баг, вероятно, прожил более 18 лет. Он срабатывал очень и очень редко. И для его поимки пришлось модифицировать C++ компилятор и прогнать большое количество тестов.
Такие дела. Что-то в последнее время баги вокруг возникают просто в невообразимых количествах. То на бажную обертку для libcurl наткнешься, то на баги в Poco. Наш новый клиент буквально вчера нашел у меня баг, которому если не пять лет, то года четыре точно. Прямо эпидемия какая-то, сезонная ;)
PS. Забавно, что в DMD 2.047 опять появилось много нововведений. В частности, некий opDispatch, назначение которого я с ходу понять не смог.
7 комментариев:
Да похоже до релиза D еще далеко :(
opDispatch как я понял перехват не найденных вызовов, подобное есть например в питоне, удобно чтобы делать всяческие прокси классы и для некоторых DSL.
>удобно чтобы делать всяческие прокси классы и для некоторых DSL.
Разработчикам D не мешало бы в документации пару-тройку жизненных примеров для этого дела привести. А то это штука такая, которая вроде как в compile-time работает, но выглядит как вызов метода. Пример же когда opDispatch приводит к определению enum-а вообще бошку сносит :) Куда его в жизни применить сразу и не поймешь.
Ну я в питоне подобным пользовался поэтому ничего крышесносного не вижу :)
В compile-time организовать тоже ничего сложного, если метод не найден попробовать вместо него подставить вызов шаблонной функции opDispatch.
Применений много, например прокси, притом не как operotor-> в С++ (или opDot в D) а гораздо более гибкий, например можно реализовать ленивые вычисления, или к примеру прозрачный доступ к DOM подобным конструкциям, когда можно писать типа xml.body.header = "Test". Ну и что-то linq подобное наверно будет проще сделать.
Ну в Ruby я тоже пользовался method_missing временами. Однако там все просто -- язык динамический и все такое.
Здесь же ситуация какая-то странная. Например, как перехватывать несколько вызовов с разными списками аргументов? Как выводить типы возвращаемых значений? В Ruby с этим проблем нет.
С разными списками аргументов без проблем
import std.stdio;
struct S
{
T opDispatch(string s, T)(T a, T b)
{
writefln("S.opDispatch('%s')", s);
static if(s == "add")
{
return a + b;
}
else static assert(!"unknown operator");
}
void opDispatch(string s, T)(ref T a)
{
writefln("S.opDispatch('%s')", s);
static if(s == "add")
{
++a;
}
else static assert(!"unknown operator");
}
}
void main()
{
S s;
writefln("%d", s.add(1, 2));
int x = 0;
s.add(x);
writefln("%d", x);
}
Обычная перегрузка, ну и при необходимости variadic template. Автовывод возвращаемого значения тут по моему сильно и не нужен, хотя при желании и с этим поизвращаться :)
>T opDispatch(string s, T)(T a, T b)
>void opDispatch(string s, T)(ref T a)
Я не знал, что в рамках одной структуры можно определить несколько opDispatch с разными параметрами.
Даже если бы было нельзя хватило бы variadic template + static if.
Отправить комментарий