Ответ 1
Clojure мультиметоды - это, по существу, карты функций, поэтому нет, это совсем не плохая идея.
Я новичок в Clojure и нахожу свои морские ноги. Мне было интересно, считается ли это хорошей или плохой практикой, с точки зрения функционального программирования, размещать функции в картах Clojure, а затем передавать эти карты вокруг как квазиобъекты, как это часто делается в JavaScript. Пояснения также будут оценены.
Clojure мультиметоды - это, по существу, карты функций, поэтому нет, это совсем не плохая идея.
Сделайте это, если это сделает ваш код короче или проще для понимания или тестирования или отладки.
Или, если бы вам просто хотелось. Доверяйте своему мнению.
Было бы плохо по нескольким причинам:
Короче говоря, если вы используете Clojure для выполнения ООП, вы будете только раздражаться. Вы можете сделать ООП более легко в тоннах других языков, например, скажем Groovy. Если вы хотите использовать Clojure, сделайте это функционально.
До сих пор я писал не делать этого и почему бы не сделать это. Теперь вы можете спросить меня: Итак, как мне писать функции в Clojure?
Напишите функции, которые принимают вашу структуру данных (например, карту, список, объект... независимо) в качестве параметра. Итак, вместо:
foo.bar();
Вы бы определили его так:
(defn bar [foo]
;stuff
)
И назовите его следующим образом:
(bar foo)
Теперь для чистой функции bar
объект foo
остается неизменным после оценки функции, и у вас нет общего состояния объекта, о котором нужно беспокоиться, если вы решили распараллелить свой код, который вы бы если вы делаете что-то ООП.
Кроме того, это может выглядеть как небольшая разница, но обратите внимание, что определение функции bar
- это объект, полностью независимый от структуры данных foo
. Кроме того, foo
содержит только данные, а не поведение - все поведение в функции. Это разделение дает вам гораздо большую свободу при кодировании.
Это работает - и в некотором смысле это естественно, если вы рассматриваете функции как первоклассные объекты на языке (как и все функциональные программисты должны!)
Однако - это требует реальной заботы, потому что в основном вы выполняете код перемежения с данными. Это скорее похоже на смешивание вашей модели данных с презентационным кодом в MVC. Да, могут быть ситуации, когда это имеет смысл, но общим принципом было бы избежать этого.
Стиль, с которым я медленно сблизился примерно через год Clojure, выглядит следующим образом:
Это решает большинство вещей под солнцем, одна вещь, которую я все еще пытаюсь выяснить, - лучший способ создать объекты с очень полиморфным поведением. Основные параметры, которые я вижу:
По-прежнему не удалось выяснить, куда идти..... но у меня есть догадка, что функции могут проскользнуть в карты немного больше в будущем....
Если вам действительно нужно сделать объектно-ориентированное программирование в Clojure, существует несколько способов сделать это.
Первый способ - использовать макросы deftype
, defrecord
и defprotocol
.
Второй способ - использовать мультиметоды в сочетании с картой или типом записи для хранения данных.
Третий способ - использовать универсальный шаблон дизайна, описанный Steve Yegge, или более конкретное введение Clojure можно найти в Книга Криса Хаузера и Майкла Фогуса Радость Clojure.
Третий подход очень похож на то, что вы ожидаете увидеть в JavaScript, и первый подход, не считающийся ООП в традиционном смысле, является наиболее распространенным в "современном" идиоматическом Clojure.
Пространства имен - это буквально карты функций. Гораздо проще использовать их для организации ваших функций. Однако, если вы столкнетесь с ограничением пространств имен для вашего варианта использования, вы можете рассмотреть возможность размещения функций на карте.
Как обычно, когда вы идете по проторенной дорожке, просто не задумывайтесь о том, почему вы не идете по очевидному маршруту.