我想要:
将块传递给方法调用,然后
将整个方法调用作为while
循环的条件传递,
即使我不需要在循环内部放置任何逻辑.
具体来说,我有一个数组,我希望#reject!
某些元素来自相当复杂的逻辑.后续调用#reject!
可能会删除先前传递中未删除的元素.当#reject!
最终停止查找要拒绝的元素时,它将返回nil
.此时,我希望循环停止并继续执行程序.
我以为我可以做以下事情:
while array.reject! do |element|
...
end
end
我还没有尝试过它,但是这个构造抛出了vim的ruby语法高亮显示器用于循环(即,它认为第一个do
用于while
语句,并认为第二个end
实际上是封装方法的结束).我也尝试将其重写为while
附加到begin...end
块的内联修饰符,
begin; end while array.reject! do |element|
...
end
但它仍然以同样的方式搞砸了突出显示.在任何情况下,感觉就像是滥用while
循环.
我能想到的唯一方法就是将方法调用指定为proc:
proc = Proc.new do
array.reject! do |element|
...
end
end
while proc.call do; end
虽然有效,但感觉很笨拙,尤其是尾随do; end
.
有没有优雅的方法来实现这一目标?
这不仅仅是vim,while array.reject! do |element|
语法无效:
$ ruby -c -e 'while array.reject! do |element| end' -e:1: syntax error, unexpected '|' while array.reject! do |element| end ^
您可以使用{ ... }
而不是do ... end
:
while array.reject! { |element| # ... } end
或loop
和break
:
loop do break unless array.reject! do |element| # ... end end
更明确一点:
loop do r = array.reject! do |element| # ... end break unless r end
Ruby允许您将条件移动到循环语句的末尾.这样可以很容易地将结果存储在循环内部并根据条件检查它:
begin any_rejected = arr.reject! { … } end while any_rejected
这可以和做的一样end while arr.reject! { … }
,但是在这里发生的事情要清楚得多,特别是在复杂的情况下reject!
.