clojure vs c # язык - PullRequest
       19

clojure vs c # язык

15 голосов
/ 08 июня 2011

Я все еще пытаюсь понять явные преимущества clojure.Я понимаю, что это динамический, [почти] чисто функциональный язык, который хорошо подходит для модульного тестирования, параллелизма и быстрого развития.

Я смотрел эту презентацию ее основателя Рича Хики.

На отметке 25-й минуты вы можете увидеть множество замечательных способов, с помощью которых clojure упрощает программирование благодаря возможности динамически определять списки и векторы:

( 123) [123]

возможность использовать их динамическиопределяемые векторы как функции

([ 123] 0)

способность вызывать функции для вновь определенных строк

(.ToUpperCase "foo")

, как выразился Рич, «синтаксис для литералов - это синтаксис для языка» ..прекрасный.

но разве невозможно реализовать этот стиль программирования в .net 4.0?(хотя и более болтливый)

(new[] {1,2,3})[0]
"foo".ToUpper()

и т. д. .net также может быть использован для функционального программирования (хотя это не обязательно)

это тривиальные примеры, но кажется, чтоэто основа clojure.Какие функции выделяют clojure и делают его лучшим выбором в некоторых сценариях?

Ответы [ 4 ]

23 голосов
/ 09 июня 2011

Лично я считаю, что синтаксис Clojure очень эффективен, лаконичен и даже красив, когда вы освоите его.Однако, на мой взгляд, не является самой веской причиной для выбора языка.

Мои личные причины, почему я предпочел Clojure в качестве своего "универсального языка разработки" после многих лет Javaи C #:

  • Макропрограммирование макроса - Clojure является Lisp и наследует девиз семейства Lisp "Code is Data".Поскольку сам язык написан в форме, которая сама по себе является структурой данных в языке (это называется Гомо-звонность ), написать код, который генерирует код в любой выбранной вами форме, тривиально.По сути, вам больше никогда не нужно беспокоиться о «шаблонах проектирования» - если в языке, которого вы хотите использовать, чего-то не хватает, вы просто расширяете язык макросом и двигаетесь дальше…

  • Динамический по умолчанию - Clojure является динамическим языком по умолчанию, что означает, что он автоматически «правильно делает» гибким способом для большинства задач.Это делает вас более продуктивным.Примерами являются автоматическое перетекание в арифметику BigInteger, возможность помещать в коллекцию любые типы объектов, которые вам нравятся, не нужно объявлять типы параметров и т. Д. В то же время вы можете указать информацию о типе для повышения производительности при необходимости.(например, напрямую используя примитивы или предоставляя подсказки типа) - чтобы вы могли получить действительно быструю производительность при необходимости.

  • Акцент на функциональном программировании с постоянными неизменяемыми даннымиструктуры и ленивый анализ - в частности, вся базовая библиотека Clojure по умолчанию поддерживает этот стиль разработки.Как только вы это освоите (я признаю, что это не так просто ...), FP становится исключительно мощным.Хотя вы можете эмулировать код в стиле «FP» практически на любом языке, вы в полной мере получаете преимущества только тогда, когда это распространенная особенность языка (Clojure, Haskell, ML наиболее очевидны)

  • Отличный многоядерный параллелизм .Благодаря очень новой системе STM, я считаю, что Clojure имеет лучшую историю параллелизма на любом языке на данный момент (см. Это видео для более детальной проработки самого Рича Хики )

  • Экосистема библиотеки с открытым исходным кодом - Я большой поклонник открытого кода, а Clojure - очень дружественный язык с открытым исходным кодом.Сам язык и почти каждая библиотека с открытым исходным кодом, и если вам этого недостаточно, вызывать библиотеки Java тривиально.Учитывая широту всей экосистемы Java / JVM с открытым исходным кодом, это означает, что практически все, что вы хотите сделать, легко доступно в библиотеке (большое преимущество перед большинством новых языков!)

  • Функциональная совместимость JVM - это может вас не волновать, но лично для меня очень важно иметь возможность интеграции с библиотеками и инструментами во вселенной Java / JVM.Clojure делает это очень простым - объекты Clojure являются объектами JVM под капотом, и вызов метода Java обычно так же прост, как (.someMethod someObject someParameter)

  • Интерактивная разработкав REPL - типичным стилем разработки Clojure является взаимодействие с работающей программой Clojure в REPL.Вы можете переопределить практически все на лету, не выполняя цикл компиляции / сборки / тестирования.Это удивительно продуктивный способ работы - я в основном собираю работающую программу на REPL, а затем копирую нужные команды в исходный файл для запуска в будущем.Глупый пример - у меня есть одна строка, которая способна визуализировать различные структуры данных из запущенной программы на графике с помощью Incanter.Я сразу могу визуально увидеть, если что-то идет не так, и это само по себе спасло мне несколько недель отладки ....

  • Сообщество - Мне лично нравится сообщество Clojure, которое небольшое, но быстро растущее.В нем правильно сочетаются прагматизм (то есть выполнение задач), полезность и забота о том, чтобы делать что-то хорошо, что я считаю важным.

