【问题标题】:How does argument passing work in Clojure?Clojure 中的参数传递是如何工作的?
【发布时间】:2013-08-24 00:04:45
【问题描述】:

我知道在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 绑定创建的同一个 rdr?

有没有办法检查两个 clojure 实例是否指向同一个内存?

很抱歉我的“指向”和“实例”等不好的术语,我是 Clojure 的新手,还在学习它。 :-)

【问题讨论】:

    标签: clojure


    【解决方案1】:

    根据对this question on google groups的回答,它是按值传递的。

    Clojure 继承了 Java 的参数传递语义。所以它是按值传递,其中传递的值是对象引用。此外,还有一些优化工具可以传递原始类型的值。

    所以函数在传递参数时不会进行复制。您代码中的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 中分配的值。

    【讨论】:

    • 也感谢您的回答! :-D
    【解决方案2】:

    Clojure 和 Java 一样是按值传递的。我认为它是按值传递的引用。 Clojure 像这样工作并不是一件容易的事,Scheme 和 Common Lisp 的行为方式相同。

    你可以用identical?测试两个引用是否指向同一个内存:

    (相同?x y)

    测试两个参数是否是同一个对象

    【讨论】:

    • (相同?)看起来很方便,现在我又学会了一个技巧! :-)
    猜你喜欢
    • 1970-01-01
    • 2011-05-22
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    相关资源
    最近更新 更多