Scala有符号 - 以单引号开头的名称',它们是一种字符串常量.
我知道来自Ruby的符号(它们以冒号开头).在Ruby中,它们用于一些元编程任务,例如为成员变量生成getter和setter(例如attr_reader :name为其生成getter name).
我还没有在Scala代码中看到很多符号的使用.Scala中符号的实际用途是什么?
Mat*_*ard 33
符号真的适合Scala吗?
在Lisp的美妙土地中,代码表示为文本对象的嵌套列表,表示它们自己(字符串,数字等)和符号,它们用作类,函数和变量之类的标识符.由于Lisp代码具有非常简单的结构,Lisp允许程序员操作它(在编译时和运行时).显然,在执行此操作时,程序员将不可避免地将符号视为数据对象.
因此,在任何情况下,符号都是(并且需要)Lisp中的对象,那么为什么不将它们用作哈希表键或枚举呢?这是自然的做事方式,它使语言简单,因为您不必定义特殊的枚举类型.
总而言之,符号自然用于代码操作,枚举和键控.但是Java人员默认情况下不使用身份作为哈希键之间的等价关系(传统的Lisp就是这样),所以他们只能使用字符串作为键.枚举类型在Scala中单独定义.最后,语言根本不支持代码作为数据.
所以不,我的印象是符号不属于Scala语言.那就是说,我将密切关注对这个问题的回复.他们可能仍然在Scala中展示了我现在无法想到的符号的真实用法.
(附录:根据Lisp方言,Lisp符号也可能是命名空间限定的,当然,这在操作代码时是一个非常有用的功能,而字符串也没有.)
Det*_*Det 18
在网络上搜索一下,与Scings相比,Scala中的符号(符号文字)似乎是语义问题,因此甚至可能是编译器意识.
'String'是一种数据类型,由一系列字符组成.您可以对字符串进行操作,然后对其进行操作.字符串在语义上可以是任何文本数据,从文件名到要在屏幕上打印的消息,CSV文件中的行等等.
对于编译器 - 因此IDE字符串是数据类型String的值,类似数字(数字序列)是数据类型的值,例如:Integer.在程序级别上"foo"和"bar"之间没有区别.
OTOH符号是标识符,即在语义上识别程序中的项目.在这个问题上,它们就像类名,方法名或属性名.但是,虽然类名称标识了类 - 声明类的结构和行为的属性集 - 方法名称标识方法 - 参数和语句 - 符号名称标识符号 - 它本身,仅此而已 - .
因此编译器可以明确区分符号'foo和'bar,就像他区分Foo和Bar类一样.作为编译器符号表的一部分,您可以在IDE中应用相同的机制,例如,搜索'foo(即对此符号的引用)的用法,就像搜索类Foo的用法一样.
在比较中,搜索字符串"foo"将需要不同的方法,如全文扫描.它遵循与在程序代码中搜索所有出现的4711相同的语义.
这就是我理解的方式,如果我错了,有人可能会纠正我.
jqn*_*qno 15
根据Scala的书,符号被实习:" 如果你写两次相同的符号,两个表达式都将引用完全相同的Symbol对象. "
相比之下,String如果它们以字面形式出现,那么它们只会被实现(至少在Java中它们是不完全确定的Scala).所以我想如果你做了大量的Strings 序列化然后放入集合中,你可能会使用符号代替并节省一些内存.
但我同意斯卡弗曼,我并不完全相信他们的使用.
(在Ruby中,Symbols,除了你提供的元编程示例之外,经常用作Hashes中的键.在Ruby中,这很有用,因为在那里,Strings永远不会被实现:每个都String分配新内存.在Scala中它可能是有用的,如我提到过,如果你将它与很多(反)序列化结合起来,那么Java String也不会被实际干掉.)
Dan*_*ral 15
我猜Scala添加了它们,因为函数式语言使用它们.
但是,他们忘记了添加通过符号引用标识符的能力,这是它们存在的中心点.Scala 2.8中有一个实验性功能,可以提供一些功能.我将完整引用API文档的相关部分:
@experimental
object Invocation
extends AnyRef
Run Code Online (Sandbox Code Playgroud)
反射调用的更方便的语法.用法示例:
class Obj { private def foo(x: Int, y: String): Long = x + y.length }
Run Code Online (Sandbox Code Playgroud)
你可以反思性地称之为两种方式之一:
import scala.reflect.Invocation._
(new Obj) o 'foo(5, "abc") // The 'o' method returns Any
val x: Long = (new Obj) oo 'foo(5, "abc") // The 'oo' method casts to expected type.
Run Code Online (Sandbox Code Playgroud)
如果你调用oo方法并且不给类型推理器足够的帮助,它很可能会推断Nothing,这将导致a ClassCastException.
作者保罗菲利普斯
我相信符号之间的比较更快.如果您使用过Erlang,那么在传递消息时使用的符号就是一吨,并且您想要一些便宜且快速的东西,它可以很好地适应ACROSS的机器边界.我不确定在Scala,IIRC的远程演员处于什么状态,他们相当狡猾,但是将来当它们到位时,符号可能非常有用,就像它们在Erlang中一样.还有案例类,一些好处并不明显,然后,符号仍然更便宜.