那麼,我知道你可以使用任何內置的東西(除了你不想要的let
以外)。但美麗的是,你可以自己建造它。
一個想法是創建一個「新」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 [email protected] ~to-be-returned)]
[email protected]
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
。此外,此宏目前不在聲明多個arities的函數定義上工作。但修改它以適應這些問題也不會太困難。
你能解釋一下「功能性」是什麼意思嗎?對我來說,沒有任何關於'let'的非函數,但是你的例子中的其他語句都是*無功能的。 –