Hi all,
这个语法是我在 Rails 里发现的:
def f
Module.new &Proc.new
end
M = f do
def self.x
'hello world'
end
end
M.x # => "Hello world"
事实上这个案例可以直接简化成:
def f
Proc.new
end
(f { |name| 'hello, ' + name }).call 'bachue'
# => "hello, bachue"
原来Proc.new
只要不传入 block 就默认自动接受其调用者的 block,这个语法我以前还真的没看到过诶。
不仅仅是Proc.new
,proc
, lambda
也类似,只是有时会出现警告而已,但依然可以工作。
#2 楼 @iBachue 用了 rb_block_proc
的方法都能做的,而用 rb_yield
的就会检查栈帧
foo.c
#include <ruby.h>
static VALUE foo(VALUE self) {
// rb_yield(0);
VALUE p = rb_block_proc();
rb_funcall(p, rb_intern("call"), 0);
return Qnil;
}
void Init_foo() {
rb_define_method(rb_mKernel, "foo", foo, 0);
}
extconf.rb
require "mkmf"
create_makefile 'foo'
执行
ruby extconf.rb
make
ruby -r./foo -e 'def bar;foo;end; bar{puts "the block goes into the inner method"}'
第二种不能算是一个简化,它们是两个不同的实现。
1、返回的是个 Module,我不可以创建实例,可以 include,执行 module_exec 2、返回的是个 Proc 的实例。Proc.new,proc, lambda 它们只是本身有些区别。跟这个用法没关系了。
mark 一下:
3.2 (master) $ ack "Module.new" | ack "&Proc.new" activerecord/lib/active_record/associations/builder/collection_association.rb:27: extension = Module.new(&Proc.new)
Proc.new{ |name| "Hello, " + name }.call 'Leslie'
#10 楼 @zhenjunluo 大概只算是语法糖吧 当你准备写类似于Proc.new { |*args| yield *args }
proc { |*args| yield *args }
lambda { |*args| yield *args }
的时候,就可以写得简单点了。