Allow blocks to be optional instead of requiring overloaded methods.
def foo(&block = nil)
The current way of using overloads causes unnecessary code duplication:
def foo() { }
def foo(&block)
On a more detailed request, having support for block_given? would be nice to avoid having blunt overloads when a block is optional but implementations are identical otherwise. For instance:
def foo
foo {}
end
def foo
yield
end
The following would be nicer:
def foo
yield if block_given?
end
This is really hard to implement, mostly becuase a non-captured block is not an object that you can pass around.
@asterite maybe it can be implemented by expanding the non typed def in two when block_given? is used in the body. One with yield and replacing the block_given? with true and another without yield and replacing the block_given? with false. All this before the type inference.
Can we solve this using macros?
def foo
{% if @call.block? %}
yield
{% else %}
raise "meh"
{% end %}
end
@call would make the method a macro method just like @type so it's instantiated for each call and then refer to the call it was instantiated by. Regular methods win if there are any that match. @call having AST access to the original call arguments could probably also allow some very interesting things.
Maybe we could make it so that block_given? would be a special call that the language would know about. Then for a method that uses this the compiler would generate two methods, one where block_given? would be replaced by true and marked as yielding, and the other as not, or something like that. Since this might be common, writing if block_given? rather than using the macro language is less noisy.
But I'll have to think about it a bit more.
Or simply having if block_given? be something special, I think that could work fine too and also be easier to implement.
What are current examples in the standard library or in shards that could benefit from this, and how?
I was thinking about something like this
def pop(&block = {
raise IndexError.new
})
if @size == 0
yield
else
@size -= 1
value = @buffer[@size]
(@buffer + @size).clear
value
end
end
In 2020 exists nice solution for it?
@0x000def42 nope. This has never been implemented, as nice as it would be to have. Currently the only real solution I know of is still just to use overloaded methods.
Currently the only real solution I know of is still just to use overloaded methods.
I honestly don't see anything wrong with that. Overloads are fine.
Overloads just look messy, but they work
Most helpful comment
@0x000def42 nope. This has never been implemented, as nice as it would be to have. Currently the only real solution I know of is still just to use overloaded methods.