and*_*ich 8 ruby metaprogramming ruby-1.9 ruby-1.8
我知道我可以使用动态定义类的方法define_method,并且我使用块的arity指定此方法所使用的参数.
我想动态定义一个接受可选参数和块的方法.在Ruby 1.9中,这很容易,因为现在允许将块传递给块.
不幸的是,Ruby 1.8不允许这样做,所以以下内容不起作用:
#Ruby 1.8
class X
define_method :foo do |bar, &baz|
puts bar
baz.call if block_given?
end
end
x = X.new
x.foo("foo") { puts "called!"} #=> LocalJumpError: no block given
Run Code Online (Sandbox Code Playgroud)
替换显式block.call,yield也不能解决问题.
遗憾的是,升级到Ruby 1.9对我来说不是一个选择.这是一个棘手的问题,还是有办法绕过它?
这适用于Ruby 1.8.7,但不适用于1.8.6:
class X
define_method(:foo) do |bar, &baz|
puts bar
baz.call if baz
end
end
Run Code Online (Sandbox Code Playgroud)
测试:
X.new.foo("No block")
X.new.foo("With block") { puts " In the block!"}
p = proc {puts " In the proc!"}
X.new.foo("With proc", &p)
Run Code Online (Sandbox Code Playgroud)
得到:
No block
With block
In the block!
With proc
In the proc!
Run Code Online (Sandbox Code Playgroud)
(用1.8.6给出syntax error, unexpected tAMPER, expecting '|'.)
如果你想要可选参数以及阻止,你可以尝试这样的事情:
class X
define_method(:foo) do |*args, &baz|
if args[0]
bar = args[0]
else
bar = "default"
end
puts bar
baz.call if baz
end
end
Run Code Online (Sandbox Code Playgroud)
测试:
X.new.foo
X.new.foo { puts " No arg but block"}
Run Code Online (Sandbox Code Playgroud)
得到:
default
default
No arg but block
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4887 次 |
| 最近记录: |