在函数中定义的var仍然可以在clojure函数之外访问,为什么?

时间:2016-09-16 13:33:07

标签: clojure scheme

在Clojure REPL中:

user> (defn add [x y] (def foo :defined-inside) (+ x y))
#'user/add
user> foo
#object[clojure.lang.Var$Unbound 0x63a0ad69 "Unbound: #'user/foo"]
user> (add 1 1)
2
user> foo
:defined-inside

显然,我认为foo不应该在add之外访问,为什么Clojure允许这样做,这与其他lisp(例如。scheme)不同?

3 个答案:

答案 0 :(得分:2)

def在Clojure中总是全局的,与其他一些Lisps不同。

要在函数中创建局部符号绑定,请使用let

答案 1 :(得分:0)

在Clojure中,您可以使用let来定义本地易记:

(defn add [x y] 
  (let [foo :defined-inside] 
    (+ x y)))

它甚至可以用于本地功能:

(defn add [x y]
  (let [foo (fn [x y] (+ x y))]
    (foo x y)))

但是对于相互递归函数,您需要使用letfn

(defn is-odd? [n]
  (letfn [(is-even? [n]
            (if (zero? n)
                true
                (is-odd? (dec n))))
          (is-odd? [n]
            (if (zero? n)
                false
                (is-even? (dec n))))]
    (is-odd? n)))

答案 2 :(得分:0)

当我想通过调用函数在全局var lazily 中创建一个绑定时,函数内部的Def很有用。

(defn initialize-browser []
    (def browser (run-browser)))

例如,我使用此模式使用selenium运行浏览器。 我可以轻松控制浏览器的状态。 如果我不想运行浏览器,我不会调用该函数。当我想运行和处理浏览器时,我只调用此函数一次,并由其他函数处理。