Is it possible to break yield_self (then) chain in ruby?
"a".then { |str| <break> if break_condition }.then { |str| str << "b" } # => I need "a"
CodePudding user response:
You could move the whole code into another method and "break" the chain with a simple return
:
def foo
"a".then { |str| return str if break_condition ; str }
.then { |str| str << "b" }
end
You could utilize catch
and throw
:
catch do |brk|
"a".then { |str| throw(brk, str) if break_condition ; str }
.then { |str| str << "b" }
end
Alternatively, you could not use then
in the first place:
str = "a"
str << "b" unless break_condition
CodePudding user response:
I don't think that you can "break" the chain without raising an exception but you can pass a tagged value from the first block to the second one:
"a".
then { |str| [str, !break_condition] }.
then { |str,do_it| do_it ? str << "b" : str }
edit: An other form that might be easier to work with:
"a".
then { |str| break [str,true] if break_condition; str }.
then { |str,broken| break str if broken; str << "b" }
CodePudding user response:
You can refactor your chain with using just one then
like this
result =
"a".then do |str|
next str if break_condition
str << "b"
end
or
result =
"a".then do |str|
break str if break_condition
str << "b"
end
CodePudding user response:
This might be silly, but since you can't break
or return
, I guess raise
should do it:
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"
One liner works too:
>> "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"
Best silly solution I could come up with:
>> "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"