2010-06-15 25 views
5

比方说,我有一个函数了解Ruby的可枚举#地图(更复杂的块)

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

而且我有一个简单枚举阵列

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

,我跑它通过地图,与我功能,使用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] 

是无效的红宝石,并且编译器因为想到它而生气。但是,我将如何实现一个等效的东西,这是有效的?

编辑

在现实中,解决我的问题关系到我比它背后的动机/推理少了很多,帮助我了解更多块红宝石是如何工作的:)

+2

对于它的价值,你可以做甚么?或1.odd?在红宝石> = 1.8.7 – steenslag 2010-06-15 06:57:10

回答

13

你”离得这么近。只需删除return即可,您是金色的。

这是因为传递给map的块是一个proc(即使用Proc.new创建),而不是lambda。在proc中的return不会跳出进程,而是跳出执行该进程的方法(即称为call)。另一方面,拉姆达内的返回仅跳出拉姆达。

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' 

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

+0

是否有任何理由*为什么会发生这种情况?该块是否简单地输出最后执行的命令,如隐式返回? 我问这是因为我想能够预测会发生什么;有这些出来,似乎有点......随机。 – 2010-06-15 01:35:32

+0

简短版本是“这是proc和lambdas之间的区别之一。”工作更好的解释。是的,块会返回最近评估过的表达式。 – x1a4 2010-06-15 01:37:55

+0

感谢您的解释;这是非常彻底的和有益的=) 只是最后一个问题......是否有可能通过lambda作为块?到#map,也许? – 2010-06-15 02:28:15

9

我怀疑这可能是一个重复的问题,而是给一个数值超出块,用安德鲁的回答使用next

simple.map do |n| 
    if n%2 == 0 
    next :even 
    else 
    next :odd 
    end 
end 
+0

嗯,这似乎正是我正在寻找:)谢谢:) – 2010-06-15 04:00:26

3

最短的变体:

simple.map { |n| next :even if n % 2 == 0; :odd } 
+1

更进一步:'simple.map {| N |下一个n%2 == 0? :even::odd}';-) – 2012-10-06 23:06:56