2015-10-03 3 views
0

Есть много восхитительных мнений о макросах в Lisp, но я действительно не могу найти праймер, который я могу использовать в своем ежедневном рабочем процессе. Я веб-разработчик, но использую emacs около 10 лет. И я хочу понять, действительно ли макросы действительно полезны для всех, или это просто функция убийцы для очень конкретных задач.Являются ли макросы lisp полезными в типичной разработке?

Большинство праймеров с использованием макросов - это попытки сделать DSL поверх lisp. Ну, это может быть полезно иногда, но создание синтаксических расширений в коммерческом развитии - это плохая практика, насколько я понимаю. Большинство языков имеют стандартные функции, такие как, если, в то время как операторы foreach, общие концепции, такие как классы, пространства имен, модули, замыкания (lambdas). Таким образом, все программы, как правило, построены из таких произведений, и новый программист, изучающий ваш код, уже знает, что штук и может ими управлять. А в случае DSL, построенного на макросах, программисту нужно не только изучить бизнес-логику, но и узнать свой DSL. Коммерческая значимость для типичных решений с простой поддержкой и высокой заменой программистов.

Далее - создание шаблонов двигателей поверх макросов. Ну, теперь отраслевым стандартом является Twig, Jinja2, Template Toolkit - вы можете создать свою собственную систему шаблонов, но ... Это 2015 год, а не 2001 год, когда был создан Viaweb Пола Грэма. Современные системы шаблонов очень похожи друг на друга - они разрабатывались годами, и у них много концепций, таких как блоки, фильтры, наследование, i18n. Так что в 2001 году создание собственного шаблонизатора имело смысл, но теперь есть сложные шаблонные двигатели для всех suddens жизни.

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

Далее - сами алгоритмы. В настоящее время 90% из нас, веб-разработчиков, просто используют готовые библиотеки и алгоритмы. Поэтому, даже если я ошибаюсь в предыдущем параграфе, роль макросов очень мала в нашей работе.

Итак, вы действительно используете макросы каждый день, или вы просто просто снимаете некоторые проблемы с макросами очень изящно и экстраполируете этот hapinees на следующие несколько месяцев?

+3

Макросы используются только тогда, когда они необходимы, а не для удовольствия или просто для макросов. Если вы можете моделировать свое приложение и свои внутренние DSL таким образом, что они могут быть реализованы с использованием функций, тем лучше. – progo

+0

Я просто думаю, что теряю очень полезный инструмент, потому что я не понимаю, где он может быть применим. Все примеры макросов, которые я нашел, слишком синтетичны. – Rengraz

+0

Используйте макросы, когда вы не можете делать то, что вам нужно другим способом. Для многих контекстов программирования это редко. К сожалению, некоторые программисты Lisp пытаются убедить других в значении Lisp, обсуждая макросы. Это один ответ на вопрос «Почему так много круглых скобок?» вопрос. Lisp настолько гибкий, что макросы не требуются, за исключением особых потребностей. – Mars

ответ

2

цитата

Существует цитата, я видел несколько раз в сообществе Clojure:

данных> функции> макросы

данных

Почему ? Ну данные потрясающие: вы можете распечатать его, преобразовать, сериализовать, чтобы отправить его в сеть ... Это также язык-агностик. Вы можете преобразовать его в другое представление и использовать другую программу, написанную на другом языке. Насколько это мощно? Как глинянин, вы можете видеть, что почти все функции Clojure предназначены для управления данными. Это приятно манипулировать данными. Цитирование Fogus:

Хорошо сформированные данные в состоянии покоя как можно ближе к совершенству при программировании. Все дерьмо, которое должно было случиться, чтобы поместить его там ...

Функция

Тогда приезжайте функции: в шепелявостью нам повезло иметь их зеркально структуру данных (список), но это все равно меньше, чем компонуемо данные. Например, можете ли вы merge код? Предположим, в этом случае merge означает comp ose. Можете ли вы сказать, откуда приходит функция? Можете ли вы diff это? Таким образом, в некотором смысле функции являются данными бедного человека.

Макросы

Но Clojure пытается облегчить боль. И для этого есть несколько инструментов. Некоторые из них просты (например, meta, которые действительно привязывают данные к функции) или макросы. Нам повезло! У нас есть макросы для управления кодом. Это еще менее приятно, чем манипулировать необработанными данными, но мы получаем его там. Теперь для обычного аргумента «но функции - данные в Clojure»: сколько функций данных Clojure работает над функциями? Однако есть большая неудобство. Процитировать Eric Normand:

Макросы непрозрачны во время выполнения.

То есть, они не являются первоклассными гражданами, и вы не можете передавать макросы в качестве значений. Итак, как мы составляем макросы? Больше макросов? Это похоже на скользящий путь.

К настоящему моменту вы можете почувствовать, что мы предпочли бы не использовать их. Конечно, они очень мощные (код, который меняет код? Это звучит довольно круто!).

Кстати, I чувствую (хотя у меня нет никаких ссылок), что Clojure пытается нацелиться на удобочитаемость и меньше скобок, чем на другие листы, за счет того, что макросъемка немного сложнее.

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

Примеры

Самого классическое использование макроса я могу думать о том, чтобы определить if конструкции. Можем ли мы сделать это с помощью функции? Давайте попробуем:

(defn if [condition if-true if-false] 
    ...) 

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

(if true (println "true!") (println "false!)) ;; prints both "true!" and "false!" 

Макросы не оценивают свои аргументы и поэтому используются в этом случае. Вы можете найти их в [clojure.core][3]. Что касается типичной веб-разработки (укажите «типичный»?), Давайте посмотрим на некоторые макросы в дикой природе.

В [mori][3] есть страница в вики о benchmarking, где мы видим, что функции определены с несколькими arities. Макрос для экспорта этих функций определяется here и используется there.

От этого же автора мы можем взглянуть на макрос [defui][6]Om.

Множество макросов, которые я видел в дикой природе, также просто упрощают декларацию, например [defroute][6] в Compojure.

Также, если у вас было время, чтобы прочитать мой ответ, вам обязательно нужно посмотреть "Zach Tellman - Always Be Composing".

+0

Можете ли вы показать несколько примеров, где макросы идеальны, а функций нет? – Rengraz

+1

Очень интересный и замечательный ответ! –

3

Макросы, безусловно, полезны в «типичном развитии», потому что, когда все сделано хорошо, они значительно облегчают задачи развития во многих отношениях. Например, подумайте о большом количестве сайтов, написанных на Clojure, используя замечательный макрос defroutes от Compojure. Или в самой библиотеке Clojure.core, все полезные макросы, такие как when или if-let, или очень широко используемая библиотека core.async. Все они являются макросами и значительно позволяют разработчику делать то, что в противном случае не так просто без них.

Что касается создания собственного приложения с макросами или без них, в общем, их следует избегать, пока у вас не будет выбора, кроме как использовать их. Два наиболее распространенных сценария, которые возникают для меня, когда я обратился к макросу:

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

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

Смежные вопросы