Это плохая идея помещать функции в карты Clojure, как в JavaScript? - PullRequest
10 голосов
/ 10 февраля 2011

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

Ответы [ 6 ]

8 голосов
/ 11 февраля 2011

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

Или, если хотите. Доверяйте своему суждению.

7 голосов
/ 13 февраля 2011

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

6 голосов
/ 10 февраля 2011

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

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

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

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

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

 foo.bar();

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

 (defn bar [foo]
   ;stuff
   ) 

И назовите это так:

  (bar foo)

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

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

4 голосов
/ 11 февраля 2011

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

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

Стиль, к которому я медленно приближаюсь после года Clojure:

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

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

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

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

2 голосов
/ 11 февраля 2011

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

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

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

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

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

1 голос
/ 14 февраля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...