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

欢迎!请查看关于页面以了解更多关于如何工作的信息。

0
语法和reader

当前规范禁止包含多个斜线的关键词和符号,但读取器允许。
此微小的补丁使读者也无法读取它们。

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

user=> :foo/bar/baz RuntimeException Invalid token: :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_ 提出

请考虑以下原因重新考虑此“修复”

- 为了一致性,需要修复 (keyword "foo/bar/baz")
- 它将破坏我的代码的用户
   - http://docs.caudate.me/adi/adi-guide.html
   - http://docs.caudate.me/adi/adi-walkthrough.html#schoolyard

请参见下面对该主题的讨论


dm3 [5:04 PM]
为什么 `(read-string "a/b/c")` 可以正常工作,而用 `(clojure.tools.reader/read-string "a/b/c")` 就会报错“无效令牌”?

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 会报错并抛出“无效令牌”异常。以下代码展示了此问题 - ;;; 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]
如果文档明确指出“你可以在一个符号中使用 *一个* `/`”,那么如果你使用超过一个,你写的Clojure是不正确的,你应该预期它可能会出错(编辑过)

dm3 [下午5:47]
在使用Clojure的三四年间,我真的没有考虑过在符号中使用多斜杠(也没有注意到文档)

[5:47]
今天我最初的思考是它应该是允许的

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

bronsa [下午5:51]
但是,这并没有太多意义。在Clojure中,`/`是命名空间分隔符。无论`FOO`和`BAR`是什么,如果我看到`FOO/BAR`,我就知道`FOO`是命名空间,`BAR`是名称。如果你想在关键字中使用路径,就像@zcaudate的lib中所做的那样,你应该在关键字中使用一个没有特殊意义的分隔符,比如`.`(例如`:foo/bar/baz` -> `:foo.bar.baz`或`:foo/bar.baz`)(编辑过)

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

bronsa [下午5:52]
我的观点是,只有在语义明确和没有歧义的情况下,才应该考虑现实主义的观点(尤其是当它们与当前文档相悖时)

sveri [下午5:53]
@bronsa:很好的解释,谢谢你:笑脸

dm3 [下午5:53]
是的:笑脸

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


zcaudate [晚上9:07]
@bronsa:书面形式的交流有时会让人感觉事情比实际严重

[9:08]
说实话……我从1.6版开始就知道会有这种情况,因为edn reader开始破坏我的代码

[9:09]
可能是我没有早点沟通的错,但……我们都要顺应时代的发展

bronsa [晚上9:09]
@zcaudate:没问题,我只是因为你提到了你的库,所以用了你的库作为例子

zcaudate [晚上9: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 [晚上9:12]
@zcaudate:你发布的质量内容很多,我怀疑你从不睡觉!
1  

bronsa [晚上9:12]
@zcaudate:幸运的是,修复应该很简单:笑脸:只需将`/`换成`.`即可

zcaudate [晚上9:12]
不!

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

[9:13]
所以我必须做cljs的事情`account.type$user`

bronsa [晚上9:13]
(顺便说一下,这是高质量的文档,做得很好)

zcaudate [晚上9: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 [晚上9:17]
@zcaudate:对不起如果不是很清楚,但事实上我没有控制Clojure或者里面有什么,我只是个贡献者:笑脸:所以clojure/core团队可能会做出不同的决定,并实际上拒绝那个条目(如果真的是那样的话,我会非常失望的!)如果那样的话,我会明显地改变`tools.reader`,允许它们作为同样,(编辑过)

zcaudate [晚上9: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
通过

评论者:alexmiller

Chris -

  • (keyword "foo/bar/baz")仍然会很好。可以为任何字符串创建程序性关键字 - 这比读者支持的代码中的字面值要广泛得多,这是一个广泛使用的功能。在未来某个时刻,可能有对符号或关键字进行转义的机制,以便读者也能读取它们,但这超出了此处的范围。
  • 你的API使用的是非法关键字,根据https://clojure.org/reference/reader,你不能期望它们会工作。我认为你应该更改你的库。
0
通过

评论者:zcaudate

Alex

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

评论者:alexmiller

阅读页明确指出"\"/\"具有特殊含义,它可以在符号中间被一次使用,用以分隔命名空间和名称",“关键字”就像“符号”。这一说法从我在互联网档案馆找到的最古老版本(2008年7月)以来,一直出现在阅读页上。edn(尽管与Clojure类似)是另一回事,与Clojure无关。

{{keyword}}的2参数形式可以模糊不清地使用:{{(keyword nil "foo/bar/baz")}}。1参数形式将根据第一个"/"进行分割(在这个例子中是"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显示,否则不清楚命名空间在哪里,如果输出无法作为数据读取回,那么code is data的概念将会削弱。

还有关于符号的情况
user=> (symbol "foo/bar/baz")
foo/bar/baz

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

不管怎样,即使文档没有明确指出,:foo/bar/baz自从Clojure开始以来就存在了,个人感觉它更像字符串而不是符号。讽刺的是,我相当确信我是从开始做adi工作时阅读datomic文档得到在关键字中使用多个斜杠的灵感。

最终,这并不是我作决定的事情,我确实尊重Clojure团队在语言发展方面的指导。然而,我确实希望我的保持现状的观点能被认识和考虑。

0

评论者:zcaudate

我引用Rich在https://www.youtube.com/watch?v=P76Vbsk_3J0 @ 5:10的言论

"你认为多数是问题的东西(在Lisp中)是特性……最终……”

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