Symbols and Variables

To understand the relationship between a symbol and an identifier such as a variable name, take a look at the symbols_2.rb program. It begins by assigning the value 1 to a local variable, x. It then assigns the symbol :x to a local variable, xsymbol:

symbols_2.rb

x = 1
xsymbol = :x

At this point, there is no obvious connection between the variable x and the symbol :x. I have declared a method that simply takes some incoming argument and inspects and displays it using the p method. I can call this method with the variable and the symbol:

def amethod( somearg )
    p( somearg )
end

# Test 1
amethod( x )
amethod( :x )

This is the data that the method prints as a result:

1
:x

In other words, the value of the x variable is 1, since that’s the value assigned to it and the value of :x is :x. But the interesting question that arises is this: If the value of :x is :x and this is also the symbolic name of the variable x, would it be possible to use the symbol :x to find the value of the variable x? Confused? I hope the next line of code will make this clearer:

# Test 2
amethod( eval(:x.id2name))

Here, id2name is a method of the Symbol class. It returns the name or string corresponding to the symbol (the to_s method would perform the same function); the end result is that, when given the symbol :x as an argument, id2name returns the string “x.” Ruby’s eval method (which is defined in the Kernel class) is able to evaluate expressions within strings. In the present case, that means it finds the string “x” and tries to evaluate it as though it were executable code. It finds that x is the name of a variable and that the value of x is 1. So, the value 1 is passed to amethod. You can verify this by running symbols2.rb.

Note

Evaluating data as code is explained in more detail in Chapter 20.

Things can get even trickier. Remember that the variable xsymbol has been assigned the symbol :x.

x = 1
xsymbol = :x

That means that if you eval :xsymbol, you can obtain the name assigned to it—that is, the symbol :x. Having obtained :x, you can go on to evaluate this also, giving the value of x, namely, 1:

# Test 3
amethod( xsymbol )                                      #=> :x
amethod( :xsymbol )                                     #=> :xsymbol
amethod( eval(:xsymbol.id2name))                        #=> :x
amethod( eval( ( eval(:xsymbol.id2name)).id2name ) )    #=> 1

As you’ve seen, when used to create attribute accessors, symbols can refer to method names. You can make use of this by passing a method name as a symbol to the method method and then calling the specified method using the call method:

#Test 4
method(:amethod).call("")

The call method lets you pass arguments, so, just for the heck of it, you could pass an argument by evaluating a symbol:

method(:amethod).call(eval(:x.id2name))

If this seems complicated, take a look at a simpler example in symbols_3.rb. This begins with this assignment:

symbols_3.rb

def mymethod( somearg )
   print( "I say: " << somearg )
end

this_is_a_method_name = method(:mymethod)

Here method(:mymethod) looks for a method with the name specified by the symbol passed as an argument (:mymethod), and if one is found, it returns the Method object with the corresponding name. In my code I have a method called mymethod, and this is now assigned to the variable this_is_a_method_name.

When you run this program, you will see that the first line of output prints the value of the variable:

puts( this_is_a_method_name )  #=> #<Method: Object#mymethod>

This shows that the variable this_is_a_method_name has been assigned the method, mymethod, which is bound to the Object class (as are all methods that are entered as “freestanding” functions). To double-check that the variable really is an instance of the Method class, the next line of code prints out its class:

puts( "#{this_is_a_method_name.class}" )  #=> Method

Okay, so if it’s really and truly a method, then you should be able to call it, shouldn’t you? To do that, you need to use the call method. That is what the last line of code does:

this_is_a_method_name.call( "hello world" )  #=>I say: hello world
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.157.142