2024 Clojure状态调查!中分享你的看法。

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

0
语法和读取器

目前,规范不允许包含多个斜杠的关键字和符号,但读取器允许。
此简单补丁使它们对读取器来说也变得不可读。

前置

user=> :foo/bar/baz :foo/bar/baz

后置

user=> :foo/bar/baz RuntimeException 无效标记::foo/bar/baz clojure.lang.Util.runtimeException (Util.java:221)

9 个答案

0

评论由:jafingerhut

或许与CLJ-1527重叠?

0

评论由:zamaterian

请注意,包含多个斜杠的关键字在不同的 Clojure 版本(1.5 和 1.6)中具有不同的哈希代码。

当在 Clojure 1.6 下使用与 Clojure 1.5 兼容的 datomic 版本,且模式包含一个或多个包含多个斜杠的键时,这会产生问题。

0
_评论由:zcaudate_

请考虑以下原因重新考虑此修复方案

- (关键字 "foo/bar/baz")也需要为了保持一致性而修复
- 它将破坏我的代码的使用者
   - http://docs.caudate.me/adi/adi-guide.html
   - http://docs.caudate.me/adi/adi-walkthrough.html#schoolyard

请见下面此主题的讨论


dm3 [下午5:04]
为什么`(read-string "a/b/c")`可行,而`(clojure.tools.reader/read-string "a/b/c")`却因为`Invalid token`失败?

hiredman [5:04 PM]
已经有一个修复read-string的票

dm3 [5:05 PM]
那么行为应该失败吗?

hiredman [5:05 PM]
http://dev.clojure.org/jira/browse/CLJ-1530

dm3 [5:06 PM]
谢谢,看起来这是一个破坏性的变化 :simple_smile

hiredman [5:07 PM]
文档已经禁止使用像a/b/c这样的符号有一段时间了,而且显然在某个时期这种行为发生了变化

lucas [5:09 PM]
加入了#clojure

zcaudate [5:16 PM]
@hiredman:严重啊。我真的因为这个很生气,因为我已经使用`:a/b/c`关键字了一段时间……甚至还写了一个完全的库来处理这个问题http://docs.caudate.me/hara/hara-string.html#api---path (已编辑)

[5:16]
现在他们要移除它

[5:18]
我认为应该是先移除`::foo/baz`这样的关键字

[5:20]
 ```user=> (require '[clojure.walk :as walk])
nil
user=> ::walk/hello
:clojure.walk/hello
```

[5:20]
这会引发很多问题

[5:20]
特别是在分析器上

[5:22]
https://github.com/jonase/kibit/issues/14
 
