Загадка Clojure: eval, макросы и пространства имен - PullRequest
1 голос
/ 07 февраля 2012

В clojure, макросы дают огромные возможности программисту.eval также очень мощный.Существуют некоторые тонкие различия между ними.Я надеюсь, что эта загадка осветит эту тему.

(ns hello)
(defmacro my-eval [x] `~(read-string x))
(defn hello[] "Hello")
(defn run-stuff []
  (println (hello))
  (println (my-eval "(hello)"))
  (println (eval (read-string "(hello)"))))
(ns main)
(try (hello/run-stuff)
  (catch Exception e (println e)))

Над тремя утверждениями внутри run-stuff тела, которое вызывает исключение, а другие нет?

Я сформулировал следующую загадку после исследования этого прекрасного вопроса Clojure - (функция чтения строки String . Спасибо @Matthias Benkard за разъяснения

1 Ответ

4 голосов
/ 07 февраля 2012

(println (hello)) и (println (my-eval "(hello)")) - полностью идентичные утверждения - единственное отличие состоит в том, что вы еще больше запутаете ваш редактор. my-eval НЕ сопоставимо с реальным eval. Разница в том, что аргумент my-eval должен быть строкой во время компиляции - следующие ошибки, потому что символ x не может быть приведен к строке.

(def x "(hello)")
(my-eval x)

Это делает my-eval совершенно бессмысленным - вы можете "вычислить" буквальную строку или вы можете удалить кавычки и my-eval и иметь одинаково функциональный код (который ваш редактор поймет).

Real eval, с другой стороны, пытается скомпилировать код во время выполнения. Здесь он завершается неудачно, потому что он запускается из пространства имен main, а не из пространства hello, как указал @Matthias Benkard.

...