Подтвердить что ты не робот

Это плохая идея поместить функции в карты Clojure, например, в JavaScript?

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

4b9b3361

Ответ 1

Clojure мультиметоды - это, по существу, карты функций, поэтому нет, это совсем не плохая идея.

Ответ 2

Сделайте это, если это сделает ваш код короче или проще для понимания или тестирования или отладки.

Или, если бы вам просто хотелось. Доверяйте своему мнению.

Ответ 3

Было бы плохо по нескольким причинам:

  • Это не нужно. В JavaScript мы делаем это, чтобы использовать простые карты как объекты, подобные Java. В Clojure, если вы действительно этого хотите, вы можете использовать фактический объект Java через Java interop.
  • Если вы размещаете функции на картах или используете реальный объект Java, вы выполняете объектно-ориентированное программирование в языковой среде, которая была разработана для функционального программирования. Первая проблема, которая приходит с этим, заключается в том, что ваш код просто не вписывался. Это выглядело бы странно, неуклюже и, возможно, даже слишком сложно в Clojure. На данный момент я не говорю, что ООП обязательно плохо, просто чтобы лучше писать ООП на языках, которые были предназначены для него.
  • Наиболее важным моментом в отношении такого стиля кодирования является то, что программа, подобная ООП, неизбежно опиралась бы на объекты, которые имеют некоторое состояние, и их функции-члены (похожие на методы), которые изменяют это состояние. Если вы используете состояние, то ваши функции не являются чистыми, и вы не можете использовать все функциональные качества, например, простое распараллеливание.

Короче говоря, если вы используете Clojure для выполнения ООП, вы будете только раздражаться. Вы можете сделать ООП более легко в тоннах других языков, например, скажем Groovy. Если вы хотите использовать Clojure, сделайте это функционально.

До сих пор я писал не делать этого и почему бы не сделать это. Теперь вы можете спросить меня: Итак, как мне писать функции в Clojure?

Напишите функции, которые принимают вашу структуру данных (например, карту, список, объект... независимо) в качестве параметра. Итак, вместо:

 foo.bar();

Вы бы определили его так:

 (defn bar [foo]
   ;stuff
   ) 

И назовите его следующим образом:

  (bar foo)

Теперь для чистой функции bar объект foo остается неизменным после оценки функции, и у вас нет общего состояния объекта, о котором нужно беспокоиться, если вы решили распараллелить свой код, который вы бы если вы делаете что-то ООП.

Кроме того, это может выглядеть как небольшая разница, но обратите внимание, что определение функции bar - это объект, полностью независимый от структуры данных foo. Кроме того, foo содержит только данные, а не поведение - все поведение в функции. Это разделение дает вам гораздо большую свободу при кодировании.

Ответ 4

Это работает - и в некотором смысле это естественно, если вы рассматриваете функции как первоклассные объекты на языке (как и все функциональные программисты должны!)

Однако - это требует реальной заботы, потому что в основном вы выполняете код перемежения с данными. Это скорее похоже на смешивание вашей модели данных с презентационным кодом в MVC. Да, могут быть ситуации, когда это имеет смысл, но общим принципом было бы избежать этого.

Стиль, с которым я медленно сблизился примерно через год Clojure, выглядит следующим образом:

  • Несколько refs/atom/vars верхнего уровня для прозрачного управления изменяемым состоянием (престиж для Rich Hickey!)
  • Большие, вложенные неизменные структуры данных в ссылках верхнего уровня
  • Чистые функции для обработки практически всей обработки.
  • Несколько функций, оканчивающиеся на! для тех неприятных побочных эффектов, используемых экономно
  • Много и много тестов! Это действительно важно, потому что с динамической типизацией и очень гибкими структурами данных вам нужно проверить почти все ваши предположения.
  • Java (к сожалению!) для оптимизации чувствительных к производительности разделов кода, как правило, путем определения легкого, неизменяемого Java-класса, который хорошо работает в структурах данных Clojure

Это решает большинство вещей под солнцем, одна вещь, которую я все еще пытаюсь выяснить, - лучший способ создать объекты с очень полиморфным поведением. Основные параметры, которые я вижу:

  • Использовать протоколы с deftype/defrecord - высокая производительность, идиоматическая Clojure, но вы получаете только одну отправку по типу, которая недостаточна для некоторых сильно полиморфных ситуаций.
  • Создавать функции, которые ведут себя полиморфным способом с помощью множества функций макроса/более высокого порядка - работает, но может очень запутанно/сложно поддерживать
  • Положите функции внутри карт! Да, он чувствует себя не так, но он работает!

По-прежнему не удалось выяснить, куда идти..... но у меня есть догадка, что функции могут проскользнуть в карты немного больше в будущем....

Ответ 5

Если вам действительно нужно сделать объектно-ориентированное программирование в Clojure, существует несколько способов сделать это.

Первый способ - использовать макросы deftype, defrecord и defprotocol.

Второй способ - использовать мультиметоды в сочетании с картой или типом записи для хранения данных.

Третий способ - использовать универсальный шаблон дизайна, описанный Steve Yegge, или более конкретное введение Clojure можно найти в Книга Криса Хаузера и Майкла Фогуса Радость Clojure.

Третий подход очень похож на то, что вы ожидаете увидеть в JavaScript, и первый подход, не считающийся ООП в традиционном смысле, является наиболее распространенным в "современном" идиоматическом Clojure.

Ответ 6

Пространства имен - это буквально карты функций. Гораздо проще использовать их для организации ваших функций. Однако, если вы столкнетесь с ограничением пространств имен для вашего варианта использования, вы можете рассмотреть возможность размещения функций на карте.

Как обычно, когда вы идете по проторенной дорожке, просто не задумывайтесь о том, почему вы не идете по очевидному маршруту.