#clojure
#clojure
Вопрос:
Почему этот код работает?
(defn g []
do (println 10) (println 20))
Примечание: Нет ( перед do.
Ответ №1:
Теоретически это даже не должно компилироваться. Компилятор должен жаловаться, что do
не может быть разрешен, поскольку это специальный символ не в первой позиции формы.
Это (вероятно, непреднамеренное) следствие использования одного и того же кода синтаксического анализа BodyExpr как для do
специальной формы, так и для тела fn*
специальной формы. При компиляции do
специальной формы начальная do
отбрасывается, а остальные формы компилируются. Использование этого же синтаксического анализатора для тела функции означает, что один голый do
также может появиться первым.
public static class BodyExpr implements Expr, MaybePrimitiveExpr{
...
public Expr parse(C context, Object frms) {
ISeq forms = (ISeq) frms;
if(Util.equals(RT.first(forms), DO))
forms = RT.next(forms);
....
Вы заметите, что если do
повторяется, это
(defn g [] do do (println 10) (println 20))
;=> CompilerException java.lang.RuntimeException:
Unable to resolve symbol: do in this context ...
не компилируется, как ожидалось.
Комментарии:
1. Спасибо. Итак, в нем явно закодировано исключение. Есть идеи, почему?
2. @Tim Смотрите редактирование. Это следствие (вероятно, непреднамеренное) использования одного и того же синтаксического анализатора как для
do
специальной формы, так и для тела функции special form,fn*
.3. Как странно… Я бы ожидал чего-то вроде:
=> ((fn [] println println)) ;; #<core$println clojure.core$println@15d3b17>
, но это исключение, похоже, относится ко всем специальным формам.((fn [] if))
например, выдает тот же RTE.