请在2024年Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解如何使用的更多信息。

0
语法和读取器
编辑

目前,Clojure 允许包含 &rest 参数的解构模式

user=> (let [[a b & c] (range 5)] [a b c])
[0 1 (2 3 4)]

Python 允许这样做,还将所谓的通配符放置在前面和中间位置(PEP 描述

>>> a, *b, c = range(5)
>>> a
0
>>> c
4
>>> b
[1, 2, 3]

对于 Clojure 是否考虑过类似的东西?可能看起来像这样

user=> (let [[a & b c] (range 5)] [a b c])
[0 (1 2 3) 4]

我觉得这可能可以通过处理核心函数的解构方式来实现,但我可能不知道一些细微之处。

1 答案

+1

选中
 
最佳答案

在什么情况下这会有用?


重新展示
其他使用序列解构的相同或类似场景
我有包含一系列数据的序列,并希望获取边界(例如,最早的和最新的)。我可以通过[f (first s),l (last s),r (next (butlast s))]不使用任何解构来完成此操作,但解构会使它更简洁。
我有一个后进先出队列,希望选择最后一个项目和倒数第二个项目来处理:[[& init second-item first-item]]

在这些场景中,自己构造所选项目是可以的,但使用Clojure的解构语法,也是一种很好且一致的方式来达到这一点,而不需要在let块中填充所有繁重的工作。

此外,将解构作为核心语法的一部分,它将可嵌套使用,并且所有性能改进都将自动由每个人感受到。
对于序列(可能未索引)输入,这类用例通常效率不高。目前在这些更广泛的应用场景中,通过s/conform和正则规范在spec中提供了对此类用例的支持。

在您提到的第二个案例中,我认为我们甚至不会想要支持或鼓励这样做——你只是在用这样的事物制造性能混乱。

虽然我偶尔见过对这样东西的需求,但它比当前支持的情况要少得多(且通常不妥当,会对性能产生影响),因此,我不确定有必要添加。
有道理,大致符合我预期的答案。你愿意查看带有性能比较的`destructure`补丁吗?
by
不是特别感兴趣。我认为你低估了假设在尾部位置使用剩余参数的数量以及进行此类变更所需付出的努力。再加上缺乏用例,这实在不值得花时间。
by
太好了,非常感谢。
by
@Noah 可以在库的宏中这样处理,几乎一样地对社区有好处,而不必干涉 clojure.core 的修补。语言小组虽然不热衷于将慢操作定为语法,但程序员也很重视在提高代码清晰度时使用解构。
by
@pbwolf 我也想过这个。也许我会试试看。

@alexmiller 想了一下,我对你说有很多地方假设剩余参数以及需要进行这种变更的努力感到有点困惑。问题是人们依赖 Clojure 读取器在剩余参数不在尾部位置时抛出错误吗?
如上所述,如果需要,spec 和 conform 已经能够处理这个问题。

(let [{:keys [a b c]} (s/conform (s/cat :a int? :b (s/* int?) :c int?) (range 5))] [a b c])

;;=> [0 [1 2 3] 4]
我在谈论 Clojure 实现中,有很多东西都假定了尾部有剩余参数。
啊哈,Clojure 实现内部。我以为这仅在 `destructure` 函数中处理。这更有意义。
...