HAL
HAL

Reputation: 451

In ruby, symbols that cannot be replaced by strings?

As far as I understand, symbols are ways to reduce the memory footprint of strings. So functionally :firefox should be equivalent to "firefox" in all cases.

However, in some of the selenium bindings, this doesn't seem to apply.

https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings

driver = Selenium::WebDriver.for :remote, desired_capabilities: :firefox

If I replace :firefox with "firefox" in that call, I get an error. Is the symbol here actually something more than a slightly more memory efficient string?

Upvotes: 2

Views: 95

Answers (3)

Neil Slater
Neil Slater

Reputation: 27207

Strings and Symbols in Ruby are never directly equal. The difference in class is important in more than one way, and

:my_label != "my_label"

However,

:my_label.to_s == "my_label"

A Ruby Symbol is more efficient than a String in a few ways, including:

  • A Symbol hashes and compares faster, which helps when using as hash keys.

  • Multiple uses of the same Symbol do not make copies of the internal data, but are just identical pointers to the same object in memory. This makes them memory efficient when you have a lot with the same value.

If a library, such as Selenium::WebDriver makes use of a Symbol as a parameter, then you cannot always replace it with an equivalent string. Whether or not you can treat it like that depends on the specific library. It is relatively easy to cast Symbols to Strings and vice-versa, so a lot of libraries will do that cast for you. It is very common to have library code that does param = param.to_s when it needs a String param.

Casting from String to Symbol is less commonly found in library code, because for a long while Ruby would not garbage-collect unreferenced Symbol objects - converting arbitrary String values to equivalent Symbol ones was a way of getting memory leaks (and a vector for an attacker to crash your program).

Upvotes: 3

user000001
user000001

Reputation: 33327

To see the difference between a string and a symbol, see the following irb transcript:

irb(main):007:0> "firefox"
=> "firefox"
irb(main):008:0> "firefox".to_sym
=> :firefox
irb(main):009:0> "firefox".class
=> String
irb(main):010:0> "firefox".to_sym.class
=> Symbol

Upvotes: 0

Andrey Deineko
Andrey Deineko

Reputation: 52357

Symbol is a data type.

Selenium::WebDriver.for method accepts arguments, and probably expects the hash values to be symbols. I never worked with the class and don't know whether last argument to for is a hash or kwargs, but you got the idea: datatype matters.

When you pass "wrong" data type, error is raised.

Upvotes: 2

Related Questions