在Clojure中,为什么有字符串、关键字和符号?

25

我正在学习Clojure,但无法理解某些语言设计决策:既然Clojure使用不可变字符串,为什么还需要关键字和符号数据类型?字符串不能只有可选的命名空间和元数据等吗?对于不可变字符串,比较也可以基于标识进行,对吗?

另外,由于与Java的互操作性对于Clojure来说是必须的,因此至少应该有Java String类型和一个KeywordSymbol数据类型。

我发现Clojure中String/Keyword/Symbol的“三分法”特别奇怪,因为Clojure在其他方面似乎非常注重“纯洁性”和简单性。


2
不,不可变性并不意味着仅通过身份比较就足够了,您仍然可以拥有具有相同内容的多个不可变实例。这种假设仅适用于内部化字符串。 - David Ongaro
2个回答

16

它们在语言中的作用非常不同:

  • 变量用于给事物命名。它们实现了runnable,可以直接用来调用函数。你无法运行一个字符串。
  • 关键字本身就是名称,并在映射中查找自己。它们真正有助于保持Clojure的“数据驱动”风味。字符串没有实现必要的接口来在映射中查找自己。
  • 字符串只是字符串。它们做它们需要做的事情,没有多余的功能。

Clojure设计中的核心原则之一是拥抱托管平台,因此在Clojure中,字符串是Java字符串,您永远不需要在将其放入Clojure生态系统之前将Java字符串包装在某个convert-to-clojure-string函数中。这需要使用未经修改的Java字符串,以及数值类型。关键字和符号是Clojure正在添加的新构造,因此只需要使它们以一种有用的方式从Java生态系统的其余部分访问即可。符号和关键字通过成为实现接口的类来使自己可访问。开始时认为,为了使新语言在JVM生态系统中成功,需要完全拥抱Java并最小化“阻抗不匹配”(对于这个术语很抱歉),即使这需要在语言中添加更多内容。

编辑:


您可以通过将符号def为它自身,将其转换为关键字

user> a
; Evaluation aborted.
user> :a
:a
user> (def a 'a)
#'user/a
user> a
a
user> 

关键字会自我表达


这并不能解释为什么关键字和字符串必须分开。例如,在Ruby中,字符串和符号都是必需的,因为一个是可变的,而另一个则不是。为什么不能只有关键字或字符串,并且其中一个具有查找自身的接口? - Chris
我会将差异追加到我的答案中。 - Arthur Ulfeldt
@andrewcooke,你说一个符号不会被评估为什么都没有?如果我在REPL中键入'x,我会得到x,所以我的结论是“一个符号评估为它自己,即一个符号,但该符号不会被解析”...我的头现在很晕... - NeuronQ
@ArthurUlfeldt...你不是真的必须要使用(keyword (name a))(keyword (name 'a))(它们会被正确地求值为相同的结果),才能将符号转换为关键字吗?我认为andrew coke指的是('a {'a 1 'b 2}),这确实有效,求值为1,因此符号也可以在映射中查找自己 - NeuronQ
5
我认为重点是明确目的。关键词旨在进行数据查找,符号旨在进行编译时查找。您可以保证给定名称只有一个关键字,但这种保证对于映射不存在。我认为字符串没有被简单地扩展的另外原因是,由于关键字能够被命名空间化以及由于关键字使用的自定义内部化行为,这些原因也起了作用。 - deterb
显示剩余5条评论

4
我认为Clojure更注重“实用性”(如果这个词是正确的话),而不是“纯粹性”。这可以从Clojure拥有地图、向量和集合语法以及使用它来定义语言中看出。在Scheme中,它更注重纯度(我个人认为),你只有列表的语法。
正如Arthur Ulfeldt所指出的,字符串、关键字和符号都有其预期的使用情况。按照预期使用它们可以使阅读Clojure代码更容易。这类似于HTML 5所做的事情,它添加了语义标记。像<article><section>这样的东西,在HTML 4中可以用<div class="article"><div class="section">表示。
哦,你关于仅通过身份比较字符串是错误的。这仅对已经interned的字符串有效。你不想intern太多的字符串,因为它们被存储到所谓的permgen中,它的大小非常有限且永远不会被垃圾回收。

1
我认为在一些较新版本的JVM中,如果所有对字符串的引用都丢失,则interned字符串可以进行垃圾回收。我现在找不到可靠的来源,所以我可能是错的。无论如何,肯定不能经常使用==来比较字符串。 - amalloy
有趣的是,我之前不知道JVM的内部字符串(你可能已经发现我不是Java程序员,我从完全不同的背景来到Clojure,也许这就是为什么我觉得一些受Java/JVM影响的语言设计决策很奇怪的原因 :))...也许在学Clojure之前,我应该先玩一下Scheme,以获得更好的关于Lisp的“直觉”... - NeuronQ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接