[ruby/set] Avoid the `block or return` pattern to save Proc allocations

Using the block param in a boolean context like this cause it to be
allocated.

Using it with an `if` or `unless` was optimized in 3.2
(https://github.com/ruby/ruby/pull/6286) but using it with `or`
or `and` wasn't.

```ruby
def foo(&block)
  block or return 1
end

puts RubyVM::InstructionSequence.of(method(:foo)).disasm
== disasm: #<ISeq:foo@(irb):11 (11,0)-(13,3)> (catch: false)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1])
[ 1] block@0<Block>
0000 getblockparam                          block@0, 0                (  12)[LiCa]
0003 dup
0004 branchif                               10
0006 pop
0007 putobject_INT2FIX_1_
0008 leave                                  [Re]
0009 putnil
0010 leave
```

versus

```
def foo(&block)
  return 1 if block
end

puts RubyVM::InstructionSequence.of(method(:foo)).disasm
== disasm: #<ISeq:foo@(irb):15 (15,0)-(17,3)> (catch: false)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1])
[ 1] block@0<Block>
0000 getblockparamproxy                     block@0, 0                (  16)[LiCa]
0003 branchunless                           7
0005 putobject_INT2FIX_1_
0006 leave                                                            (  17)[Re]
0007 putnil                                                           (  16)
0008 leave
```

https://github.com/ruby/set/commit/e89da977d4
This commit is contained in:
Jean Boussier 2023-01-11 10:08:52 +01:00 коммит произвёл git
Родитель 8c2b6926d2
Коммит e85ef212de
1 изменённых файлов: 3 добавлений и 3 удалений

Просмотреть файл

@ -507,7 +507,7 @@ class Set
# the element as parameter. Returns an enumerator if no block is
# given.
def each(&block)
block or return enum_for(__method__) { size }
block_given? or return enum_for(__method__) { size }
@hash.each_key(&block)
self
end
@ -582,7 +582,7 @@ class Set
# Equivalent to Set#delete_if, but returns nil if no changes were
# made. Returns an enumerator if no block is given.
def reject!(&block)
block or return enum_for(__method__) { size }
block_given? or return enum_for(__method__) { size }
n = size
delete_if(&block)
self if size != n
@ -591,7 +591,7 @@ class Set
# Equivalent to Set#keep_if, but returns nil if no changes were
# made. Returns an enumerator if no block is given.
def select!(&block)
block or return enum_for(__method__) { size }
block_given? or return enum_for(__method__) { size }
n = size
keep_if(&block)
self if size != n