Pull to refresh

Comments 18

В месте, где мы определяем оператор равенства и D автоматически из него выводит оператор неравенства — у меня сразу возникает дурацкий вопрос.

Могу ли я вручную сам определить оба оператора?

Поясню мысль — допустим, у меня есть некая структура достаточно большого размера. Чтобы проверить ее равенство — нужно проверить миллион равенств ее членов, а для того, чтобы определить неравенство — достаточно первого неравенства.
Нет, к сожалению нет. У меня тоже возникли поначалу мысли, что это нехорошо, но с другой стороны операторы — всего лишь синтаксический сахар, для суровой оптимизации можно обойтись и без них.
Хотя стоп, о чем это я? Равенство относительно членов проверяется лениво — то есть, если что-то не равно, то заведомо не равно! Приведите пожалуйста конкретный пример с проблемой эффективности.
Ты в проверке равенств, когда первое неравенство получишь, разве есть смысл дальше равенства проверять?
В принципе, логично. В любом случае, подобный подход страхует от ошибок двойного определения.
Увидев первый вариант opUnary уже было хотел разразится праведным generic гневом, но успел прочитать чуть дальше :)
Важный момент — range не должны имплементировать интерфейс и даже не обязаны иметь методы с таким именем. Необходимое и достаточное условие — должен компилироваться код с использованием этих методов. Думаю в контексте вашего же Dynamic должно быть понятно, почему это принципиальное отличие.
А про интерфейс — это я имел ввиду «виртуально» имплементировать. Ведь не обязательно иметь интерфейс в виде кода, чтоб его имплементировать.
obj.AddMethod(«empty»,… );
obj.AddMethod(«front»,… );
obj.AddMethod(«popFront»,… );
Философский вопрос — имплементировано ли в этом случае искомое? :)
Ну вроде как да. Интерфейс же предоставлен. В сущности, обычным образом определяя интерфейс мы делаем то же самое — добавляем методы в класс. Только тут обьект будет имплементировать, а класс обьектов данного типа.
На самом деле забавную ситуацию можно представить:
a.foo() раскрывается, как a.opDispatch!«foo»(), что в свою очередь раскрывается, как a.opDispatch!«opDispatch!»foo"()"() и так далее…
Я прямо уверен, что такой баг при написании компилятора проскочил.
Была ( а скорее всего и есть ) проблема, связанная с тем, что opDispatch без статических ограничений делает класс полностью нерабочим в сочетании с duck-typing алгоритмами. Он будет проходить все мыслимые constraints. Но это, кажется, неизбежная расплата.
Чем больше читаю, тем больше удивляюсь:
Complex opBinary(string op)(Complex v) if (op == "-" || op == "+")
{… }


Что в этом случае значит двойные скобки () () — функция, которая возращает функцию? Это только для операторов возможно? Как такое вызывать? В чем отличие если функция просто вернет делегата?

В этом примере получается, что 1-ая функция раскрывается статически — на этапе компиляции, а вторая динамически, по крайней по логике. А на самом деле?

Можно ли переопределить умножение 2-х строк (или классов из другой библиотеки )? Можно ли при этом вернуть объект не строку? И еще чуть-чуть не понятно, как компилятор определяет, что к чему приводить.
Пример есть Real var = ((Complex)s) + ((String) t);

P. S.: за статью спасибо, немного не хватает базовых понятий, в синтаксическом сахаре легко запутаться.
Это не функция возвращающая функцию, это описание шаблонного параметра. В синтаксисе C++ это могло бы выглядеть так
template Complex opBinary(Complex v);

template Complex opBinary(Complex v){… }
template Complex opBinary(Complex v){… }
Парсер съел шаблонные параметры
Еще раз:
template<string op> Complex opBinary(Complex v);

template Complex opBinary<"-">(Complex v){…}
template Complex opBinary<"+">(Complex v){…}
Прочитайте мою предыдущую (вторую) статью, чтобы разобраться в вашем вопросе. В данном случае компилятор ничего ни к чему не приводит, но вообще D придерживается идеологии explicit better than implicit и автоматически приводит только некоторые числа.
Sign up to leave a comment.

Articles