按索引解构向量

3

我想知道是否有一种按索引解构向量的方式。基本上,这是一种简写方式,可以避免以下操作:

(defn f [v]
    (let [x (nth v 4)
          y (nth v 5)]
        (println x y)))

这是我的基本问题:
user=> (defn f [{x 4 y 5}] (println x y))
#'user/f
user=> (f [0 1 2 3 4 5 6])
4 5
nil
user=> (f (apply vector (range 10)))
4 5
nil
user=> (f (range 10))
5 nil
nil
user=>

你的问题在编辑后发生了相当大的变化。无论如何,(range 10)是一个惰性序列,因此不是可关联的,因此这样做不起作用。或者说,它的工作方式不同。有关更多详细信息,请参见我的答案评论。 - Michał Marczyk
所以,关于按索引解构向量的原始问题的答案是可以的;关于按索引解构序列的新问题的答案是不行的。 - Michał Marczyk
1个回答

8

关于解构向量的原始问题的答案:

向量是可以进行关联的,因此您可以使用关联解构:

(let [{x 4 y 5} [0 1 2 3 4 5 6]]
  [x y])
;= [4 5]

回应下面的评论,这适用于任何解构形式有效的地方,包括在fn参数列表中:

((fn [{x 4 y 5}] [x y]) [0 1 2 3 4 5 6])
;= [4 5]

关于解构序列的新问题的答案:

如果您将一个序列传递给上述定义的函数而不是向量,则会应用序列的关联解构规则。也就是说,序列首先会被转换为哈希映射 - 在此阶段,(range 10) 变成了 {0 1 2 3 4 5 6 7 8 9},然后这个哈希映射将被解构为一个映射。

没有通过索引解构序列的方法。这是有意设计的,因为序列不适用于需要快速随机访问的应用程序。


我希望在函数参数列表中使用解构赋值,这样就可以避免使用 let。 - Kevin
我在我的问题中添加了更多信息,这也是我提出问题的原因;也就是说,只有当参数是向量时它才有效。如果是列表,它突然就不起作用了。 - Kevin
毫不意外的是,列表不是关联的,而且映射解构对它们的操作方式也不同。具体来说,它们(以及其他序列类型)首先被倒入一个新的哈希映射中,然后在解构操作中使用。 - Michał Marczyk
这里的结果是,(range 10)首先被转换为{0 1 2 3 4 5 6 7 8 9},并且正是这个映射被后来解构。请注意,它没有一个键为55是键为4的值)。 - Michał Marczyk
你说得对,我想我抱怨的事情是,如果你不知道或者不能控制所有的调用者,那么通常没有简洁的方法使这个工作起来。 - Kevin
显示剩余2条评论

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