在Scala中使用符号的实际示例?

时间:2009-08-24 20:08:19

标签: scala symbols

Scala有符号 - 以单引号开头的名称',它们是一种字符串常量。

我知道来自Ruby的符号(它们以冒号开头)。在Ruby中,它们用于一些元编程任务,例如为成员变量生成getter和setter(例如attr_reader :namename生成getter。)

我还没有在Scala代码中看到很多符号的使用。 Scala中符号的实际用途是什么?

8 个答案:

答案 0 :(得分:33)

符号真的适合Scala吗?

在Lisp的美妙土地上,代码表示为文本对象的嵌套列表,表示自身(字符串,数字等)和符号,它们用作类,函数和变量之类的标识符。由于Lisp代码具有非常简单的结构,Lisp允许程序员操作它(在编译时和运行时)。显然,在执行此操作时,程序员将不可避免地将符号视为数据对象。

因此,在任何情况下,符号都是(并且需要)Lisp中的对象,那么为什么不将它们用作哈希表键或枚举呢?这是一种自然的做事方式,它使语言简单,因为您不必定义特殊的枚举类型。

总而言之,符号自然用于代码操作,枚举和键控。但是Java人员默认情况下不使用身份作为哈希键之间的等价关系(传统的Lisp就是这样),所以他们只能使用字符串作为键。枚举类型在Scala中单独定义。最后,语言根本不支持代码作为数据。

所以不,我的印象是符号不属于Scala语言。那就是说,我将密切关注对这个问题的回复。他们可能仍然在Scala中展示了我现在无法想到的符号的真实用法。

附录:取决于Lisp方言,Lisp符号也可能是名称空间限定的,当然,这在操作代码时是一个非常有用的功能,而字符串不是有。)

答案 1 :(得分:18)

在网络上搜索一下,与Scings相比,Scala中的符号(符号文字)似乎是语义问题,因此甚至可能是编译器意识。

'String'是一种数据类型,由一系列字符组成。您可以对字符串进行操作,然后对其进行操作。字符串在语义上可以是任何文本数据,从文件名到要在屏幕上打印的消息,在CSV文件中的行或其他任何内容。

对于编译器 - 因此IDE字符串是数据类型String的值,类似数字(数字序列)是数据类型的值,例如:Integer。 在程序级别上,“foo”和“bar”之间没有区别。

OTOH符号是标识符,即在语义上识别程序中的项目。 在这个问题上,它们就像类名,方法名或属性名。 但是,类名称标识类-i.e.声明类的结构和行为的属性集,方法名称标识方法-i.e.参数和语句 - 符号名称标识符号-i.e.它自己,仅此而已 - 。

因此,编译器可以明确区分符号'foo和'bar,就像他区分Foo和Bar类一样。作为编译器符号表的一部分,您可以在IDE中应用相同的机制,例如搜索'foo(即对此符号的引用)的用法,就像搜索Foo类的用法一样。

在比较中,搜索字符串“foo”需要不同的方法,如全文扫描。它遵循与在程序代码中搜索所有出现的4711相同的语义。

这就是我理解的方式,如果我错了,有人可能会纠正我。

答案 2 :(得分:15)

根据Scala的书,符号被实习:“如果你写两次相同的符号,两个表达式都将引用完全相同的Symbol对象。

相比之下,String只有在它们以字面形式出现时才被实现(至少在Java中它们是,不完全确定Scala)。所以我想如果你做了很多String的序列化然后放入集合中,你可以改用符号来节省一些内存。

但我同意斯卡弗曼,我并不完全相信他们的使用。

(在Ruby中,Symbol除了您提供的元编程示例外,通常在Hash es中用作键。在Ruby中,这很有用,因为String s永远不会被实现:每个String分配新内存。在Scala中,如果你将它与很多(反)序列化结合起来,那么Java String可能没有用。得到实习。)

答案 3 :(得分:15)

我猜Scala添加了它们,因为函数式语言使用它们。

但是,他们忘记了添加通过符号引用标识符的能力,这是它们存在的中心点。 Scala 2.8中有一个实验性功能,可以提供一些功能。我将完整引用API文档的相关部分:


@experimental

object Invocation 
extends AnyRef

反射调用的更方便的语法。 用法示例:

    class Obj { private def foo(x: Int, y: String): Long = x + y.length }

您可以通过以下两种方式之一反思称呼它:

    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.

如果您调用oo方法并且没有为类型推断器提供足够的帮助,则很可能推断Nothing,这将导致ClassCastException

作者 保罗菲利普斯

答案 4 :(得分:5)

我相信符号之间的比较更快。如果您使用过Erlang,那么在传递消息时使用的符号就是吨,并且您想要一些便宜且快速的东西,它可以很好地适应ACROSS的机器边界。我不确定在Scala,IIRC的远程演员处于什么状态,他们相当狡猾,但是将来当它们到位时,符号可能非常有用,就像它们在Erlang中一样。还有案例类,其中一些好处并不明显,那么符号仍然更便宜。

答案 5 :(得分:3)

我想当你想要引用代码中不是现有标识符的东西的名称时,你会使用它们。 Scala书中给出了引用数据库列名称的示例 - 它不是任意字符串,它实际上是事物的名称。

但是,它有点脆弱,但我并不完全相信。

答案 6 :(得分:1)

我可以在Scala中真正使用符号时命名一个案例。 Play 2.2使用 anorm 来访问数据库。 这是一个简单的add实体方法的代码示例:

def add(e:Entity): Option[Long] = {
    DB.withConnection {implicit conn =>
        SQL("insert into ENTITY(name, description) values({name}, {description})").on('name -> e.name, 'description -> e.description).executeInsert()
    }
}

所以你可以看到.on中的符号用法(bla bla bla) 使用String文字而不是符号也是绝对有效的,有些人正在这样做,但在anorm源代码中,相应的方法签名确实使用了Symbol paremeter类型。

答案 7 :(得分:1)

如前所述,符号来自其他(更多)功能语言。其他人没有提到的是,它们不仅充当了符号的角色,而且它们也是最接近的关键词(减去性能优势)。在我看来,它们作为关键字更有用,意思是显式标识符。

下面我将提供Clojure docs关键字和符号的法院描述。

  

符号

     

符号是通常用于指代其他内容的标识符。它们可以在程序表单中用于引用函数参数,绑定,类名和全局变量。它们具有名称和可选名称空间,两者都是字符串。符号可以包含元数据(请参阅-met)。

     

关键字

     

关键字是评估自己的符号标识符。它们提供非常快速的相等测试。与符号一样,它们具有名称和可选名称空间,两者都是字符串。前导':'不是命名空间或名称的一部分。

Scala符号不像某些语言中的符号那样强大。因此,它们也没有那么有用。但是,我不明白为什么他们不能提供与关键字相同的元编程和性能优势。至少,它们可以使您的代码更容易阅读。

相关问题