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))],我可以做到这一点而无需任何解构,但解构让它更简洁。
我有一个后进先出(LIFO)队列,并想选择最后项目和倒数第二项目进行处理:[[& init second-item first-item]]

在这些场景中,可以自己构造所选择的项目,但使用Clojure的解构语法也无妨。使用解构语法是一种简洁一致的方式,无需在let块中填充所有繁琐的工作。

除此之外,将其作为核心语法的一部分,它就可以嵌套使用,并且任何性能提升都将自动由所有人感觉到。
针对序列(可能是非索引)的输入,这类场景通常效率不高。现在在spec(通过s/conform和正则规范)中已经提供了对此类更广泛场景的支持。

在你提到的第二种情况下,我们认为这并不是我们想要支持或鼓励的,你只是在通过这样的操作创建一个性能混乱。

虽然我偶尔看到需要这样的东西,但这种现象比现有支持的场景(通常对性能不利)要少得多,所以我并不认为添加它是合理的。
这个回答很有意义,大致上是我预期的。你愿意查看针对`destructure`的补丁,并附带一些性能比较吗?
不是真的感兴趣。我认为你低估了需要假定尾参数的函数数量以及进行此类更改所需的工作。加上缺乏用例,这使得这件事不值得花费时间。
太好了,非常感谢。
@Noah 这可以作为库中的一个宏来实现,几乎可以带来相同的社会利益,无需在clojure.core中进行修补。尽管语言小组不情愿在语法中永久确立缓慢操作,但程序员也重视解构在提供清晰度时所发挥的作用。
@pbwolf 我也想到了这个。也许我会试试。

@alexmiller 想了一下,我对你说有许多地方假定尾参数和所需的工作量有点困惑。问题是人们依赖Clojure阅读器在尾位置没有rest参数时引发错误吗?
如上所述,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参数的东西。
啊哈,在Clojure实现内部。我原以为这只在`destructure`函数中处理。这更有道理。
...