5

假设我有一个功能

def odd_or_even n
  if n%2 == 0
    return :even
  else
    return :odd
  end
end

我有一个简单的可枚举数组

simple = [1,2,3,4,5]

我通过 map 运行它,使用我的函数,使用 do-end 块:

simple.map do
  |n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]

如果不首先定义函数,我怎么能做到这一点?例如,

# does not work
simple.map do |n|
  if n%2 == 0
    return :even
  else
    return :odd
  end
end

# Desired result:
# => [:odd,:even,:odd,:even,:odd]

不是有效的 ruby​​,编译器会因为我考虑它而生我的气。但是我将如何实现一种等效的东西,这行得通?

编辑

实际上,我的问题的解决方案对我来说比它背后的动机/推理要重要得多,以帮助我更多地了解 ruby​​ 块是如何工作的 :)

4

3 回答 3

13

你是如此接近。只需删除returns,您就可以了。

这是因为传递给的块map是 proc(即用 创建Proc.new),而不是 lambda。一个return过程中的一个不只是跳出过程——它跳出执行(即调用call)过程的方法。另一方面,lambda 中的 return 只跳出 lambda。

proc方法在 Ruby 1.8 中返回一个 lambda,在 Ruby 1.9 中返回一个 Proc。最好不要使用此方法,并明确您要使用的构造。

我猜你在尝试这个时要么使用 IRB,要么使用普通的 ruby​​ 脚本。

a = Proc.new { return }
a.call # fails. Nothing to return from.

def foobar
  a = Proc.new { return }
  a.call
  puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.

b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.

def bazquux
  b = lambda { return }
  b.call
  puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'

从中吸取的教训是使用隐式返回,除非你不能,我猜。

于 2010-06-15T01:30:10.597 回答
9

我怀疑这可能是一个重复的问题,但是要从块中给出一个值,请使用next

simple.map do |n|
  if n%2 == 0
    next :even
  else
    next :odd
  end
end
于 2010-06-15T03:13:05.953 回答
3

使用安德鲁答案的最短变体:

simple.map { |n| next :even if n % 2 == 0; :odd }
于 2012-05-05T21:00:27.767 回答