【问题标题】:Destructuring a variadic function with an as-binding: not possible?使用 as-binding 解构可变参数函数:不可能吗?
【发布时间】:2014-10-12 20:18:48
【问题描述】:

直到现在,我一直认为您可以在 let 绑定中执行的任何操作,都可以在 defn 表单的参数向量中执行。

但是,我刚刚注意到这一点——如果我使用 let 绑定来执行此操作,它会起作用:

(let [[x & more :as full-list] (range 10)]
  (println "x:" x) 
  (println "more:" more) 
  (println "full list:" full-list))

; x: 0 
; more: (1 2 3 4 5 6 7 8 9) 
; full list: (0 1 2 3 4 5 6 7 8 9)

但如果我尝试将其拉出到函数中,则会出现异常:

(defn foo [x & more :as full-list]
  (println "x:" x) 
  (println "more:" more) 
  (println "full list:" full-list))

; CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(/tmp/form-init615613631940782255.clj:1:1)

值得注意的是,这是可行的:

(defn foo [[x & more :as full-list]]
  (println "x:" x) 
  (println "more:" more) 
  (println "full list:" full-list))

但是我必须将参数作为集合传递,即(foo [1 2 3])

是否可以定义一个接受可变数量参数的函数,并将整个参数组绑定到一个局部变量,而无需在内部专门使用 let 绑定?你不能只做(defn foo [x & more :as full-list] ... 让我感到很奇怪,这有什么特殊原因导致这不起作用(或不应该)吗?

【问题讨论】:

  • +1 我自己最近遇到了这个问题,对此感到非常沮丧

标签: clojure destructuring


【解决方案1】:

如果您想要可变数量的参数,则缺少 &:

(defn foo [& [x & more :as full-list]]
  (println "x:" x) 
  (println "more:" more) 
  (println "full list:" full-list))

Clojure 参数定义只有一种特殊情况,即 & 字符,用于指示可变数量的参数。其余的都是简单的命名参数。

现在每个简单的参数都可以使用映射或列表语法进行解构。例如:

(defn foo [ x y ] ...)

可以像这样解构:

(defn foo [[x1 x2 & x-more :as x] {:keys [y1 y2 y3]}] ...)

所以我们说我们希望第一个参数是一个至少包含 2 个元素的列表,第二个参数是一个带有一些键的映射。请注意,这仍然是两个参数的 fn,并且 Clojure 不会强制 x 实际上至少有两个元素。如果 x 为空列表,则 x1 和 x2 将为 nil。

回到您的问题,如果您查看我的回答,您会发现我的 fn 有 0 个强制参数,参数数量可变,而您拥有的 fn 有 1 个强制参数,参数数量可变。我正在做的只是解构 var arg。

【讨论】:

  • 这行得通 - 谢谢!有趣的是,只有当您想使用 :as 表单时,您才必须添加第一个 &... 执行 (defn foo [x & more] ... 工作正常,但一旦添加 :as 部分,您必须添加初始& 以明确该函数是可变参数的。我想知道这是为什么?
  • 我已经用更长的解释更新了回复。让我知道现在是否更有意义
  • 这更清楚了,谢谢——我刚刚有一点“啊哈”的时刻。我猜let 的绑定工作方式与defn 的绑定工作方式之间的一个关键区别是let 期望至少有一个东西被绑定到一个局部变量,而一个函数可以取 0 个参数。考虑到这种差异,在绑定的前端需要一个额外的& 来表明该函数可能需要 0 个参数会更有意义。
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多