我正在寻找类似doto但不是返回的东西x,我想返回最后一个调用值.
例如,而不是:
(.size (doto (java.util.ArrayList.)
(.add 2)
(.add 3)))
Run Code Online (Sandbox Code Playgroud)
我想写:
(mydoto (java.util.ArrayList.)
(.add 2)
(.add 3)
.size)
Run Code Online (Sandbox Code Playgroud)
实现这一结果的惯用方法是什么?
Leo*_*hin 11
doto返回它的第一个参数.->并->>返回评估最后一个表单的结果(在线程化第一个表达式之后,请参阅(clojure.repl/doc ->).宏doto将扩展您的代码,如下所示:
(let [r (java.util.ArrayList.)]
(.add r 2)
(.add r 3)
r)
Run Code Online (Sandbox Code Playgroud)
在使用时.size,它不会影响您的数组列表,您只对该方法的返回值感兴趣(与使用.add它返回一个布尔值并更改您感兴趣的ArrayList的状态不同).
你不能像mydoto那样混合这些方法,因为你需要的是不同类型的返回值和输入值.如果你想将最终大小乘以3,这将是惯用的:
(-> (doto (java.util.ArrayList.)
(.add 2)
(.add 3))
.size
(* 3))
Run Code Online (Sandbox Code Playgroud)
甚至
(-> (java.util.ArrayList.)
(doto (.add 2) (.add 3))
.size
(* 3))
Run Code Online (Sandbox Code Playgroud)
这些宏应该使代码更容易阅读,因此根据上下文我会以最有意义的方式编写它们.
Clojure 宏将允许您做您想做的事情,事实上,它只是对现有 doto 宏进行 1 个符号更改(在 emacs 中使用 Meta-. 查看 core.clj 中的定义)。
(defmacro mydoto
"Like doto but returns the result of the last form
instead to the first argument"
[x & forms]
(let [gx (gensym)]
`(let [~gx ~x]
~@(map (fn [f]
(if (seq? f)
`(~(first f) ~gx ~@(next f))
`(~f ~gx)))
forms))))
Run Code Online (Sandbox Code Playgroud)
这将允许您编写以下代码:
(mydoto (java.util.ArrayList.)
(.add 2)
(.add 3)
.size)
;; => 2
Run Code Online (Sandbox Code Playgroud)