我對Clojure/Lisp宏不是很熟悉。我想編寫apply-recur
宏這將具有相同含義(apply recur ...)
在Clojure中應用復現宏
我想有這樣的宏沒有真正的需要,但我認爲這是一個很好的鍛鍊。所以我要求你的解決方案。
我對Clojure/Lisp宏不是很熟悉。我想編寫apply-recur
宏這將具有相同含義(apply recur ...)
在Clojure中應用復現宏
我想有這樣的宏沒有真正的需要,但我認爲這是一個很好的鍛鍊。所以我要求你的解決方案。
嘛,實在是沒有必要的,如果僅僅是因爲recur
不能把可變參數(一recur
到函數的頂部需要一個最終seqable說法把所有參數傳遞需要的最後一個參數)。當然,這並不影響練習的有效性。
然而,存在這樣一個「適當」 apply-recur
應該大概是處理由任意表達式返回參數seqs和不僅字面一個問題:
;; this should work...
(apply-recur [1 2 3])
;; ...and this should have the same effect...
(apply-recur (vector 1 2 3))
;; ...as should this, if (foo) returns [1 2 3]
(apply-recur (foo))
然而,任意的表達式的值如(foo)
是一般來說,在宏觀擴張時間根本不可用。 (也許(vector 1 2 3)
可能被認爲始終產生相同的值,但foo
可能意味着不同的事情在不同的時間(原因eval
不會工作),是let
- 綁定本地而不是Var(另一個原因eval
不會工作)等)
這樣寫完全通用apply-recur
,我們需要能夠確定有多少論點經常recur
形式的期望,並有(apply-recur some-expression)
擴展到像
(let [seval# some-expression]
(recur (nth seval# 0)
(nth seval# 1)
...
(nth seval# n-1))) ; n-1 being the number of the final parameter
(最終nth
可能需要爲nthnext
如果我們正在處理可變參數,這會帶來類似於下一段中所述的問題。另外,最好添加一個斷言來檢查some-expression
返回的seqable的長度。)
我不知道任何方法來確定在代碼中的特定位置的recur
的適當元數在宏觀擴張時期。這並不意味着它不可用 - 這是編譯器無論如何需要知道的東西,所以也許有一種方法可以從內部提取這些信息。即便如此,任何這樣做的方法幾乎肯定需要依賴於未來可能會改變的實現細節。
因此,結論是:即使完全可以寫這樣一個宏(甚至可能不是這種情況),任何實現都可能非常脆弱。
作爲最後的一句話,寫一個apply-recur
這隻會有能力處理文字的(實際上是ARG序列的總體結構將需要給出一個文字;參數本身 - 不一定,所以這可以工作:(apply-recur [foo bar baz])
=>(recur foo bar baz)
)將會非常簡單。我不會通過放棄解決方案來破壞練習,但作爲提示,請考慮使用[email protected]
。
apply
是將另一個函數作爲參數的函數。 recur
是一種特殊的形式,不是函數,所以不能傳遞給apply
。
當然,雖然我把這個問題的意思是「假定一個人不能只寫」(應用重複...),那麼如何編寫一個能夠捕捉這個意圖的宏呢?「 – 2010-09-08 18:15:07
是的,我的意思是這樣,謝謝你們。 – JoeCamel 2010-09-08 18:23:09