本地同时运行多个Rails App时同时监听80端口的办法
安装Rails 4.0 beta

Ruby中将代码块作为参数传入方法的几种方法及其区别

bachue posted @ 2012年12月13日 22:41 in Ruby with tags ruby proc lambda block , 7603 阅读

这篇文章只是随手写写玩玩的,我对Ruby的Block和Lambda其实理解并不怎么深刻,知识现在够用就差不多了吧。

第一种方法最传统了:

def f1(a)
  yield a
end

f1(1){|a| a.to_s} # "1"
f1(1, &:to_s) # "1" 

这种方法要求传入一个block,但是不传入也可以,可以用block_given?方法判断是否被传入了block。在第二个示例中虽然看上去要求是一个参数,但是再传入一个block并不会出错,&:to_s是{|a| a.to_s}这个block的简写

下面是第二种方法:

def f2(a, &b)
  b[a]
end

f2(1){|a| a.to_s} # "1"
f2(1, &:to_s) # "1"

这种方法和前一种其实效果一致,虽然看上去要求两个参数,但是block依旧是可选的,如果不传也不会出错,一样可以用block_given?方法判断是否被传入了block。唯一的区别就是这种方法可以为传入的block赋个值,以便于在再传给另外一个方法作为参数。

下面是第三种方法:

def f3(a, b)
  b[a]
end

f3(1, lambda{|a| a.to_s}) # "1"
f3(1, :to_s.to_proc) # "1"

这种方法虽然和第二种方法只有一个字符之差,但其实天差地远,b不能被传入一个block,无论是{|a| a.to_s}还是&:to_s都将被视为错误,它必须被传入一个lambda。因此在示例中我用两种方法创建了lambda,注意第二个示例其实是第一个示例的简写,在Ruby中&:to_s只能创建block,而:to_s.to_proc则可以创建proc对象(这里有件更加神奇的事,可以通过hack to_proc修改这个方法的返回值,但是依然要求必须是Proc对象,并且无法通过hack这个Proc对象的call方法或是[]方法修改它的执行行为,并且写在这个Proc中的return,next,break的语意也只按proc的语意处理,下面会提及)。至于proc,lamdba和block三者的差异?lamdba和proc其实差别很小,主要差异在binding和参数传递上,不过lambda {|a| a.to_s}其实也返回一个Proc对象,而lambda和block的区别主要是返回方法不一致,这个在很多Ruby书中都有详细介绍。但是它们其实可以相互转换,看下列代码:

def f4(a, &b)
  f3(a, b)
end

f4(1, &:to_s) # "1"

def f5(a, b)
  f1(a, &b)
end

f5(1, :to_s.to_proc) # "1"

可以看到在第一个示例中,一个方法调用时传入的block参数在方法内部会被当作成proc对象,因而f3也可以接受。而在第二个示例中,一个proc对象前面加上&符号跟在方法后面就被当作block,很有意思吧。更有意思的是,似乎无论怎么转换,代码块中return,next,break语句的语意似乎并不改变,几次试验下来都是如此,这点我至今还是没有想通。例如:

def f6(&b)
  puts "class of b is: #{b.class.inspect}"
  3.times {b.call}
end

def f7(b)
  puts "class of b is: #{b.class.inspect}"
  3.times {b.call}
end

f6 {puts 1; break}
# output:
# class of b is: Proc
# 1

f7 lambda {puts 1; break}
# class of b is: Proc
# 1
# 1
# 1

可以看到虽然都是在方法中调用代码块,并且在方法中b都是proc对象,代码内容也完全一致,但是由于f6传入的block形式而f7中传入的lambda形式,因此最后的结果存在差异。证明了break的语意并没有因为都转换成了proc对象而发生转变。

NCERT Social Questio 说:
2022年9月27日 00:42

Social Science or Social Studies including Geography, History, Civics, and Economics is called as Social in the Secondary Education Class 9th Standard Curriculum. NCERT has published learning and study material for all topics of the course to all regional students of Class 9th standard studying at Hindi Medium, NCERT Social Question Paper Class 9 English Medium and Urdu Medium Schools of the country to the academic year of 2023.Social Science or Social Studies including Geography, History, Civics, and Economics is called as Social in the Secondary Education Class 9th Standard Curriculum.

seo service london 说:
2024年1月16日 15:02

We need many stories, Like genuinely appreciated, You want addiitional data over it, mainly because it can be reasonably exceptional., Take care exclusively for declaring


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter