ruby中的return

在ruby中,有三个关键字可以从一段代码中返回,分别是returnnextbreak,今天主要研究一下return。

方法中的return

在ruby中调用一个方法,默认的情况下,会一行一行依次执行方法中的代码,方法的值是最后一行的值。

return可以改变这个方法一行一行执行的行为,当遇到return,方法会直接返回(rescue、ensure例外)。

def test
  puts 'first puts'
  return
  puts 'next puts'
end

在上面这个例子中,puts 'next puts'这行代码永远不会执行。同时我们可以显示指定返回值,默认为nil。例如上面这个例子没有指定返回值,其返回值则为nil。

proc中的return

代码胜千言,先看几个例子:

def test1
  proc = Proc.new { return 10 }
  puts 'puts here'
end

def test2
  proc = Proc.new { return 10 }
  proc.call
  puts 'puts here'
end

def test3
  return 10
  puts 'puts here'
end

test4 = Proc.new { return 10 }
test4.call

在上面的例子中:

  • test1方法,puts 'puts here'能够执行,返回值为最后一行代码的返回值。

  • test2方法,返回值为10。

  • test3方法的行为和test2是等价的。

  • test4在call调用的时候会报错,错误信息是:LocalJumpError: unexpected return;

为什么会这样,其实test2test3已经告诉我们答案了,在proc中使用 return 和在方法本身中使用return的效果是一样的。

test4的例子就相当于你直接执行return 10,报的错误也同样是:LocalJumpError: unexpected return

LocalJumpError这个错误其实很有意思,如果拦截这个错误,是依然可以拿到return的返回值的。 下面是我在pry中做的实验。

return 10
#=> LocalJumpError: unexpected return

_ex_
#=> <LocalJumpError: unexpected return>

_ex_.class
#=> LocalJumpError < StandardError

_ex_.exit_value
#=> 10

_ex_.reason
#=> :return

lambda 中的return

还是继续看例子:

test1 = -> { puts 'first puts'; return 10; puts 'next puts' }
test1.call

# first puts
#=> 10

def test2
  la = -> { puts 'first puts'; return 10; puts 'next puts' }
  la.call
  puts 'puts here'
end

# first puts
# puts here
#=> nil

lambda对象,跟proc对象不一样,在lambda中,return是从lambda代码块中返回。在proc中,return是从proc代码块所在的上下文环境中返回。