Practical examples of using symbols in Scala?

2019-01-16 10:34发布

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

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 :name to generate a getter for name).

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

标签: scala symbols
8条回答
Summer. ? 凉城
2楼-- · 2019-01-16 11:14

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.

'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.

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".

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- .

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.

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.

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

查看更多
【Aperson】
3楼-- · 2019-01-16 11:28

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 docs of keywords and symbols.

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.

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.

查看更多
放荡不羁爱自由
4楼-- · 2019-01-16 11:29

I guess Scala added them because functional languages use them.

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:


@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 oo method and do not give the type inferencer enough help, it will most likely infer Nothing, which will result in a ClassCastException.

Author Paul Phillips

查看更多
forever°为你锁心
5楼-- · 2019-01-16 11:29

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.

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

查看更多
欢心
6楼-- · 2019-01-16 11:31

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.

查看更多
相关推荐>>
7楼-- · 2019-01-16 11:33

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

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.

查看更多
登录 后发表回答