11 голосов
/ 08 июня 2011

Объяснение Clojure дает гораздо более подробную информацию, чем я, но мои причины изучения Clojure были:

  • Макросы - Код - это данные, данныеэто код ( гомойкон ).Макросы дают вам возможность писать новый код во время компиляции, и это позволяет вам добавлять новый синтаксис к языку.
  • Программная транзакционная память - STM позволяет писать код, не беспокоясь онизкий уровень параллелизма.В программной транзакции среда выполнения Clojure определяет, обращаются ли две транзакции к одним и тем же данным, и резервирует одну из них и повторяет попытку.
  • Интеграция с существующей виртуальной машиной - благодаря возможности использовать Java, Clojure автоматическиимеет доступ к миллионам строк проверенного кода.
10 голосов
/ 08 июня 2011

Основные удобства Clojure по сравнению с C # упорядочены по уровню удобства, с огромными улучшениями наверху:

  • Более приятный синтаксис для буквальных коллекций, как вы заметили. В первую очередь для литеральных хеш-карт, которые в C # достаточно уродливы (вам нужно выписать универсальный тип), чтобы вы не определяли одну строку. C # new Dictionary<string, int> { { "Joe", 6" }, { "Steve", 18" } } становится {"joe" 6, "steve" 18}.

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

  • Ключевые слова позволяют легко ссылаться на вещи символически, не тратя время на определение перечислений.

  • Библиотека ядра имеет много полезных встроенных функций для функционального программирования, которых нет в LINQ.

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

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

  • Метаданные чрезвычайно удобны; это позволяет вам «привязать» информацию, которая сочетается с другими данными, намного проще, чем, например, определение одноразового типа, представляющего оригинал-данные-плюс-другие-вещи.

  • Часто вы хотите использовать абстракцию с типами, которые вы не контролируете; Протоколы Clojure позволяют легко это сделать, тогда как в C # это практически невозможно, поскольку вы не можете расширить чужой тип для реализации интерфейса. (Вы даже не можете делать тривиальные вещи, такие как создание INumeric интерфейса.)

  • Макросы проще в использовании и более мощные, чем деревья выражений C # для расширения языка.

Вы можете найти больше информации о большинстве упомянутых выше материалов на Clojure.org .

7 голосов
/ 08 июня 2011

([1 2 3] 0) не эквивалентно (new [] {1,2,3}) [0], поскольку в clojure [1 2 3] может быть передано функции, которая принимает любую функцию, которая принимаетint и возвращает значение.Например:

(defn do-something [mylist myfunc]
  (map myfunc mylist))

(do-something [0 2] [1 2 3])

=> (1 3)

Это позволяет вам повторно использовать что-то с любой функцией, которая получает 1 аргумент и возвращает значение.

...