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中,包含多个斜杠的键具有不同的hashcode。

这在使用1.5版本的clojure进行datomic操作时可能出现问题,而在1.6版本的clojure中,该schema有一个或多个包含多个斜杠的键。

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")`会失败并抛出`Invalid token`异常?

hiredman [下午5:04]
有一个修复read-string的工单

dm3 [下午5:05]
所以正确的做法是失败吗?

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

dm3 [下午5:06]
谢谢,看起来这是一个破坏性变更呢:微笑

hiredman [下午5:07]
文档已经阻止了像a/b/c这样的符号一段时间了,而那些未指定符号的读取行为在某个时候似乎已经改变了

lucas [下午5:09]
加入了#clojure聊天室

zcaudate [下午5:16]
@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]
是的,不幸的是,还得修补cljs.tools.reader:困惑

[5:31]
我想我会先绕过去解决这个问题

bronsa [下午5:36]
@zcaudate:`::foo/bar`风格的符号是按设计加入的,不会移除,`:foo/bar/baz`始终是无效 Clojure 并未定义的行为(已编辑)

[5:37]
@dm3:改变未定义的行为算是一个破坏性更改吗?:微笑

dm3 [下午5:37]
破坏性,指破坏人们代码的意思:微笑

[5:37]
例如zcaudate

bronsa [下午5:38]
如果它使用无效的Clojure,那么该代码已经是损坏的。只是偶然在运行

dm3 [下午5:39]
我从实用主义的角度来看。从理论上讲,你是对的:微笑

[5:40]
我也没有评判

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

dm3 [下午5:40]
目前返回什么就返回什么?

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

sveri [下午5:41]
@dm3 @bronsa 我不同意你觉得你是理论上的正确:我不同意。一旦足够的人适应了损坏的代码,它就会变得像一种被双方接受足够长时间的共同法一样。

bronsa [下午5:42]
那么`(keyword "foo/bar" "baz")`和`(keyword "foo" "bar/baz")`的`namespace`呢?

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

[5:43]
但我认为这是一个破坏性更改

[5:43]
并不是因为它是一个“坏”的变更

[5:43]
这是一个判断

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

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

[5:45]
这破坏了现有代码,它没有导致奇怪的语义,所以被撤回。与`:foo/bar/baz`不同。

[5:45]
@dm3:你可以这样说——修复任何错误都是破坏性变更——人们可能会依赖那个错误。

dm3 [下午5:46]
是的,我想重要的是,错误的明显程度以及有多少人依赖它

bronsa [下午5:46]
如果文档明确说“你可以在符号内部使用*一*个/”,那么如果你使用了多个,你就是在编写无效的Clojure,你应该预期它可能会破坏(已编辑)

dm3 [5:47 PM]
我真的甚至在过去的3年多时间里都没有想过在Clojure中的符号中的多个斜杠(也没有注意到文档)

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

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

bronsa [5:51 PM]
然而,这并没有太大的意义。在Clojure中`/`表示`命名空间分隔符`。如果我看到`FOO/BAR`,不管`FOO`和`BAR`是什么,我都知道`FOO`是命名空间,`BAR`是名称。如果您想使用关键词(如@zcaudate的库中所示)来表示路径,您应该使用没有特殊意义的不同分隔符,如`.`(即`:foo/bar/baz` -> `:foo.bar.baz`或`:foo/bar.baz`)(编辑过)

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

bronsa [5:52 PM]
我的观点是,只要它们所隐含的语义清晰且不含糊,才应考虑这些实际的观点(特别是当它们与当前文档相反时)

sveri [5:53 PM]
@bronsa: 不错的解释,谢谢:简单的笑脸

dm3 [5:53 PM]
是啊:简单的笑脸

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


zcaudate [9:07 PM]
@bronsa:书面沟通有一种让事情看起来比实际上更严重的方式

[9:08]
说实话……我自从1.6版edn读取器开始破坏我的代码时就知道这会来了

[9:09]
这可能是我的问题,因为我没有早些时候就传达这一点,但无论如何……我们都要与时俱进

bronsa [9:09 PM]
@zcaudate:没问题,我只是因为你想起了它,才拿你的库作为例子

zcaudate [9:10 PM]
话虽如此,你可以想象我的失望,因为我本想完全基于关键词`: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 PM]
@zcaudate:你发布的东西质量这么高,我想知道你是否从未睡过!
1  

bronsa [9:12 PM]
@zcaudate:幸运的是,修复应该很容易:简单的笑脸:只需将`/`替换为`.`

zcaudate [9:12 PM]
不!

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

[9:13]
所以我将不得不做cls风格的事:`account.type$user`

bronsa [9:13 PM]
(顺便说一句,那是一些高质量的文档,干得好)

zcaudate [9:14 PM]
@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 PM]
@zcaudate:抱歉,如果这不够清楚,但事实上我没有控制或决定将什么内容放入Clojure,我只是贡献者:简单的笑脸。所以有可能会是clojure/core团队做出不同的决定,实际上拒绝那个票据(如果是这样,我肯定会非常失望)。如果那样的话,我会显然将更改应用到`tools.reader`上,以允许他们这样做(编辑过)

zcaudate [9:18 PM]
@bronsa:见鬼。

[9:19]
嗯……也许你可以强调这一点

[9:19]
并且如果修复了,还需要修复`(keyword "foo/bar/baz")`(编辑过)

bronsa [9:20 PM]
我认为这永远不会完成。人们多次要求/讨论了通过`keyword`/`symbol`等验证输入,但由于性能原因,这些请求/讨论总是被拒绝

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

bronsa [9:20 PM]
(我并不认同那个决定,但感觉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
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 在reader中是非法的,那么它应该在哪里都非法
  • 我的库应该没有问题...但是库的用户可能需要更改他们的查询
0
by

评论者:alexmiller

阅读页清楚地指出,“/”有特殊含义,它可以在符号中间使用一次来区分命名空间和名称”和关键字是“如符号”。这在我能从网络档案馆找到的最老版本中出现在阅读页(2008年7月)。edn(尽管与其相似)是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
by
参考:https://clojure.atlassian.net/browse/CLJ-1530(由bronsa报告)
...