Is my assumption correct that Ruby does not call the to_s or to_str method when interpreting a String object during string-interpolation?
a = "Hallo"
class String
def to_s
"Servus"
end
end
def a.to_s
"Servus"
end
puts "Hier sagt man #{a}"
=> Hier sagt man Hallo
Is it more efficient to check if an object is a String than to simply call the to_s method?
Is my assumption correct that Ruby does not call the
to_sorto_strmethod when interpreting aStringobject during string-interpolation?
It is correct.
The test you provided doesn't rule out the possibility that the parser took a shortcut by recognizing that a was assigned to a string literal. Here's a test that does:
a = "Hallo"
class String
def to_s
"Servus"
end
end
def a.to_s
"Servus"
end
test_string = 'puts "Hier sagt man #{' + 97.chr + '}'
eval(test_string) # => Hier sagt man Hallo
Now, Ruby doesn't actually do any kind of "local variable is a literal string" automatic substitution, because Ruby is so dynamic that the value of a could be updated in any of the following lines of code without the parser knowing. But if you didn't already know for sure that that's the case, a test like the above guarantees it.
Is it more efficient to check if an object is a
Stringthan to simply call theto_smethod?
Here's another interesting test, which shows that Ruby (at least C Ruby) isn't using some secret shortcut to check if it's exactly a String, but is rather using something more like is_a?:
class Foo < String
def to_s
"foo"
end
def to_str
"foo"
end
end
a = Foo.new("initial value")
puts "a: #{a}"
#=> a: initial value
If we had seen a: foo instead, we would know that a very simple (and presumably more efficient) check was used, and was unable to recognize that the Foo object was an instance of a String subclass.
Given the above, we've ruled out the possibility that the test for String is a simple test optimized for exactly String classes. Without examining the code in every Ruby implementation, there a few other things we know for sure:
is_a? method call to identify whether an object is an instance of a String subclass.is_a?, because it can just use rb_obj_is_kind_of for any object type.to_s and to_str causes at least 1 or 2 method lookups. Actually calling them causes an unknown number of method lookups and additional calls.to_s or to_str actually returns a string, so the is_a? check has to be repeated.Considering these things, we can say that it's at least twice as efficient to check if the object is a String as to call to_s or to_str without checking first, and on average it's likely much more efficient.