Clojure: Как я могу связать переменную? - PullRequest
4 голосов
/ 26 марта 2011

У меня есть следующие определения в clojure:

(def ax '(fn x [] (+ 1 z)))

(let [z 4]
    (str (eval ax))
)

: но вместо возврата:

5

: Я получаю:

Unable to resolve symbol: z in this context 

: Iпытался изменить "пусть" на "связывание", но это все еще не работает.Кто-нибудь знает, что здесь не так?

Ответы [ 3 ]

11 голосов
/ 26 марта 2011

Внесение наименьшего возможного изменения в ваш код, чтобы заставить его работать:

(def ^:dynamic z nil)

(def ax '(fn x [] (+ 1 z)))

(binding [z 4]
    (str ((eval ax)))
)

Два изменения определяют z как динамическую переменную, так что имя разрешается, и ставят еще одну скобку (evalax), потому что ax возвращает функцию.

Немного приятнее изменить определение топора:

(def ^:dynamic z nil)

(def ax '(+ 1 z))

(binding [z 4]
    (str (eval ax))
)

Таким образом, оценка ax сразу же дает желаемый результат, а не возвращаетфункция, которая делает это.

Еще раз лучше пропустить eval:

(def ^:dynamic z nil)

(defn ax [] (+ 1 z))

(binding [z 5]
    (str (ax))
)

Но лучше всего не иметь z, плавающий как var, и передавать его в axкак предложили Мимсбрунн и Йост.

8 голосов
/ 26 марта 2011

Краткий ответ: не используйте eval. Тебе это почти никогда не нужно, и уж точно не здесь.

Например:

user> (defn ax [z]
         (+ 1 z))
#'user/ax
user> (let [f #(ax 4)]
         (f))
5
1 голос
/ 26 марта 2011

Правильно, поэтому я не совсем уверен, что вы пытаетесь сделать здесь.

Я имею в виду, что это работает, хотя он не использует eval, он определяет x как функцию (fn [ x ] (+ x 1))

> (def x #(+ 1 %))
#'sandbox102711/x
> (x 4)
5

В конце концов, eval - это не то, что вы должны использовать. Поскольку поддержка Lisp Cljoure для лямбда-абстракции и макросов (см. Определение fn выше) должна устранить необходимость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...