我知道在Java中,如果我将一个对象作为参数传递给一个方法,那么该方法将让参数变量指向同一个对象而不是重复。在Clojure怎么样?例如:
(defn print-from-reader [rdr]
(print (.read rdr)))
(...inside some code...
(with-open [rdr (Reader file)]
(print-from-rader rdr)))
当传入rdr时,print-from-reader是否会在内存中创建另一个rdr副本,或者它指向已经通过with-open binding创建的相同rdr?
有没有办法检查两个clojure实例是否指向同一个内存?
抱歉我的错误用语如“指向”和“实例”,我是Clojure的新手并且还在学习它。 : - )
答案 0 :(得分:5)
根据对this question on google groups的回答,它是按值传递的。
Clojure继承了Java中的参数传递语义。所以它是pass-by-value,其中传递的值是对象引用。此外,还有一些优化工具可以传递原始类型的值。
因此,在传递参数时,函数不会复制。您代码中的rdr
将是同一个实例。
由于java互操作性而有意义地实现它 - 否则你不能(轻松地)用它的方法修改java对象的状态。
您可以轻松测试:
(import 'java.util.HashMap)
(def m (new HashMap))
(defn foo [m] (defn bar [m] (.put m "testkey" "testvalue")) (bar m) (println (get m "testkey")))
(foo m)
结果:
testvalue
nil
如果bar
创建了自己的m
副本,则println
将无法打印bar
内分配的值。
答案 1 :(得分:5)
Clojure就像Java一样是按值传递的。我认为它是,引用是通过值传递的。 Clojure不像这样工作,Scheme和Common Lisp的行为方式相同。
您可以使用identical?
测试两个引用是否指向同一个内存:
(相同?x y)
测试2个参数是否是同一个对象