好吧,我不知道你可以使用什么内置的东西(除了let
你不想要的)。但美妙之处在于您可以自己构建它。
一个想法是创建一个 "new" defn
,其中:return
表达式左侧的关键字表示从该表达式返回值,而不是最后一个表达式。宏在这里是合适的,因为我们将构建一个修改后的(defn ...)
表达式,这需要未计算的代码。
(defmacro defn-return-middle
[nm arg-vec & body-exprs]
`(defn ~nm ~arg-vec
~(if (some #{:return} body-exprs)
(let [[before _ [to-be-returned & after]]
(partition-by #{:return} body-exprs)]
`(let [ret# (do ~@before ~to-be-returned)]
~@after
ret#))
body-exprs)))
这扩展了以下内容:
(defn-return-middle f []
a
:return b
c)
类似于:
(defn f []
(let [ret (do a b)]
c
ret))
例如,您现在可以执行以下操作:
(defn-return-middle blah [a]
(+ 1 a)
:return (+ 2 a)
(println "does this work?"))
现在在 REPL 中:
user> (blah 5)
does this work?
=>7
(耶!)
或者对于您的示例,您现在将执行以下操作:
(defn-return-middle test1
[]
(start-server)
:return (run-pvt-and-expect "PVT-0")
(stop-server))
诚然,宏使用let
,但let
如果您每次都手写它,它会自动进行扩展。这意味着现在,当使用此宏时,您将不再手写let
. 此外,此宏目前不适用于声明多个参数的函数定义。但是修改它以使其也适用于那些也不会太难。