13
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 symbol works as expected, but here:

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

why :s is printed here?? I dont understand the reason behind it. Can anyone please explain for me ?

sunny1304
  • 1,684
  • 3
  • 17
  • 30

5 Answers5

18

Symbols are sort of lightweight strings (though they are not strings). The send() and method() methods can take strings or symbols; one is converted to the other in the inner workings (not sure which) and then ruby executes the method with the matching name. Hence A.send(:text) is equivalent to A.text(). If you had a variable named methodName = :text, you could do A.send(methodName) but not A.methodName().

Symbols are not variables, so you can't assign a value to a symbol. In your example, the symbol :s is unrelated to the variable s (despite the fact that they have the same "name", preceding it with a colon makes it a symbol instead of a variable). You're assigning a string value to the variable s but telling it to print the symbol :s, which it does.

4

Symbols are just a special kind of stringlike value that's more efficient for the runtime to deal with than a regular string. That's it. They aren't methods or variables or anything like that.

When you do A.send(:test), all you are doing is saying "hey, A, call the method named 'test'". You aren't sending the method itself, just the name; it's the logic inside send that is responsible for looking up the actual method to call.

The same thing goes when you ask for method with A.new.method(:test). All you are passing to method is the name "test", not the method defined with that name. It's up to method to use the name and find the actual method so it can return it, and it's that return value - a Method object - that you are doing call on. You can't do call on a Symbol like :test, because it's just a name.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
3

From https://stackoverflow.com/a/1255362/509710:

p foo does puts foo.inspect, i.e. it prints the value of inspect instead of to_s, which is more suitable for debugging (because you can e.g. tell the difference between 1, "1" and "2\b1", which you can't when printing without inspect).

Community
  • 1
  • 1
TheDude
  • 3,796
  • 2
  • 28
  • 51
3
s="test"
s1=:s
p :s.object_id  #137448
p s.object_id   #77489950
p s1.object_id  #137448

I have understand it now. I was assigning a symbol but expecting a string.

sunny1304
  • 1,684
  • 3
  • 17
  • 30
2

You set the value of s1 to be :s, so why would you expect it to return anything different?

If you look at the ruby API for the Object class, you will see both Object#send and Object#method take a symbol as a parameter, so the top example is also totally expected.

DanSingerman
  • 36,066
  • 13
  • 81
  • 92