proc是block的对象形式,它的行为像是一个block,lambda和proc之间有些细小的差别,lambda更像一个方法,而不是一个block,调用一个proc就像yield一个block,调用一个lambda就像在调用一个方法(当然还是有区别的),在ruby1.9里,你可以使用lambda?来查看这个对象究竟是一个lambda还是一个proc。下面,是proc和lambda的一些区别:
1,Return in blocks,procs,and lambdas
在一个block或proc中执行return,程序将从包含这个block或proc的方法中返回
def test
puts "entering method"
p = Proc.new { puts "entering proc"; return }
p.call # Invoking the proc makes method return
puts "exiting method" # This line is never executed
end
test
#=》
# entering method
# entering block
在一个lambda中执行return,只是从该lambda中返回,在这也可以看出lambda像个方法
def test
puts "entering method"
p = lambda { puts "entering lambda"; return }
p.call # Invoking the lambda does not make the method return
puts "exiting method" # This line *is* executed now
end
test
#=》
# entering method
# entering lambda
# exiting method
2,break in blocks,procs,and lambdas
在一个block或proc中调用break,会使用程序从block或proc中返回到它的iterator,再从它的iterator返回到调用它的方法中,当我们使用Proc.new创建一个proc时,Proc.new是一个iterator,我们使用break,程序将会从这个iterator中返回。这时我们调用这个proc对象,程序已经从它的iterator已经返回了,在一个Proc.new中调用break是没有什么意义的
irb(main):048:0> proc = Proc.new { puts "entering proc"; break }
=> #<Proc:0x8a83984@(irb):48>
irb(main):049:0> proc.call
entering proc
LocalJumpError: break from proc-closure
from (irb):48:in `block in irb_binding'
from (irb):49:in `call'
from (irb):49
from /usr/local/bin/irb:12:in `<main>'
#有点难理解
下一个例子,比较好理解:
def iterator(&proc)
puts "entering iterator"
proc.call # invoke the proc
puts "exiting iterator" # Never executed if the proc breaks
end
def test
iterator { puts "entering proc"; break }
end
test
#=》
# entering iterator
# entering proc
在lambda中调用break效果和return是一样的
3,Other control-flow statements
next: 在block,proc,lambda中表现是一样的,都是从本个yield或都是call中返回到iterator,如果next 后面跟一个表达式,该表达式的值将被作为返回值返回
irb(main):052:0> proc = Proc.new { puts "entering proc"; next }
=> #<Proc:0x89bf070@(irb):52>
irb(main):053:0> proc.call
entering proc
=> nil
irb(main):054:0> proc = Proc.new { next;puts "entering proc" }
=> #<Proc:0x89b58f4@(irb):54>
irb(main):055:0> proc.call
=> nil
irb(main):056:0> a=[1,2,3]
=> [1, 2, 3]
irb(main):057:0> a.each{|x|next if x == 2;puts x }
1
3
=> [1, 2, 3]
redo:一样
retry:不能用在porcs和lambdas中,会产生LocalJumpError
raise:如果在block,proc,lambda中raise一个exception,并且不在该 block,proc和lambda中捕捉异常,异常会传播到调用该block,proc,lambda的方法中。
procs和lambdas的参数传递:这是一个意外收获~
使用yield调用一个block(使用call()调用proc)和调用一个方法非常相似,但是它们是不一样的,
yield语句使用 yield
semantics,它的语法和并行赋值一样,
方法调用使用
invocation semantics
.它没并行赋值那么强大,lambda类似方法,所以它也是采用这个方法调用。
p = Proc.new {|x,y| print x,y }
p.call(1) # x,y=1: nil used for missing rvalue: Prints 1nil
p.call(1,2) # x,y=1,2: 2 lvalues, 2 rvalues: Prints 12
p.call(1,2,3) # x,y=1,2,3: extra rvalue discarded: Prints 12
p.call([1,2]) # x,y=[1,2]: array automatically unpacked: Prints 12
#yield semantics 一切都是自动的,抛弃多余的实参,为没有值的形参赋
#nil,甚至自动打散数组,这在方法(或lambda)中都是需要显示的调用*才行的
l = lambda {|x,y| print x,y }
l.call(1,2) # This works
l.call(1) # Wrong number of arguments
l.call(1,2,3) # Wrong number of arguments
l.call([1,2]) # Wrong number of arguments
l.call(*[1,2]) # Works: explicit splat to unpack the array
总结:proc和lambda在大部分情况下表现是一样的,当遇到return ,break等涉及到控制权变更时才会有些许的不一样,一个简便的方法就是把proc看成类似block的东西,而lambda看成类似方法的东西。
分享到:
相关推荐
The road to Ruby mastery is paved with blocks, procs, and lambdas. To be a truly effective Ruby programmer, it’s not enough just to understand these features—you need to know how to use them in ...
少儿编程scratch项目源代码文件案例素材-我的世界冒险通过 V5.zip
scratch少儿编程逻辑思维游戏源码-火星探测器.zip
少儿编程scratch项目源代码文件案例素材-炫酷音乐.zip
少儿编程scratch项目源代码文件案例素材-跳跃.zip
使用蚁群优化算法求解聚类问题.docx
少儿编程scratch项目源代码文件案例素材-像素小猫.zip
scratch少儿编程逻辑思维游戏源码-废料.zip
少儿编程scratch项目源代码文件案例素材-小绿人 demo.zip
房地产 -洪门湖 旅游项目一期落地方案 .pptx
scratch少儿编程逻辑思维游戏源码-经典版超级玛丽.zip
VID20250429210109.mp4
用Qt5.12.12写的一个计算24点的程序,输入4个任意数字用逗号分隔
少儿编程scratch项目源代码文件案例素材-我的世界 3D场景.zip
少儿编程scratch项目源代码文件案例素材-网格守卫者.zip
scratch少儿编程逻辑思维游戏源码-工厂逃生.zip
2022中德车联网(智能网联汽车)C-V2X量产应用研究报告_中国信息通信研究院&德国汽车工业协会
java基于ssm+jsp珠宝购物网站系统的毕业设计源码+论文
scratch少儿编程逻辑思维游戏源码-回旋镖男孩.zip
scratch少儿编程逻辑思维游戏源码-混乱弹球.zip