GitHub
Kibit 在命名空间限定关键字上会中断 · Issue #14 · jonase/kibit · GitHub
如果代码中包含带有别名的命名空间限定关键字,Kibit会因为一个Invalid token异常而出错。以下代码演示了这个问题—— ;;; foo.clj (ns foo) ;;; bar.clj (n...

[5:25]
@dm3 如果确实有问题,你可以修复它

[5:25]
https://github.com/helpshift/hydrox/blob/master/lein/src/leiningen/hydrox/setup.clj
 
GitHub
helpshift/hydrox
hydrox - 更深入了解您的代码

dm3 [5:31 PM]
是的,遗憾地也要修复cljs.tools.reader :confused

[5:31]
我将对这个问题进行绕过处理

bronsa [5:36 PM]
@zcaudate:"::foo/bar"样式的关键字是按照设计保留的,不会移除,而`:foo/bar/baz`始终是无效的,根据规范是未定义的行为(已编辑)

[5:37]
@dm3:改变未定义的行为是破坏性行为吗? :simple_smile

dm3 [5:37 PM]
破坏性的,就是破坏人们的代码 :simple_smile

[5:37]
例如zcaudate

bronsa [5:38 PM]
如果有无效的Clojure语法,这样的代码已经是破损的,只是偶然能工作

dm3 [5:39 PM]
我从实用的角度来考虑。从理论上讲你是正确的 :simple_smile

[5:40]
我没有批判的意思

bronsa [5:40 PM]
实用上,`:foo/bar/baz`是一个等待发生的错误。 `(namespace :foo/bar/baz)`返回什么?

dm3 [5:40 PM]
目前返回什么都可以?

[5:41]
我的意思是这有点由实现来定义

sveri [5:41 PM]
@dm3 @bronsa 我甚至不同意你所提出的理论。一旦足够多的人适应了破损的代码,它就好像是双方共同接受的长期的惯例。

bronsa [5:42 PM]
那么`(keyword "foo/bar" "baz")`和`(keyword "foo" "bar/baz")`上的`namespace`如何?

dm3 [5:43 PM]
我同意当前的实现语义是很混乱的

[5:43]
但我的观点是,这仍然是一个破坏性改变

[5:43]
并不是说它是一个"坏"的改变

[5:43]
这是一个判断

bronsa [5:43 PM]
@sveri: 我会同意你的观点,只要我们接受的未定义行为不会导致无法修复的语义。

[5:44]
这就是为什么例如,使以数字开头的符号非法的修复被回滚

[5:45]
它破坏了现有的代码,但它没有导致奇怪的语义,所以被回滚了。 `:foo/bar/baz`的情况并非如此

[5:45]
@dm3:你可以说修复任何错误都是一种破坏性改变——人们可能依赖于那种错误。

dm3 [5:46 PM]
是的,我想重要的是错误的明显性和多少人依赖于它

bronsa [5:46 PM]
如果文档明确说明“在符号中可以使用*一个*/”,那么如果你使用了多个,你编写的Clojure代码是无效的,你应该预期它可能会出错(编辑)

dm3 [17:47]
在使用Clojure的三年多时间里,我甚至没有想过在符号中使用多个斜杠(也没有注意到文档)

[5:47]
我最初的想法(今天)是这是允许的

[5:47]
并且命名空间是第一个斜杠之前的第一个段(编辑)

bronsa [17:51]
嗯,这并没有什么意义。在Clojure中,“/”表示“命名空间分隔符”。无论如何,如果我看到“FOO/BAR”,我都会知道“FOO”是命名空间,“BAR”是名称。如果你想在关键字中表达路径,就像@zcaudate的库中那样,你应该在一个没有特殊意义的clojure中不同的分隔符,比如“.”(即“:foo/bar/baz” -> “:foo.bar.baz”或“:foo/bar.baz”)(编辑)

dm3 [17:51]
我不想争辩语义。我只是分享一个观点

bronsa [17:52]
我的观点是,只有当它们隐含的语义清晰且无歧义时,才应该考虑这些实用主义观点(尤其是当它们与当前文档相矛盾时)

sveri [17:53]
@bronsa:很好的解释,谢谢:simple_smile

dm3 [17:53]
yep:simple_smile

[5:54]
我同意这个观点,因为最终你必须做出决定


zcaudate [21:07]
@bronsa:书面形式的交流有时会让事情看起来比实际上更严重

[9:08]
说实话……我从1.6版本开始就知道会是这样,因为edn读取器开始破坏我的代码

[9:09]
这可能是我的错,我没有早点沟通,但这也没关系……我们都要适应时代的变化

bronsa [21:09]
@zcaudate:没关系,我之所以用你的库作为例子,是因为你提到了这一点

zcaudate [21:10]
但是,这么说吧,我失望的原因是因为我全部的设计都基于关键字`:foo/bar/baz`的功能(现在是错误)(编辑)

[9:11]
http://docs.caudate.me/adi/adi-walkthrough.html#querying

[9:11]
你注意到了在我的文档中没有使用`(adi/select ds {:student/classes/teacher/name "Mr. Blair"})`

[9:12]
,因为测试开始失败

jstew [21:12]
@zcaudate:你贡献了这么多高质量的内容,我想知道你是否睡觉!
1  

bronsa [21:12]
@zcaudate:幸运的是,修复应该很简单:simple_smile:只需将“/”换成“.”

zcaudate [21:12]
不!

[9:13]
问题是……datomic有像`account.type/user`这样的东西

[9:13]
所以我必须像clj的东西`account.type$user`

bronsa [21:13]
(顺便说一句,这确实是高质量的文档,做得好)

zcaudate [21:14]
@bronsa:哈哈,谢谢……所以也许你可以把修复推到1.10版本

[9:14]
这样我还能剩下几个月

[9:15]
就当这不是什么大问题……但我认为`/`调用路径的结构和映射的嵌套之间有一个平行关系

[9:16]
因此,它与`{:student {:classes {:teacher {:name '(?fulltext "Blair")}`

[9:17]
和`{:student/classes/teacher/name "Mr. Blair"}`

[9:17]
在观点上更漂亮

bronsa [21:17]
@zcaudate:对不起,如果这不是清晰的,但我实际上没有控制什么时候或什么进入Clojure,我只是一个贡献者:simple_smile:所以clojure/core团队可能会做出不同的决定,并实际上拒绝那个票(如果那样我会非常失望!)。  如果那样发生,我将显然将更改`tools.reader`以允许它们,(编辑)

zcaudate [21:18]
@bronsa: 糟糕。

[9:19]
好吧……也许你可以突出这个事实

[9:19]
并且如果进行了修复,还需要为 `(keyword "foo/bar/baz")` 制作修复(已编辑)

bronsa [晚上9:20]
我不认为这会完成。针对 `keyword`/`symbol` 等的输入验证已经询问/讨论了很多次,但出于性能原因被反复拒绝

zcaudate [晚上9:20]
因此这是一致性问题。

bronsa [晚上9:20]
(虽然我不赞同这个决定,但看起来Rich不会在这个问题上改变主意)

[9:21]
@zcaudate:在运行时一个符号/关键字能是什么,和有效的读取时符号/关键字是什么是不同的

zcaudate [晚上9:21]
此外,这意味着我可以设置一个读取宏 #k foo/bar/baz 并得到相同的效果

[9:22]
虽然看起来很丑陋,但我相信它会工作

bronsa [晚上9:23]
但是关于 `namespace` 和 `name` 的歧义仍然存在,所以我不知道

[9:23]
@zcaudate:无论如何,如果 http://dev.clojure.org/jira/browse/CLJ-1530 被接受,那么 `:foo/bar/baz` 和 `foo/bar/baz` 都将不再有效

[9:24]
@zcaudate:顺便说一句,如果你强烈反对它,我建议你在那里的备注中记录你的问题

新消息
[9:25]
我 *怀疑* 响应将会是 "你应该使用在Clojure中没有特殊意义的分隔符",但我可能完全错了(我发现核心团队并不经常同意我的观点 :)),尤其是如果你指出你的库会中断。(已编辑)

