无需功能,也不要使用def
在函数中,除非你明确打算“创建和实习生全局变量”(中def
文档字符串)。合并地图可以使用merge
完成。
(doto (merge ms) (SomeJavaClass/someStaticVoidMethod "some" "other" "stuff"))
编辑:因为我的答案可能有关正确使用高清的误解(见狮子座流星雨的评论):在函数中使用清晰度是不是一个好主意。我引用了文档字符串来暗示使用def的全局效果,而这在你的函数中肯定是不希望的。
EDIT2:这里有一些关于上面一行的更多解释:doto总是返回它的第一个参数。如果它是可变的并且它之后的表达式将其修改为副作用,则返回修改后的版本。然而,如果你只是想调用一个静态方法(大概)有副作用而不修改第一个参数,那么使用doto是正确的,因为你可以依赖你的地图的不变性。
由于您在寻求一种通用的惯用方法,并希望在您的静态方法(或具有副作用的函数)不希望将期望的返回值作为第一个参数时解决类似问题,因此可以始终这样做:
(doto (merge ms) (#(SomeJavaClass/someStaticMethod "Some" "other" "stuff" %)))
现在,如果出于任何原因需要确保静态方法永远不会修改参数(如果它是一个可变的事情),使用let块没有帮助。这是因为在let-block中,你将一个符号绑定到可变的东西上,并且你不会从符号中得到它的旧值。您需要事先创建一个旧值的副本,通常通过调用它的构造函数并创建它的一个新实例。在REPL
例子:
(let [a (into-array [4 3 2 1]]
(java.util.Arrays/sort a)
a)
(first *1)
=> 1
;; now how to return the original thiing
(let [a (into-array [4 3 2 1])
a-copy (aclone a)]
(java.util.Arrays/sort a)
;; do some other ops on a, maybe invoke side-effects
a-copy)
(first *1)
=> 4
因此,如果首先让块产生你想要的结果,让块可以与多托这是一个帮助宏不会完全不是别的,创建替换让你阻止。
(doto (into-array [4 3 2 1]) java.util.Arrays/sort)
(first *1)
=> 1
(macroexpand '(doto (into-array [4 3 2 1]) java.util.Arrays/sort))
=> (let* [G__7326 (into-array [4 3 2 1])] (java.util.Arrays/sort G__7326) G__7326)
既然你不是“做什么”到您的合并地图,名称为“多托”可能有些误导,但希望我可以convice您保存的冗余几行代码。
IIRC函数中最后一行的评估结果是返回值。 – m0skit0
您应该**从不**在函数内部使用'def'。不仅因为你影响全局范围,而且因为Clojure在编译期间为'def'创建了变量 –
@ m0skit0它不是,因为void方法返回nil。 –