63

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

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

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

4

8 回答 8

36

符号真的适合 Scala 吗?

在 Lisp 的奇妙之地,代码被表示为表示自身的文字对象(字符串、数字等)和符号的嵌套列表,这些符号用作类、函数和变量等事物的标识符。由于 Lisp 代码具有非常简单的结构,Lisp 允许程序员操作它(在编译时和运行时)。显然,在这样做时,程序员将不可避免地遇到符号作为数据对象。

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

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

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

附录:根据 Lisp 方言,Lisp 符号也可能是命名空间限定的,这当然是操作代码时非常有用的功能,并且是字符串所没有的功能。)

于 2009-08-25T08:12:47.957 回答
19

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

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

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

OTOH 符号是标识符,即在语义上标识程序中的项目。在这个问题上,它们就像类名、方法名或属性名。但是,虽然类名标识了类——即声明类的结构和行为的属性集——并且方法名标识了方法——即参数和语句——,但符号名标识了符号——即它本身,仅此而已—— .

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

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

我是这么理解的,如果我错了,有人可以纠正我。

于 2010-06-11T08:50:59.333 回答
15

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

相比之下,Strings 只有在以字面形式出现时才会被保留(至少在 Java 中它们是,对 Scala 并不完全确定)。所以我想如果你对Strings 进行大量序列化然后放入集合中,你可能会使用符号来代替并为自己节省一些内存。

但我同意 skaffman 的观点,我并不完全相信它们的用途。

(在 RubySymbol中,除了您给出的元编程示例外,s 经常用作Hashes 中的键。在 Ruby 中,这很有用,因为Strings 永远不会被实习:everyString分配新内存。在 Scala 中它可能很有用,因为我提到过,如果你将它与大量(反)序列化结合起来,那么 JavaString也不会被实习。)

于 2009-08-24T20:29:24.027 回答
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方法并且没有给类型推断器足够的帮助,它很可能会推断NothingClassCastException.

作者保罗菲利普斯

于 2009-08-25T22:59:10.443 回答
5

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

于 2009-08-24T23:48:00.430 回答
3

我想当您想引用代码中不存在的标识符的事物的名称时,您会使用它们。Scala 书中给出了引用数据库列名称的示例——它不是任意字符串,它实际上是事物的名称。

不过,这有点脆弱,我并不完全相信。

于 2009-08-24T20:11:33.830 回答
1

我可以举出一种在 Scala 中真正使用符号的情况。Play 2.2 使用anorm访问数据库。下面是简单添加实体方法的代码示例:

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) 中看到符号的用法使用字符串文字而不是符号也是绝对有效的,有些人正在这样做,但是在异常源代码中,相应的方法签名确实使用符号参数类型。

于 2013-11-03T11:11:15.403 回答
1

如前所述,符号从其他(更多)功能语言中继承。其他人没有提到的是,它们不仅填补了符号的作用,而且它们也是最接近关键字的等价物(可能减去性能优势)。在我看来,它们作为关键字更有用,意味着显式标识符。

下面我将包含来自Clojure 文档的关键字和符号的法庭描述。

符号

Symbols are identifiers that are normally used to refer to something else. They can be used in program forms to refer to function parameters, let bindings, class names and global vars. They have names and optional namespaces, both of which are strings. Symbols can have metadata (see with-meta).

Keywords

Keywords are symbolic identifiers that evaluate to themselves. They provide very fast equality tests. Like Symbols, they have names and optional namespaces, both of which are strings. The leading ':' is not part of the namespace or name.

Scala symbols are not as powerful as symbols in some languages. Therefore, they are not as useful either. However, I don't see why they couldn't offer the same meta-programming and performance advantages as keywords. At the very least, they can make your code easier to read.

于 2015-12-24T18:30:57.150 回答