The line...
Code: Select all
options_hash.each{|key,val| eval("@#{key}=val")}
...converts all hash entries into normal instance variables. e.g.
options[:hello] creates an instance variable called
@hello with the key's value assigned to it. The symbols can't be used directly in this case, so the little 'eval' trick is used to create normal instance variables.
EDIT) He he, you beat me to it!
Symbols are a rather strange kind of object - they don't "contain" anything, and can't be used as variables, only as values. They are closely related to Strings, but unlike a String they can never be edited, and have hardly any methods that you can use on them.
More importantly, there is only ever one instance of a symbol...
For example,
@a = "Hello" and
@b = "Hello", may look like the same String, but they are most likely two separate String objects being held in different places in the PC's memory - so you can edit them independently.
OTOH,
@a = :hello and
@b = :hello gives you two variables pointing at the same Symbol object, because there can only ever be one Symbol object called
:hello - no matter where you put it in your code, a reference to
:hello will always point at that same object.
That's why using Symbols can speed up 'if' and 'case' methods, and also Hash lookups. To check if two Strings are the same, Ruby has to check each and every letter. But Symbols are like class and method names - unique identifiers that the Ruby interpreter can replace with "ID codes". To compare two symbol references, Ruby just has to check "are these the same object" - there's no "content" to scan through, so it is much faster than Strings would be.
That might seem odd when you consider that Ruby is an interpreted language - surely it has to parse the letters anyway? But Ruby uses a much faster technique called a "Just In Time" (JIT) compiler - because methods usually get called many times, it only parses the text once, and then remembers the commands as "byte code"; just numbers that are much faster to run the second time around. As symbols can never be edited, they can also be encoded like this.
In fact, class and method names in Ruby code pretty much
are Symbols - they all end up in the same 'library' that the Ruby interpreter uses for parsing the code. For example...
...will produce an Array containing Symbols - each Symbol being the name of a method that you can use on String objects.
...or...
...tells you whether or not the object in @variable has a method called 'split' - so true for a String, but false for an Integer.
So the best way to think of Symbols is just as 'labels' that you can 'tag' things with, like the keys of a Hash, or a selection that has been made (e.g.
@current_state = :waiting .... if @current_state == :ready ...).