Ruby:为什么要调用to_ary? [英] Ruby: why does puts call to_ary?

查看:90
本文介绍了Ruby:为什么要调用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-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).

相反,方法printp不调用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