请在Clojure 2024 现状调查中分享您的想法!

欢迎!请访问关于页面获取更多关于如何使用本网站的信息。

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]

Closure 有类似考虑吗?可能看起来像这样

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))]等不需要解构就达到这个目的,但是解构让其看起来更美观。
我有一个后进先出(LIFO)队列,并想要选取最后一个和倒数第二个项进行处理:[[& init second-item first-item]]

在这些场景中,我们可以自己构建选定的项,但这也适用于Clojure所有的解构语法。使用解构语法是一种既优雅又一致的方式来完成这项工作,而不必在let块中填写所有繁重的操作。

此外,将它作为核心语法的一部分,它将可以嵌套使用,任何性能提升都将被自动感受到。
在给定的顺序(可能是非索引)输入中,这些类型的用例通常不是高效的。对于这些更广泛的应用场景,现在在spec(通过s/conform和正则表达式规范)中提供了对此类内容的支持。

在你提到的第二种情况下,我认为我们甚至不支持也不会鼓励这样做 - 你只是用这种方式制造了性能上的混乱。

虽然我偶尔看到对这类东西的需求,但它比目前支持的情况要少得多(并且常常对性能不佳),因此我不相信添加这一点是有意义的。
这个答案很有道理,基本上是我预期的答案。你愿意看一下补丁 `destructure` 并提供一些性能比较吗?
不是的,我不是特别感兴趣。我认为你低估了假设尾部位置参数的函数所在的位置数量,以及像这样进行更改所需的努力。这再加上缺乏用例,使得这项工作不值得花时间。
太好了,非常感谢。
@Noah 这可以作为库中的一个宏来实现,几乎可以带来相同程度的社区利益,而不必在修补 clojure.core 时陷入困境。尽管语言小队不倾向于将缓慢的操作嵌入语法中,但程序员也重视解构在提供清晰度的时候。
@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 实现中有很多假设尾部参数为 rest 参数的情况。
Ahhh,在 Clojure 实现内部。我以为这只是在 `destructure` 函数中处理的。这样更合理。
...