Ruby:为什么要调用to_ary? [英] Ruby: why does puts call to_ary?
问题描述
我正在学习Ruby中的元编程,只是尝试通过method_missing和define_method定义缺少的方法.我收到一些意想不到的行为,想知道是否有人可以解释这一点.这是我的课程:
I'm learning metaprogramming in Ruby and am just trying out defining missing methods via method_missing and define_method. I'm getting some unexpected behaviour and am wondering if anyone can explain this. Here is my class:
class X
def method_missing(m, *args, &block)
puts "method #{m} not found. Defining it."
self.class.send :define_method, m do
puts "hi from method #{m}"
end
puts "defined method #{m}"
end
end
现在,此代码:
x = X.new
x.some_method
puts
x.some_method
puts
puts x
产生输出:
method some_method not found. Defining it.
defined method some_method
hi from method some_method
method to_ary not found. Defining it.
defined method to_ary
#<X:0x007fcbc38e5030>
我没有得到的是最后一部分:为什么Ruby在看跌期权的调用中调用to_ary? Ruby为什么会尝试将我的对象转换为数组以打印它?
What I don't get is the last part: why is Ruby calling to_ary in a call to puts? Why would Ruby try to convert my object into an array just to print it?
我已经在Google周围搜索了,找到了以下相关链接:
I've Googled around and found these related links:
- http://tenderlovemaking.com/2011/06/28/til-its-ok-ok-to-nil-from-to_ary/
- http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
- http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary/
- http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
这些还讨论了method_missing和to_ary陷阱,但没有专门讨论为什么puts会调用to_ary.
These also talk about method_missing and to_ary gotchas, but not specifically about why puts would call to_ary.
我还应该提到,当我定义to_s时,行为不会改变,例如
I should also mention that the behaviour does not change when I define a to_s, e.g.
def to_s
"I'm an instance of X"
end
则"puts x"的输出为:
The output of "puts x" is then:
method to_ary not found. Defining it.
defined method to_ary
I'm an instance of X
推荐答案
puts
是$stdout.puts
的同义词. $ stdout是一个IO
类,因此请查看
puts
is a synonym for $stdout.puts
. $stdout is an IO
class, so look at the documentation for IO.puts:
与IO#print一样,将给定的对象写入ios.写一条记录 分隔符(通常是换行符)后的任何未结尾为 换行符序列.如果使用数组参数调用,则写入每个 元素换行.
Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line.
这意味着puts
方法旨在写几行输出.因此,它尝试在对象上调用to_ary
方法,如果定义了to_ary
,则在新行上打印返回的Array
的每个元素,否则puts
调用to_s
方法.
This mean that puts
method is intended to write several lines of output. Thus it tries to call to_ary
method on an object and if to_ary
is defined, then prints each element of the returned Array
on a new line, else puts
calls to_s
method.
to_ary
的内部用法确实没有在Ruby文档中得到很好的记录(Matz在他的 The Ruby Programming Language 书中指出了这一点).
to_ary
internal usage is really not well documented in the Ruby documentation (Matz points this out in his The Ruby Programming Language book).
相反,方法print
和p
不调用to_ary
,仅调用to_s
.
Methods print
and p
on the other hand don't call to_ary
, only to_s
.
Sidenote :有趣的是,to_ary
必须返回真实的Array
对象,而不是定义each
方法或其他内容的对象:
Sidenote: Interesting, that to_ary
must return real Array
object, not an object defining each
method or something else:
class Test
def to_ary
10.downto(1)
end
end
puts Test.new
#TypeError: can't convert Test to Array (Test#to_ary gives Enumerator)
# from (irb):28:in `puts'
# from (irb):28:in `puts'
# from (irb):28
这篇关于Ruby:为什么要调用to_ary?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!