Ruby 关于 Ruby 中 return 的一些疑问

jasonliu · 2015年06月05日 · 最后由 africwildman 回复于 2015年06月06日 · 3782 次阅读

在 ruby 中,return 的作用是从方法中返回一个或多个值,所以如果直接从块中 return 是会报错的:

[1.2].each { |e| return e } => LocalJumpError: unexpected return

如果把块包裹在方法中就不会报错:

def a
    [1.2].each { |e| return e }
end

但是从 Proc 和 lambda 中却可以使用 return:

Proc.new { return 1 }
=> #<Proc:0x007fb39408b0e8@(irb):6>
lambda { return 1 }
=> #<Proc:0x007fb39408dac8@(irb):7 (lambda)>

但 Proc 和 lambda 并不是方法啊,难道 Proc 和 lambda 中的 return 与方法中的 return 的含义是不同的么?

Proc 里的 return 是当你调用这个 Proc 时,从调用的作用域 return lambda 里的 return 是当你调用这个 lambda 时,只是返回 lambda 值,不会 return

Proc, lambda 是不同的 lambda 更像是方法,return 就跟函数中 return 一样, proc 则有些不同,proc 中 return,break 则是从代码块绑定的作用域中返回, 第一个中,proc 绑定的环境为全局环境(或者是 main)这个具体的不太清楚 第二个中,proc 绑定的为 a 函数 proc, lambda 是延时执行的,只有 call 的时候才会起作用

Proc.new { return 1 } 是会有异常的,只是你没 call 而已。

@mingyuan0715 非常好的帖子,很有帮助,非常感谢

#1 楼 @chaucerling 原来我也以为是从调用的 scope 跳出,其实是从 proc 的定义处跳出

def double(callable_object) 
  callable_object.call * 2
end

def p
  Proc.new { return 10 }
end

double(p)

代码出自 Metaprogramming Ruby, 这段代码会出错误unexpected return (LocalJumpError),原因是 call proc 的时候会从 proc 定义出 return,但是定义 proc 的 p 方法已经 return 了,所以 LocalJumpError

也就是说程序执行到 double(p) 的时候试图从 p 的作用域中返回,但是它现在处于 double 的作用域,而 double 只能从自己当前的作用域中返回,由于 ruby 中的作用域是相互不可见的,所以会出错,这样理解对么?

如果 Proc 的定义和方法是在同一作用域,Proc 的行为类似于向方法中插入一个代码片段,而 lambda 的行为更像是方法,在方法中使用 lambda 就像调用其他的方法一样,不管是否显示的 return,和当前的作用域都没有关系

不错,一早起来学到新知识。以前没有深究过 proc lambda 的区别。

11 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号