簡體   English   中英

clojure 如何綁定可變參數?

[英]How does clojure bind variable parameters?

我是 Clojure 的新手。問題出在我曾經檢查過conj的源代碼時:

    (def conj 
      (fn ^:static conj
        ([] [])
        ([coll] coll)
        ([coll x] (clojure.lang.RT/conj coll x));4
        ([coll x & xs] ;1
         (if xs ;2
           (recur (clojure.lang.RT/conj coll x) (first xs) (next xs)) ;3
           (clojure.lang.RT/conj coll x)))))

conj的源代碼顯示,它使用 recur 來實現該功能。 這個源代碼看起來很簡單。 我感到困惑的是它在確定遞歸是否需要繼續時使用的條件。 看起來它會檢查變量參數是否為nil ,但如果變量參數為nil ,它很快就相當於conj的第三個“arity”? 然后我嘗試評估以下表達式:

user=> (conj [] 1 (next []))
[1 nil]
user=>

它正常工作並成功地將nil添加到向量中。 我知道 clojure 實際上將nil包裝在一個列表中並將其傳遞給函數,但我不明白為什么recur可以傳遞一個真正的nil 為什么 clojure 會識別並匹配正確的“arity”?


user=> (def my_conj
   (fn [coll x & xs]
     (println "xs is" xs)
     (if xs
       (recur (clojure.lang.RT/conj coll x) (first xs) (next xs))
       (clojure.lang.RT/conj coll x))))
#'user/my_conj
user=> (my_conj [] 1 (next []))
xs is (nil)
xs is nil
[1 nil]

好的,我很抱歉沒有早點意識到您遇到了我以前從未見過的 Clojure 行為的一個方面。 今天我學到了一些關於 Clojure 的新知識,並在 10 年的時間里使用它,這讓我感到驚訝。

這在 Clojure 官方文檔的幾句話中提到了 recur,這里: https : //clojure.org/reference/special_forms#recur

這是一個社區編寫的示例和文檔(因此不是“官方”)頁面,它描述了具有可變參數的函數的 recur 行為: https : //clojuredocs.org/clojure.core/recur#example-55ff3cd4e4b08e404b6c1c7f

我建議復制此函數,將其名稱更改為其他名稱,並向println添加一些您感興趣的值的調用,例如 x、xs 等,然后觀察在 Clojure REPL 會話中打印的內容使用您感興趣的不同參數調用您的函數。

if xs如果值為true xs是比所有其他的任何值nilfalse (nil)是一個元素的列表,當用作if條件表達式時被認為是 true。

用參數聲明的函數部分[coll x & xs]表示“將第一個參數的值綁定到coll,將第二個參數的值綁定到x,然后如果沒有更多參數,則將xs綁定到值nil ,否則將 xs 與作為剩余參數列表的值綁定”。

您可以使用這個根本不使用 recur 的更簡單的函數來看到這一點:

user=> (defn my-fn [a & xs]
         (println "a=" a " xs=" xs))

user=> (my-fn 1)
a= 1  xs= nil

user=> (my-fn 1 2)
a= 1  xs= (2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM