了解Ruby可枚举#map(具有更复杂的块)

Jus*_* L. 5 ruby language-features enumerable

假设我有一个功能

def odd_or_even n
  if n%2 == 0
    return :even
  else
    return :odd
  end
end
Run Code Online (Sandbox Code Playgroud)

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

simple = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

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

simple.map do
  |n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]
Run Code Online (Sandbox Code Playgroud)

如果不首先定义函数,我怎么能这样做呢?例如,

# 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]
Run Code Online (Sandbox Code Playgroud)

是不是有效的ruby,编译器甚至在考虑它时会生我的气.但是我如何实现同等类型的东西呢?

编辑

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

x1a*_*1a4 13

你真是太近了 只需删除returns,你就是金色的.

这是因为传递给的块map是proc(即创建的Proc.new),而不是lambda.一return一个进程内不只是跳出它跳出的是执行的方法(即所谓的的PROC- callON)的PROC.另一方面,lambda内的返回仅跳出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'
Run Code Online (Sandbox Code Playgroud)

从中学到的教训是使用隐式返回,除非你不能,我想.


And*_*imm 9

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

simple.map do |n|
  if n%2 == 0
    next :even
  else
    next :odd
  end
end
Run Code Online (Sandbox Code Playgroud)