当我实现此代码时:
class String
def method_missing(meth,*args, &block)
if self.chars.respond_to? meth
self.chars.send meth, *args, &block
else
super
end
end
def respond_to?(meth)
if self.chars.respond_to? meth
true
else
super
end
end
end
Ruby陷入flatten
。即使需要另一个文件内部调用flatten
,它也会挂起。我甚至试过这个:
class String
def method_missing(meth,*args, &block)
if meth.to_sym == :flatten
super
elsif self.chars.respond_to? meth
self.chars.send meth, *args, &block
else
super
end
end
def respond_to?(meth)
if meth.to_sym == :flatten
super
elsif self.chars.respond_to? meth
true
else
super
end
end
end
但是会出现同样的结果。内部发生了什么导致flatten
失败?
这里是错误输出:
2.1.2 :003 > require 'mygem'
=> true
2.1.2 :004 > require 'pry'
^CIRB::Abort: abort then interrupt!
from /home/user/dev/MyGem/lib/mygem/string_method_missing.rb:17:in `call'
from /home/user/dev/MyGem/lib/mygem/string_method_missing.rb:17:in `respond_to?'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/requirement.rb:112:in `flatten'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/requirement.rb:112:in `initialize'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/requirement.rb:70:in `new'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/requirement.rb:70:in `default'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/dependency.rb:260:in `merge'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/specification.rb:1323:in `block in activate_dependencies'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/specification.rb:1306:in `each'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/specification.rb:1306:in `activate_dependencies'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/specification.rb:1288:in `activate'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems.rb:194:in `try_activate'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:132:in `rescue in require'
from /home/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:144:in `require'
from (irb):4
from /home/user/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
它严格地适用于任何变平的字符串数组。
2.1.2 :005 > [1,2,3].flatten
=> [1, 2, 3]
2.1.2 :006 > ["1","2","3"].flatten
^CIRB::Abort: abort then interrupt!
from /home/user/dev/MyGem/lib/mygem/string_method_missing.rb:17:in `call'
from /home/user/dev/MyGem/lib/mygem/string_method_missing.rb:17:in `respond_to?'
from (irb):6:in `flatten'
from (irb):6
from /home/user/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
更新 我已更新评论中建议的修补程序的代码。问题仍然存在。我期待着答案。
如果我告诉它有多深,那么Flatten似乎有效。所以这似乎表明在字符串对象上展平数组时存在无限循环。例如:2.1.2 :013 > ["1","2","3"].flatten(0)
=> ["1", "2", "3"]
2.1.2 :021 > ["1","2","3"].flatten(8)
=> ["1", "2", "3"]
2.1.2 :022 > ["1","2","3"].flatten(9)
=> ["1", "2", "3"]
如何避免无限循环仍然执行此method_missing?这将有助于知道什么测试变平对内部对象的调用,因此我可以在字符串中定义它并避免循环。
答案 0 :(得分:0)
没有内置的帽子。因此,通过method_missing将所有内容重定向到String中的字符会创建一个类似于Array的对象,这将导致flatten方法无限循环。
添加此项,这是一个有效的解决方案:
class Array
# To fix a bug that our method_missing creates
# we need to set a MAXIMUM for FLATTEN
alias_method :_old_flatten, :flatten
alias_method :_old_flatten!, :flatten!
def flatten(level = 99)
_old_flatten(level)
end
def flatten!(level = 99)
_old_flatten!(level)
end
end