I’m reading the book “Programming Ruby 1.9 & 2.0” by Dave Thomas, and the Chapter “Standard Protocols and Coercion” explain it but I didn’t understand it.
Why are there 2 versions of conversion to the same datatype?
Why are there to_a and to_ary instead of only one of those? or to_s and to_str?
As an example, you can see in the following code how depending of the context, sometimes Ruby uses to_a and some times to_ary.
class A
def to_ary
[1, 2]
end
def to_a
[3, 4]
end
end
o = A.new
a, b = o
puts a, b # outputs 1, 2
a, b = *o
puts a, b # outputs 3, 4
I think you are highlighting that the splat operator can be used with things that are not arrays, and for those objects an equivalent array must be made by calling to_a.
For example, if you replace o with a range, you need the splat to get the multiple assignment of elements, because only then is the range converted to an array:
2.7.1 :022 > a, b = (1..2)
2.7.1 :023 > a
=> 1..2
2.7.1 :024 > b
=> nil
2.7.1 :025 > a, b = *(1..2)
2.7.1 :026 > a
=> 1
2.7.1 :027 > b
=> 2
to_ary and to_a should return the same thing for an array (self). You have made the two methods return different things, which highlights how splat works: class Array - RDoc Documentation
Why are there 2 versions of conversion to the same datatype?
I think the intentions are different. to_a is a real conversion, and forces an array to be returned; it exists on several classes (e.g. through Enumerable). to_ary is for classes that are ‘array-like’ enough to be treated as arrays in themselves.
For example, the range (1…2) does not respond to to_ary, and hence is not array-like enough to be split for the multiple assignment. However, the range does respond to to_a, and then it is converted into an array.
So if you were writing a new class, you might want to implement to_a, because it makes sense to convert your instance into an array. But you would only implement to_ary if, in some sense, your class is a kind of array.
For example, Time has a to_a method, because it makes sense to return its data in an array form. But it does not have a to_ary method, because it is not, in itself, array-like.
(to_ary feels like a type check to me: does this instance respond to to_ary? If so, then it’s an ‘array-like’ object.)
2 Likes
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.