Каковы правила разрешения символов как макросов по сравнению с параметрами функции?
Я был удивлен, обнаружив, что альфа-преобразование небезопасно в Clojure:
Clojure> ((fn [o] (o 3 2)) +)
5
Clojure> ((fn [or] (or 3 2)) +)
3
Clojure> ((fn [def] (def 3 2)) +)
java.lang.RuntimeException: First argument to def must be a Symbol
(Я ожидал, что все три фрагмента оцениваются в 5).
Каковы правила для разрешения символов при теневом копировании, макросах и специальных формах?
Я использую версию на Try Clojure.
2 ответа
Вы не можете скрывать специальные формы, согласно документации:
Символ разрешен:
- Если он квалифицирован пространством имен, значение является значением привязки глобальной переменной, названной символом. Это ошибка, если не существует глобальной переменной, названной символом, или если ссылка на непубличную переменную в другом пространстве имен.
- Если он квалифицирован пакетом, значением является класс Java, названный символом. Это ошибка, если нет класса, названного символом.
- ** Иначе, он не квалифицирован и применяется первое из следующего:
- Если он называет специальную форму, он считается специальной формой и должен использоваться соответствующим образом.**
- В текущем пространстве имен выполняется поиск, чтобы увидеть, существует ли сопоставление символа с классом. Если это так, считается, что символ называет объект класса Java. Обратите внимание, что имена классов обычно обозначают объекты классов, но обрабатываются специально в определенных специальных формах, например, '.' и новый.
- Если в локальной области (то есть в определении функции), поиск выполняется, чтобы увидеть, называет ли он локальную привязку (например, аргумент функции или имя с привязкой к имени). Если это так, значение является значением локальной привязки.
- В текущем пространстве имен выполняется поиск, чтобы увидеть, существует ли отображение символа на переменную. Если это так, значение является значением привязки переменной, на которую ссылается символ.
- Это ошибка.
И я не уверен, но я интерпретирую этот отрывок (с той же страницы) как означающий, что вы также не можете скрывать макросы:
Макросы - это функции, которые манипулируют формами, позволяя использовать синтаксическую абстракцию. Если оператор вызова является символом, который называет глобальную переменную, которая является макро-функцией, эта макро-функция вызывается и передается неоцененным формам операндов. Возвращаемое значение макроса затем оценивается на его месте.
Если оператор не является специальной формой или макросом, вызов считается вызовом функции.
Первые два для меня оцениваются в 5 (Clojure 1.4 в Eclipse / против часовой стрелки REPL). Я подозреваю, что есть ошибка в Try Clojure, если вы получаете 3.
Вы должны иметь возможность локально скрывать как имена функций, так и макросы (хотя это часто не очень хорошая идея, поскольку это может привести к некоторым тонким и запутанным ошибкам!).
Третий не будет работать, потому что def
это особая форма. Специальные формы получают специальную обработку от читателя Clojure и / или компилятора, поэтому вы не можете их скрывать.