Scala 符号的用途? [复制]
Posted
技术标签:
【中文标题】Scala 符号的用途? [复制]【英文标题】:Purpose of Scala's Symbol? [duplicate] 【发布时间】:2011-04-03 00:47:34 【问题描述】:可能重复:What are some example use cases for symbol literals in Scala?
Symbol 的用途是什么,为什么它值得一些特殊的literal 语法 e. G。 'FooSymbol
?
【问题讨论】:
相关:***.com/questions/780287/… 相关:***.com/questions/1324466/… Related scala-programming-language.1934581.n4.nabble.com/… 我还是不明白为什么我们需要一个特殊的语法。 Scala 已经有足够的语法了。 注意:Symbols
将在 Scala 3 (dotty) 中被删除:dotty.epfl.ch/docs/reference/dropped-features/symlits.html -- 因此,我个人不再使用 Symbols
。
【参考方案1】:
Symbol
s 被拘留。
目的是Symbol
比String
s更高效,Symbol
s同名引用同一个Symbol
对象实例。
看看这篇关于 Ruby 符号的文章:http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols
你只能得到Symbol
的名字:
scala> val aSymbol = 'thisIsASymbol
aSymbol: Symbol = 'thisIsASymbol
scala> assert("thisIsASymbol" == aSymbol.name)
【讨论】:
是的,在 .NET CLR 中也是如此。 这个条目有点误导;在您说“具有相同的哈希码”的地方,所有相等的字符串都具有相同的哈希码。它们的不同之处在于它们是完全相同的对象实例,这意味着比较它们不涉及调用复杂的“equals”方法来比较每个字符;您只需要比较内存位置(即 Java 中的 == 或 Scala 中的“eq”)。 IttayD:那不是真的。文字字符串是实习的,你可以用 String.intern() 实习字符串。 字符串不是 100% 总是被实习的javatechniques.com/public/java/docs/basics/string-equality.html【参考方案2】:符号用于您希望能够快速比较的一组封闭标识符。当您有两个 String
实例时,不能保证它们会被实习 [1],因此要比较它们,您必须经常通过比较长度甚至逐个字符检查它们是否相同来检查它们的内容。对于Symbol
实例,比较是一个简单的eq
检查(即Java 中的==
),因此它们的查找时间是恒定的(即O(1))。
这种结构往往更多地用于动态语言(尤其是 Ruby 和 Lisp 代码往往会大量使用符号),因为在静态类型语言中,人们通常希望按类型限制项目集。
话虽如此,如果您有一个键/值存储,其中有一组受限制的键,使用静态类型对象会很笨拙,Map[Symbol, Data]
风格的结构可能很适合你。
关于 String
在 Java(以及因此 Scala)上实习的说明:Java String
s 在某些情况下无论如何都会被实习;特别是字符串文字会自动被实习,您可以在 String
实例上调用 intern()
方法以返回实习副本。但是,并非所有String
s 都被实习,这意味着运行时仍然必须进行全面检查,除非它们是同一个实例; interning 可以更快地比较两个相等的 interned 字符串,但不会提高比较不同字符串的运行时间。 Symbol
s 受益于 保证 被实习,所以在这种情况下,一个单一的引用相等检查就足以证明相等或不相等。
[1] 实习是一个过程,当您创建一个对象时,您检查是否已经存在相等的对象,如果存在则使用该对象。这意味着如果你有两个相等的对象,它们就是同一个对象(即它们的引用相等)。这样做的缺点是查找您需要使用的对象的成本可能很高,并且允许对对象进行垃圾收集可能需要复杂的实现。
【讨论】:
说符号是指向全局变量的指针是否正确(例如 C 语言中的指针)?只有一个副本存在。如果两个符号s1
和s2
具有相同的name
,说“somename”,那么s1
和s2
指的是内存中的同一个对象,其值为“somename”?
@ManuChadha 是的【参考方案3】:
它在 Scala 中不是很有用,因此没有被广泛使用。一般来说,您可以在您想指定标识符的地方使用符号。
例如,计划在 2.8.0 中使用的反射调用功能使用语法 obj o 'method(arg1, arg2)
,其中 'o' 是添加到 Any 的方法,而 Symbol 是添加方法 apply(Any*) (两者都使用 'pimp my图书馆')。
另一个例子是,如果您想创建一种更简单的方法来创建 HTML 文档,那么您应该编写 'div.然后可以想象将运算符添加到 Symbol 以制作用于创建元素的语法糖
【讨论】:
对于最后一个例子,没有理由不使用字符串而不是符号。 原因是在 HTML 中,'div' 是一个标识符,而不仅仅是一个随机字符串。这就是为什么我提到 HTML 而不是 XML(元素可以是任何名称)。所以 Symbol 的原因是语义上的。从功能上讲,没有区别 @IttayD、ad.HTML、符号或字符串,没关系,因为无论如何你都可以打错字。以上是关于Scala 符号的用途? [复制]的主要内容,如果未能解决你的问题,请参考以下文章