Digging around a bit more in array.c I uncovered the weirdness described below. In this example Ruby's semantics are either bizzare or just plain broken. It's difficult to understand if and when it's actually possible to override built-in behaviour consistently.
class MyArray < Array def to_s "my array" end end class MyHash < Hash def to_s "my hash" end end a = MyArray.new a[0] = 1 b = Array.new b[0] = 1 c = MyHash.new c[0] = 1 d = Hash.new d[0] = 1 puts a.to_s puts b.to_s puts c.to_s puts d.to_s puts puts [a, b, c, d].join("\n")
Expected output:
my array 1 my hash 01 my array 1 my hash 01
Actual output:
my array 1 my hash 01 1 1 my hash 01
Why does this happen? Because the implementation of Array.join special cases elements of Array to check for infinite recursion but then statically dispatches to the built-in Array.join implementation.
Again, like the problem in my previous entry this is easy to fix. But is this a bug, or just unusual but planned semantics? Unfortunately answering that question and then finding and fixing issues like this is incrediably difficult in a language where the implementation is the only specification.