zcaudate [晚上9:30]
@bronsa:谢谢提醒。我会留条注释,并为此祈祷bdfl
0
by

评论者:alexmiller

Chris -

  • (keyword "foo/bar/baz") 仍然可以正常使用。可以为任何字符串创建程序性关键字 - 这比读取器支持的代码字面量要广泛得多,这是一个广泛使用的特性。在未来某个时候,可能存在一种转义机制,用于在规范之外的字符的符号或关键字,以便读取器也能够读取它们,但这超出了本主题的范围。
  • 你的API使用的是非法关键字,根据 https://clojure.org/reference/reader,你不应该期望它们可以工作。我认为你应该更改你的库。
0
by

评论者:zcaudate

Alex

  • 我不会一定称之为 非法的,因为在edn.reader中的当前行为是在1.6版本中添加的,没有警告。
  • 此外,如果 (keyword "foo/bar/baz") 允许存在,那么仍将存在 @bronsa 指出的不确定的命名空间/名称问题。我主张一致性和:如果 :foo/bar/baz 在读取器中是非法的,那么它应该在所有地方都是非法的
  • 我的库应该没问题...但库的用户可能需要更改他们的查询
0

评论者:alexmiller

阅读页面明确指出"\/"有特殊含义,它可以用在符号中间一次,以从命名空间中区别名称"和关键词是“像符号一样”。这自从我可以检索到的网络档案馆(2008年7月)的最古老版本以来一直在阅读页面上。edn(尽管与其相似)与Clojure是不同的事物,并且不相关。

{{keyword}}的两参数形式可无歧义地使用:{{(keyword nil "foo/bar/baz")}}。一参数形式将基于找到的第一个\/分割(在此示例中分割为"foo"和"bar/baz")。我看不到需要改变的理由。

0

评论者:zcaudate

关于关键词中\/的“特殊性质”,我不同意,特别是如果它允许作为字符串。

这导致输出的不确定性问题。

user=> (keyword "foo" "bar/baz")
:foo/bar/baz

user=> (keyword nil "foo/bar/baz")
:foo/bar/baz

除非输出显示为:foo//bar/baz,否则不清楚命名空间在哪里,如果输出不能作为数据解析回,那么“代码是数据”的概念将会减弱。

也存在符号的情况。
user=> (symbol "foo/bar/baz")
foo/bar/baz

well... 至少列出的所有示例都是“非法”的。

无论如何,即使文档没有明确声明这一点,:foo/bar/baz 自从 Clojure 之初就已存在,并且对我来说,它似乎比符号更像字符串。讽刺的是,我非常确信我从当初开始我可以使用多个斜杠在关键词中获得了想法,当时我在阅读 adi 的文档。

最终,决定不是由我来做,我非常重视 Clojure 团队在这个语言发展过程中的指导。但我确实希望我的意见能被认为是维持现状的理由之一,并得到考虑。

0

评论者:zcaudate

Rich 在 https://www.youtube.com/watch?v=P76Vbsk_3J0 的5:10处引用

"许多你认为(在 lisp 中)是问题(的特点)... 后面..."

0
参考:https://clojure.atlassian.net/browse/CLJ-1530(由 bronsa 提出)
...