
Issue #21515 has been updated by lpogic (Łukasz Pomietło). jeremyevans0 (Jeremy Evans) wrote in #note-6:
Not sure why the local variable declaration would matter, as long as you don't pick one already in use.
Because you have to write it twice. And coming up with names can be tedious. Especially for trivial and repetitive patterns like this one. jeremyevans0 (Jeremy Evans) wrote in #note-6:
```ruby def my_calculation(a, b) a == b || nil end
def t(a, b) my_calculation(a, b)&.then{return it} proc{} end
before = {} after = {}
cases = [[1, 1], [1, 2]] GC.start GC.disable cases.each do |a, b| ObjectSpace.count_objects(before) c = t(a, b) ObjectSpace.count_objects(after) # Procs have T_DATA internal type p [a, b, c, after[:T_DATA] - before[:T_DATA]] end ```
Indeed, you are right. Anyway, the "&.then" option does extra work, making it a bit slower: ```rb require 'benchmark' def my_calculation(a, b) a + b end def calculate_with_if x = my_calculation(1, 1); return x if x end def calculate_with_and x = my_calculation(1, 1) and return x end def calculate_with_then my_calculation(1, 1)&.then{ return it } end n = 10_000_000 Benchmark.bmbm do |x| x.report("x = my_calculation(1, 1); return x if x") { n.times{ calculate_with_if } } x.report("x = my_calculation(1, 1) and return x") { n.times{ calculate_with_and } } x.report("my_calculation(1, 1)&.then{ return it }") { n.times{ calculate_with_then } } end ``` ``` user system total real x = my_calculation(1, 1); return x if x 0.954000 0.000000 0.954000 ( 0.947969) x = my_calculation(1, 1) and return x 0.968000 0.000000 0.968000 ( 0.970023) my_calculation(1, 1)&.then{ return it } 2.532000 0.015000 2.547000 ( 2.539123) ``` It's not bad. But I just wanted to know if there was a way that would, like the proposed syntax, avoid this compromise. ---------------------------------------- Feature #21515: Add `&return` as sugar for `x=my_calculation; return x if x` https://bugs.ruby-lang.org/issues/21515#change-114119 * Author: nhorton (Noah Horton) * Status: Open ---------------------------------------- Let me preface this by saying I have no marriage to the exact keyword name of `&return`. # Problem It is very common to have an early return in code where you get some initial value and return it if it is non-null. i.e. ``` return my_calculation(input_a, input_b) if my_calculation(input_a, input_b) ``` That form on its own is verbose and one where you need to look at it for a moment to confirm it is the same code on either side of the if. If `my_calculation` is non-trivial at all, it normally gets turned into something with a variable: ``` my_calc = my_calculation(input_a, input_b) return my_calc if my_calc ``` That is now two lines. The worse scenario, however, is if the user did not bother doing that and my_calculation turned out to be expensive (and they did not know it). # Proposal I propose a syntax of `&return my_calculation(input_a, input_b)` where it will evaluate the argument and return it as the result of the method if it is non-nil, otherwise it will continue on. # Alternatives ## Do Nothing There is no way to work around this with rolling your own methods. You can't make a `returnif` method or something yourself since you can't do a return in the caller's scope. ## Different Name The best other name I saw were permutations of `returnif`. The biggest issue I see is the similarity of the following two statements: ``` return if foo returnif foo ``` Those are obviously very, very different statements, but are somewhat similar. However, things like this are common, and the code is still quite distinct on those, so I think it is acceptable. Ultimately, this feels so similar to the safe navigator that using `&` in this context feels appropriate. Thank you all for your consideration. -- https://bugs.ruby-lang.org/