2024年度Clojure调查中分享您的想法!

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

0
语法和读取器

当前规范禁用包含多个斜杠的关键字和符号,但读取器允许它们。
这个微不足道的补丁使它们对读取器来说也变得不可读。

前置

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版本中具有不同的hashcode。

这会在使用与clojure 1.6兼容但与clojure 1.5digits的datomic版本时创建问题,并且模式中有一个或多个包含多个斜杠的键。

0
_评论由:_

请基于以下原因重新考虑这个“修复”

- 为了一致性,需要修复(keyword "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")` 会因为“无效的标记”失败呢?

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]
我在过去3年的Clojure使用过程中,甚至没有考虑过符号中的多个斜杠(也没有注意到文档)

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

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

bronsa [下午5:51]
但是,这并不合理。在Clojure中,`/`代表`命名空间分隔符`。无论`FOO`和`BAR`是什么,如果我看到`FOO/BAR`,我都知道`FOO`是命名空间,`BAR`是名称。如果您想像@zcaudate的库中使用关键字来表示路径,您应该在关键字中使用不同的分隔符,这样在Clojure中没有特殊意义,例如`.`(即`: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读取器开始使我的代码崩溃

[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 [21:18]
@bronsa: 该死的。

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

[9:19]
另外,如果做出了修复,还需要对 `(keyword "foo/bar/baz")` 做出修复(修改过)。

bronsa [21:20]
我认为这永远都不会做。曾经无数次有人请求/讨论过对 `keyword`/`symbol` 等进行输入验证,但由于性能原因而被反复拒绝。

zcaudate [21:20]
所以这是一个一致性的问题。

bronsa [21:20]
(虽然我不完全同意这个决定,但看样子 Rich 在这个问题上不会改变主意)

[9:21]
@zcaudate: 符号/关键字的运行时可能是什么,以及在有效读取时可能是什么,这两者之间有区别。

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

[9:22]
虽然它看起来很愚蠢,但我觉得它应该会工作

bronsa [21: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 [21:30]
@bronsa: 谢谢提醒。我会留言并祈求 bdfl
0

评论者:alexmiller

Chris -

  • (keyword "foo/bar/baz") 仍然可以。为任何字符串创建程序化关键字是可以的——这故意要宽于读者支持的代码中的字面量,这是一个被广泛使用的特性。在未来的某个时刻,可能会有一个对包含字符的符号或关键字进行转义的机制,以便读者可以读取它们,但这超出了此功能的范围。
  • 你的 API 正在使用非法关键字,根据 https://clojure.org/reference/reader,你不应该期望它们生效。我认为你应该修改你的库。
0

评论者:zcaudate

Alex

  • 我不会一定称它为 **非法**,因为当前在 edn.reader 中添加的当前行为在 1.6 版中并未发出警告。
  • 此外,如果允许存在关键字 "foo/bar/baz",那么仍然存在 @bronsa 指出的不确定的命名空间/名称问题。我将主张一致性:如果 :foo/bar/baz 在阅读器中是非法的,那么它应该到处都是非法的
  • 我的库应该没问题... 但是可能用户需要更改他们的查询
0
by

评论者:alexmiller

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

{{keyword}}的2个位置形式可以无歧义地使用:{{(keyword nil "foo/bar/baz")}}。1个位置形式将根据第一个找到的'/'分割(在此示例中为"foo"和"bar/baz")。我看不到需要改变的理由。

0
by

评论者: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

好吧... 至少所有的例子都是一致的“非法”

无论如何,即使文档没有明确说明,:foo/bar/baz 自从Clojure开始以来一直存在,并且我个人认为它更像字符串而不是符号。具有讽刺意味的是,我非常确定我是从当时我开始工作于adi时阅读datomic文档中学到了在关键字中使用多个斜杠的想法。

最终,决定权不在我,我确实尊重Clojure团队对语言发展的指导。然而,我确实希望人们能认识到我保持现状的观点,并将其考虑在内。

0
by

评论者:zcaudate

我将引用Rich https://www.youtube.com/watch?v=P76Vbsk_3J0 @ 5:10

"你们认为的许多问题是(lisp中的)特性...长期来看..."

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