Understanding a Ruby Symbol as a Method Call

class A def test "Test from instance" end class << self def test "Test from class" end end end p A.send(:test) # "Test from class" p A.new.method(:test).call # "Test from instance" 

Here the symbol works as expected, but here:

 s="test" s1=:s p s1 # :s 

why : s printed here? I do not understand the reasons for this. Can someone explain to me?

+8
source share
5 answers

Symbols are light strings (although they are not strings). The send() and method() methods can take strings or characters; one is converted to another in the inner work (not sure which one), and then ruby ​​executes the method with the corresponding name. Therefore, A.send(:text) equivalent to A.text() . If you have a variable called methodName = :text , you can do A.send(methodName) , but not A.methodName() .

Symbols are not variables, so you cannot assign a value to a symbol. In your example, the symbol :s not associated with the variable s (although they have the same "name" preceding it with a colon, makes it a symbol instead of a variable). You assign a string value to s , but you tell it to print the character :s , which it does.

+14
source share

From overflow.site/questions/28944 / ... :

p foo does foo.inspect , i.e. prints the value of inspect instead of to_s , which is more suitable for debugging (because you can, for example, tell the difference between 1 , "1" and "2\b1" , which you cannot print without checking).

+3
source share

You set the value of s1 to: s, so why do you expect it to return something else?

If you look at the ruby ​​API for the Object class, you will see how Object # send and Object # method accept the character as a parameter, so the top example can also be expected.

+2
source share
 s="test" s1=:s p :s.object_id #137448 p s.object_id #77489950 p s1.object_id #137448 

I get it now. I assigned a character, but expected a string.

+2
source share

Characters are just a special type of string that is more efficient for the runtime environment. It. They are not methods or variables or anything like that.

When you execute A.send(:test) , all you do is say, “Hey, A, call a method called“ test. ”You don’t send this method yourself, just a name; this is the logic inside send that is responsible for search for the actual calling method.

The same thing happens when you request a method with A.new.method(:test) . All you go through in the method is the name “test”, not the method defined as “test”. Before method use the name and find the actual method so that it can return it, and this is the return value - the Method object - which you make call on. You cannot make a call on a character like :test , because it's just a name.

0
source share

All Articles