2014-10-29 63 views
1

我正在写一个库迭代一个集合,并调用集合中每个项目的调用者的proc。例如:如何检测何时在调用者Proc中调用“break”?

def self.each(&block) 
    # ... load some data into results_array 
    results_array.each do |result| 
     status = block.call(result) 
     # how do I know to call break if the user calls break? 
     break if status == false 
    end 
end 

目前,你可以在我的代码中看到的,我检查,以打破“最后评估表达”。这看起来很容易出错,因为最终用户可能有一个完美有效的理由,将他们的最后一个表达式评估为false。更合适的是使用“break”来检测来电者。

如何知道如果用户呼叫休息时打电话休息?

回答

0

如果使用yield而不是block.call,您可以使用nextbreak之间的行为差​​异。举个例子:

def each(&block) 
    puts "before" 
    result = yield 
    puts "after" 

    result 
end 

each do 
    puts "hello" 
    next 
end 

# Result: 
# before 
# hello 
# after 

each do 
    puts "hello" 
    break 
end 

# Result: 
# before 
# hello 

正如你可以看到,当您使用next块内,控制返还给函数调用的块。但是,如果您使用break,则调用函数将立即返回nil作为返回值。现在,您可以利用此行为的一些技巧:

def each(&block) 
    # ... 

    results_array.each do |result| 
    block_result = yielder(result, &block) || {:status => :break, :value => nil} 
    if block_result[:status] == :break 
     # block has called break 
     #... 
    else 
     # block has called either next or the block has finished normally 
     #... 
    end 
    end 
end 

def yielder(*args, &block) 
    value = yield *args 
    {:status => :normal, :value => value} 
end 

这工作,因为在这里,yielder功能的情况下,block称为break或状态和块的返回值的哈希返回要么nil。因此,您可以区分有效结果(始终与nil不同)和总是nil的特殊结果。

0

这应该工作,除非我不明白你正在尝试做的:

def each(&block) 
    # ... load some data into results_array 
    results_array= [1, 2, 3] 
    results_array.each do |result| 
    block.call(result) 
    end 
end 


each do |result| 
    puts result 
    break 
end 
相关问题