Сделайте макросы, и функции интегрируются больше беспрепятственно

Хорошо, я понимаю вполне прилично, как использовать и функцию и макросы.

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

(defmacro wonky-add [a b] `(+ ~a (* 2 ~b)))

(defn wonky-increment [a] (apply wonky-add a 1))
=> Error: can't take value of a macro

Да, я знаю, что могу сделать эту работу путем вынимания "применения" - но почему случается так, что компилятор не может выяснить, как сделать это само?

Это было бы возможно в Clojure / другой LISP для создания версии применяется или другие функции высшего порядка, которые работают одинаково хорошо с обеими функциями и макросами как параметры?

6
задан mikera 2 July 2010 в 11:52
поделиться

2 ответа

Этот ответ касается не столько Clojure, сколько Lisp и макросов в целом.

Помните:

APPLY позволяет вызывать функции со списками аргументов, которые создаются во время выполнения.

Макросы нужны для генерации нового исходного кода из некоторого исходного кода - и сгенерированный исходный код будет запущен.

Теперь:

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

Таким образом, в скомпилированной системе Lisp каждый вызов APPLY с макросом потенциально создает новый код, который необходимо скомпилировать во время выполнения, чтобы иметь возможность его выполнить. Это также означает, что вы можете получить новые ошибки компилятора во время выполнения, когда ваш код выполняется и в нем есть проблемы. Итак, чтобы ПРИМЕНИТЬ макросы во время выполнения, вам понадобится компилятор и вся необходимая информация (например, другие макросы), чтобы иметь возможность расширять и компилировать код.

Это также означает, что в общем случае вы не можете скомпилировать APPLY с макросом до выполнения, поскольку неизвестно, какие аргументы среды выполнения будут применяться.

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

В раннем Лиспе были нормальные функции и так называемые FEXPR. FEXPR позволяли гибко вызывать и манипулировать кодом во время выполнения. Позже в истории Lisp они были заменены макросами, поскольку макросы обеспечивают эффективную компиляцию, а в системах на основе компилятора позволяют обрабатывать синтаксические ошибки до выполнения.

11
ответ дан 8 December 2019 в 18:32
поделиться

То, что вы описываете, похоже на первоклассный макрос (т.е. макрос, которым можно управлять как функцией). У некоторых шепелявых они есть (например, Arc ), но apply , поскольку он сам не является макросом, вероятно, все равно не будет работать.

2
ответ дан 8 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: