ruby 如何用yield_self打破链条

beq87vna  于 2022-12-22  发布在  Ruby
关注(0)|答案(4)|浏览(115)

有可能在ruby中断开yield_self(then)链吗?

"a".then { |str| <break> if break_condition }.then { |str| str << "b" } # => I need "a"
pvcm50d1

pvcm50d11#

您可以将整个代码移到另一个方法中,并使用简单的return“断开”链接:

def foo
  "a".then { |str| return str if break_condition ; str }
     .then { |str| str << "b" }
end

您可以使用catchthrow

catch do |brk|
  "a".then { |str| throw(brk, str) if break_condition ; str }
     .then { |str| str << "b" }
end

或者,您首先不能使用then

str = "a"
str << "b" unless break_condition
6qftjkof

6qftjkof2#

我不认为你可以在不引发异常的情况下“打破”这个链,但是你可以把一个标记值从第一个块传递到第二个块:

"a".
    then { |str| [str, !break_condition] }.
    then { |str,do_it| do_it ? str << "b" : str }

**edit:**另一个可能更易于使用的表单:

"a".
    then { |str| break [str,true] if break_condition; str }.
    then { |str,broken| break str if broken; str << "b" }
xoefb8l8

xoefb8l83#

只需使用一个then就可以重构链,如下所示

result =
  "a".then do |str|
    next str if break_condition
    str << "b"
  end

result =
  "a".then do |str|
    break str if break_condition
    str << "b"
  end
ipakzgxi

ipakzgxi4#

这可能有点傻,但既然不能使用breakreturn,我想应该使用raise

def broken break_condition
  begin
    "a"
      .then { |str| break_condition ? raise(str) : str }
      .then { |str| str << "b" }
  rescue RuntimeError => e
    str = e.message
  end
end

>> broken true
=> "a"
>> broken false
=> "ab"

一个内衬也可以:

>> "a".then { |str| true ? raise(str) : str }.then { |str| str << "b" } rescue $!.message
=> "a"
>> "a".then { |str| false ? raise(str) : str }.then { |str| str << "b" } rescue $!.message
=> "ab"

我能想到的最愚蠢的解决办法:

>> "a".then{@a=_1}.then { |s| s if false }&.then { |s| s << "b" }||@a
=> "a"
>> "a".then{@a=_1}.then { |s| s if true }&.then { |s| s << "b" }||@a
=> "ab"

相关问题