将变量列表逐个传递给Clojure函数

4

我一直在研究Clojure,决定构建一个高阶函数,将mapcat和list组合使用以模拟这种行为:

Clojure> (mapcat list '(1 2 3 4) '(5 6 7 8))
(1 5 2 6 3 7 4 8)

我的第一次尝试是将mapcatList定义为以下内容:

Clojure> (defn mapcatList[& more](mapcat list more))
#'sandbox99/mapcatList
Clojure> (mapcatList '(1 2 3 4) '(5 6 7 8))
((1 2 3 4) (5 6 7 8))

显然,这个函数的行为不符合我的期望,我认为原因是两个列表被放入一个列表中并作为单个参数传递,而不是分成两个。我可以通过以下方法解决这个问题,

Clojure> (defn mapcatList[x y & more](mapcat list x y))
#'sandbox99/mapcatList
Clojure> (mapcatList '(1 2 3 4) '(5 6 7 8))
(1 5 2 6 3 7 4 8)

这个方案适用于两个列表,但我希望这个函数能够处理可变数量的参数。
我的问题是:如何将可变数量的参数传递给一个函数,然后解构它们,使它们作为单独的参数一起传递给'mapcat list'呢?

(defn mapcatList[& more](apply mapcat list more)) (defn mapcatList[& more](apply mapcat list more)) - vedang
2个回答

14
你正在寻找 apply 函数。它以序列的形式调用一个函数并传递参数。 但你是否知道有一个名为 interleave 的函数可以完全实现你的 mapcatList 尝试做的事情?

是的,我是。这整个事情是在我尝试自己实现交错之后开始的。谢谢。 - wespiserA

5

你说得对,由于变量参数声明的存在,参数被封装在列表中。需要使用apply方法按顺序提取参数并解包成单个元素:

(defn mapcatList[& more]
  (apply mapcat list more))

user=> (mapcatList '(1 2 3 4) '(5 6 7 8))               
(1 5 2 6 3 7 4 8)
user=> (mapcatList '(1 2 3 4) '(5 6 7 8) '(\a \b \c \d))
(1 5 \a 2 6 \b 3 7 \c 4 8 \d)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接