在clojure中,如何调用x的所有方法,然后返回最后一次表单执行的值?
我正在寻找类似于在clojure中,如何调用x的所有方法,然后返回最后一次表单执行的值?,clojure,Clojure,我正在寻找类似于doto的内容,但我希望返回上次调用的值,而不是返回x 例如,而不是: (.size (doto (java.util.ArrayList.) (.add 2) (.add 3))) 我想写: (mydoto (java.util.ArrayList.) (.add 2) (.add 3) .size) 实现此结果的惯用方法是什么?doto返回
doto
的内容,但我希望返回上次调用的值,而不是返回x
例如,而不是:
(.size (doto (java.util.ArrayList.)
(.add 2)
(.add 3)))
我想写:
(mydoto (java.util.ArrayList.)
(.add 2)
(.add 3)
.size)
实现此结果的惯用方法是什么?
doto
返回它的第一个参数->
和->
返回计算最后一个表单的结果(在遍历第一个表达式后,请参见(clojure.repl/doc->)
。宏doto
将按如下方式展开代码:
(let [r (java.util.ArrayList.)]
(.add r 2)
(.add r 3)
r)
当您使用.size
时,它不会影响数组列表,您只对方法的返回值感兴趣(与.add
不同,后者返回布尔值并更改您感兴趣的ArrayList的状态)
您不能像在mydoto中那样混合使用这些方法,因为您需要的是不同类型的返回值和输入值。如果您想将最终大小乘以3,这将是惯用的:
(-> (doto (java.util.ArrayList.)
(.add 2)
(.add 3))
.size
(* 3))
甚至
(-> (java.util.ArrayList.)
(doto (.add 2) (.add 3))
.size
(* 3))
这些宏应该使代码更易于阅读,因此根据上下文,我将以最有意义的方式编写它们。Clojure宏将允许您做您想做的事情,事实上,对现有的doto宏只需1个符号的更改(在emacs中使用Meta-。查看core.clj中的定义) 这将允许您编写以下代码:
(mydoto (java.util.ArrayList.)
(.add 2)
(.add 3)
.size)
;; => 2
可以使用
doto
编写mydoto
,如@lgrapenthin所述:
(defmacro mydoto
"Like doto but returns the result of the last form instead
of the first argument"
[& args]
`(-> (doto ~@(butlast args))
~(last args)))
非常好!谢谢@user499049编写这样的宏来实现OP想要的东西不是惯用的,只是混淆了他正在使用的源代码。它也可以用现有代码写成一行代码:(defmacro my doto[&args]`(->(doto~@(butlast args))~(last args))@lgrapenthin你应该自己写一个答案
(defmacro mydoto
"Like doto but returns the result of the last form instead
of the first argument"
[& args]
`(-> (doto ~@(butlast args))
~(last args)))