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_s
orto_str
method when interpreting aString
object 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
String
than to simply call theto_s
method?
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.