假设您有一个Ruby迭代器,它在其块中使用了一个外部方法:
def external_method(n)
n.valid? ? n : next #this "next" expression will result in an error
end
(1..9).map { |i| external_method(i) }
真正的问题是如何从迭代器内部使用的外部方法中break
或next
。
是否可以将next
移动到map
块中?类似这样的东西:
def external_method(n)
n.valid? && n
end
(1..9).map { |i| external_method(i) || next }
顺便说一句,我不确定你问题中的代码只是一个例子还是真实的代码。但在我看来,next
没有任何意义,因为它在块中被调用为最后一个,无论如何,移动到下一个元素都是map
的下一步。
真正的问题是如何从迭代器内部使用的外部方法中
break
或next
。def external_method(n) n.valid? ? n : next end
即使有可能,我也很难理解这种方法的作用。您不应该试图从迭代之外显式地控制迭代。
从外部方法向循环返回有效值怎么样?(不一定是n
,你也可以得到一个修改后的值(
def external_method(n)
yield n if n.valid?
end
(1..9).map do |i|
external_method(i) do |n|
# do something with n
end
end
这样,该块将仅在n.valid?
的情况下执行,否则跳过。您可能需要调整external_method
的返回值才能很好地使用map
。它当前只返回块的结果或nil
。
(1..10).filter_map { |i| i * 2 if i.even? } #=> [4, 8, 12, 16, 20]
(链接文档中的示例(
如果external_method
需要做很多事情,但只有当n
上的一个条件得到满足时,你才能始终返回,除非该条件得到满足,这会产生中断或跳到下一次迭代的效果,因为方法调用是块中唯一的操作:
def external_method(n)
return unless n.even?
puts "running block on #{n}"
end
(1..9).map { |i| external_method(i) }
如果块不仅仅有方法调用,并且根据方法调用中的条件,您希望跳过块的所有其余部分,可以尝试ruby的throw
/catch
:
def external_method(n)
throw :next unless n.even?
end
(1..9).map do |i|
catch(:next) do
external_method(i)
puts "running block on #{i}"
end
end
这两个代码段输出:
running block on 2
running block on 4
running block on 6
running block on 8