I just learned two interesting Ruby edge-case behaviours

by Jared Norman
published December 07, 2022

This month Kevin Newton is doing a blog series on YARV, CRuby’s virtual machine. If you want to check it out, it begins here. I’m following along and I learned a couple of neat edge case behaviours from part 5.

His explanation of the anytostring instruction highlights the fact that if you implement a “bad” to_s method, one that doesn’t return a string, Ruby will fall back to the default Object#to_s behaviour:

irb(main):001:1* class A
irb(main):002:2*   def to_s
irb(main):003:2*     12
irb(main):004:1*   end
irb(main):005:0> end
=> :to_s
irb(main):006:0> "foo #{A.new} bar"
=> "foo #<A:0x0000000151ae5ce8> bar"

Additionally, the section on splatarray shows off the edge case where you try to splat something that isn’t an array and can’t be converted to one. In this case, the object will be wrapped in an array, so that Ruby can be sure that it’s dealing with an array.

irb(main):007:1* def foo(*args)
irb(main):008:1*   puts args.inspect
irb(main):009:0> end
=> :foo
irb(main):010:0> foo(*A.new)
[#<A:0x00000001519b9e00>]
=> nil

If you’d asked me yesterday what the above code did, I’d have guessed that it raised a NoMethodError.