Given the class definition below, I am faced with the following problem, which I am stuck on !
How can I define the each method so that iteration is done on @sources.
def initialize(@sources : Enumerable(T))
def each …?
Any idea(s) ?
Normally you’d do something like:
def each(& : T ->) : Nil
@sources.each do |v|
However when trying this I get
Error: recursive block expansion: blocks that yield are always inlined, and this call leads to an infinite inlining, which I haven’t seen before . BUT, only if the initialize argument is typed as
Enumerable(T), if i change that to like
Array(T) it works fine…so not sure what’s going on there.
EDIT: Or could use
delegate :each, to: @sources as a shortcut, but I think it would lose the block/return typing. Not a big deal in this context tho.
Yes, I have encountered this very problem, hence my call for help. Unfortunately, the Enumerable(T) restriction is the most suitable for my application, Array(T) would be too reductive.
Perhaps a lower level approach (pointers) is worth considering…
I presume the error comes from the fact that the definition of
Enumerable(Int32)#each and its called from an implementation of
include Enumerable(T) for
So you can nest
Table(Int32).new(Table(Int32).new(Table(Int32).new(Table(Int32).new(...)))). This would lead to recursive calls of the same method, resulting in recursive block expansion.
@Blacksmoke16 Please can you elaborate on this solution, I am not familiar with the
See Object - Crystal 1.6.0-dev.
It basically just generates the wrapper method for you. E.g. in the API docs
delegate downcase, to: @string would generate like:
def downcase(*args, **kwargs)
@string.downcase *args, **kwargs
@Blacksmoke16 , Thanks, I’ll try that tomorrow !
No, to be clear it’ll suffer from the same issue as
since it generates equivalent code. Just a shortcut to reduce the boilerplate if that would have worked.
I finally found another solution, replacing
include Enumerable(T) by another type, without too much refactoring in my app.