Почему мультиметоды Clojure лучше, чем операторы if или case

Я потратил некоторое время, пытаясь понять мультиметоды Clojure. Главный аргумент "за" мультиметоды, насколько я понимаю, это их гибкость, однако меня смущает аргументация того, почему мультиметоды лучше простого оператора if или case. Может кто-нибудь, пожалуйста, объяснить, где проходит грань между полиморфизмом и преувеличенным оператором case?

РЕДАКТИРОВАТЬ: я должен был быть более ясным в вопросе, что меня больше интересует по сравнению с утверждением «если». Большое спасибо за ответы!


person Iger    schedule 11.03.2012    source источник
comment
Где проходит грань между оператором if и преувеличенным goto?   -  person Kevin    schedule 11.03.2012
comment
Вас может заинтересовать stackoverflow.com/q/5986120/625403, который не совсем дубликат, но тесно связан.   -  person amalloy    schedule 12.03.2012


Ответы (3)


Разница между мультиметодами и большим оператором if заключается в том, что вам нужно изменить функцию, содержащую оператор case, чтобы добавить случаи в оператор if. Вы можете добавить новый метод, не затрагивая ранее существующие методы.

Поэтому, если вы определяете мультиметод внутри своей библиотеки и хотите, чтобы ваши пользователи могли расширять его для своих собственных типов данных, это не проблема. Если бы вместо этого вы использовали оператор if, это было бы большой проблемой.

person sepp2k    schedule 11.03.2012
comment
Ааа, это действительно то, что я не понял, спасибо! Итак, мультиметоды не ограничены пространством имен, где был объявлен defmulti? - person Iger; 12.03.2012

Скажем, у нас есть типы A, B, C, D и E, а также методы m1, m2, m3, принимающие один аргумент предыдущих типов. Вы можете поместить их в таблицу следующим образом:

   | A | B | C | D | E |
m1 |   |   |   |   |   |
m2 |   |   |   |   |   |
m3 |   |   |   |   |   |

Стратегия оператора «переключатель» реализует одну строку этой таблицы за раз. Предположим, вы добавляете новый тип F. Вам придется модифицировать все реализации для его поддержки.

Полиморфизм на основе классов (C++, Java и т. д.) позволяет вместо этого реализовать целый столбец. Таким образом, добавление нового типа очень просто, так как вам не нужно изменять уже определенные классы. Но добавить новый метод сложно, так как вам придется добавить его ко всем другим типам.

Мультиметоды позволяют реализовать отдельные ячейки таблицы независимо друг от друга.

Эта гибкость еще больше, если вам нужно отправить несколько аргументов. Каждый новый аргумент добавляет еще одно измерение в эту таблицу, и диспетчеризация как на основе swich, так и на основе класса довольно быстро становится очень сложной (например, шаблон посетителя).

Обратите внимание, что мультиметоды на самом деле даже более универсальны, чем показано, поскольку вы можете выполнять диспетчеризацию почти по любому поводу, а не только по типам аргументов.

person ivant    schedule 11.03.2012

Ответ Ивана выше можно расширить, взглянув на эту статью. Это хорошо объясняет силу протоколов. Думайте о мультиметодах как о многомерных протоколах.

person endbegin    schedule 12.03.2012