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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1324466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:37:34  来源:igfitidea点击:

Practical examples of using symbols in Scala?

scalasymbols

提问by Jesper

Scala has symbols - names that start with a single quote ' and which are a kind of string constants.

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

I know symbols from Ruby (where they start with a colon). In Ruby they are used for some meta-programming tasks, like generating getters and setters for member variables (for example attr_reader :nameto generate a getter for name).

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

I haven't seen a lot of use of symbols in Scala code yet. What are practical uses for symbols in Scala?

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

采纳答案by Matthias Benkard

Do symbols really fit into Scala?

符号真的适合 Scala 吗?

In the wonderful land of Lisp, code is represented as nested lists of literal objects that denote themselves (strings, numbers, and so on), and symbols, which are used as identifiers for things like classes, functions, and variables. As Lisp code has a very simple structure, Lisp allows the programmer to manipulate it (both at compile-time and run-time). Clearly, when doing this, the programmer will inevitably encounter symbols as data objects.

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

So symbols are (and need to be) objects in Lisp in any case, so why not use them as hash table keys or as enums as well? It's the natural way of doing things, and it keeps the language simple, as you don't have to define a special enumeration type.

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

To summarise, symbols are naturally used for code manipulation, enumeration, and keying. But Java people don't use identity as the equivalence relation between hash keys by default (which your traditional Lisp does), so they can just use strings as their keys. Enum types are defined separately in Scala. And finally, code as data isn't supported by the language at all.

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

So no, my impression is that symbols don't belong in the Scala language. That said, I'm going to keep an eye on the replies to this question. They might still demonstrate a genuine use of symbols in Scala that I can't think of right now.

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

(Addendum:Depending on the Lisp dialect, Lisp symbols may also be namespace-qualified, which is, of course, an immensely useful feature when manipulating code, and a feature that strings don't have.)

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

回答by Det

Searching a bit around the web it seems that the sense of symbols (symbol literals) in (a language like) Scala in comparision with Strings is a matter of semantics, and thus possibly even compiler awareness.

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

'String' is a datatype, consisting of a sequence of characters. You can operate on strings and so manipulate them. Strings can semantically be any text data, from a filename to a message to be printed on screen, a line in a CSV file, or whatever.

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

For the compiler -and thus the IDE- strings are values of a data type String, like numbers (sequences of digits) are values of a data type say: Integer . There is on the program level no difference between "foo" and "bar".

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

OTOH Symbols are identifiers, i.e. semantically identifying an item in the program. In this matter they are like class names, method names or attribute names. But while a class name identifies the class -i.e. the set of properties declaring the class' structure and behaviour- and a method name identifies the method -i.e. the parameters and statements- , a symbol name identifies the symbol -i.e. itsself, nothing more- .

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

So the compiler can explicitly distinguish between the symbols 'foo and 'bar, like he distinguishes between the classes Foo and Bar. As part of the compiler's symbol table, you can apply the same mechanisms in an IDE e.g. to search for the usage of 'foo (i.e. the references to this symbol) like you search for the usage of class Foo.

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

In comparision, searching for a string "foo" would require different approaches, like a full text scan. It follows the same semantics as searching for all occurrences of 4711 in the program code.

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

That's how I understand it, someone may correct me if I'm wrong.

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

回答by Daniel C. Sobral

I guess Scala added them because functional languages use them.

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

They forgot, though, to add the ability of referencing an identifier through a symbol, which is kind of the central point of their existence. There's an experimental feature in Scala 2.8 that gives some of that. I'll quote the relevant part of the API documentation in full:

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



@experimental

object Invocation 
extends AnyRef

A more convenient syntax for reflective invocation. Example usage:

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

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

You can call it reflectively one of two ways:

您可以通过以下两种方式之一反射性地调用它:

    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.

If you call the oomethod and do not give the type inferencer enough help, it will most likely infer Nothing, which will result in a ClassCastException.

如果您调用该oo方法并且没有给予类型推断器足够的帮助,它很可能会推断Nothing,这将导致ClassCastException.

Author Paul Phillips

作者保罗菲利普斯

回答by jqno

According to the Scala book, Symbols are interned: "If you write the same symbol twice, both expressions will refer to the exact same Symbolobject."

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

In contrast, Strings are only interned if they appear in literal form (at least in Java they are, not entirely sure about Scala). So I guess if you do a lot of serialization of Strings that are then put into collections, you might use symbols instead and save yourself some memory.

相比之下,Strings 只有在以字面形式出现时才会被实习(至少在 Java 中是这样,对 Scala 并不完全确定)。因此,我想如果您对Strings进行大量序列化,然后将其放入集合中,您可能会改用符号并为自己节省一些内存。

But I agree with skaffman, I'm not totally convinced of their use.

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

(In Ruby, Symbols are, apart from the meta-programming example you give, often used as keys in Hashes. In Ruby this is useful because there, Strings are never interned: every Stringallocates new memory. In Scala it might be useful, as I mentioned, if you combine it with a lot of (de)serialization so the Java Strings don't get interned as well.)

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

回答by Saem

I believe comparisons between symbols is faster. If you've used Erlang, symbols are used a tonne when passing around messages and you want something cheap, and fast, that works well ACROSS machine boundaries. I'm not sure in what state remote actors are in Scala, IIRC, they were rather dodgy, but in the future when them in place, symbols could well be very useful in much the same way as they are in Erlang. Also case classes, some of the benefits aren't as apparent, then again, symbols are still cheaper.

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

回答by skaffman

I suppose you would use them when you want to refer to the name of a thing that isn't an existing identifier in the code. The Scala book gives the example of referring to the name of a database column - it isn't an arbitrary string, it's actually the name of a thing.

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

It's a bit tenuous, though, I'm not altogether convinced.

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

回答by Alexander Arendar

I can name one case when symbols are really used in Scala. Play 2.2 uses anormto access database. Here goes a code sample for the simple add entity method:

我可以列举一种在 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()
    }
}

so you can see the usage of symbols in the .on(bla bla bla) It is also absolutely valid to use String literals instead of symbols and some guys are doing so, but in the anorm source code the corresponding method signature really use Symbol paremeter type.

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

回答by Dominykas Mostauskis

As already noted, symbols carry-over from other (more) functional languages. Something others have not mentioned is that not only do they fill the role of symbols, but they are also the closest equivalent of keywords (minus the performance advantage maybe). In my opinion, they are more useful as keywords, meaning explicit identifiers.

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

Below I will include a court description from Clojure docsof keywords and symbols.

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

Symbols

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.

符号

符号是通常用于指代其他事物的标识符。它们可以在程序形式中用于引用函数参数、let 绑定、类名和全局变量。它们有名称和可选的命名空间,两者都是字符串。符号可以有元数据(参见 with-meta)。

关键词

关键字是对自身求值的符号标识符。它们提供了非常快速的相等性测试。和 Symbols 一样,它们有名称和可选的命名空间,两者都是字符串。前导的 ':' 不是命名空间或名称的一部分。

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.

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