Open HertzDevil opened 1 month ago
Are there any relevant real use cases for RangeLiteral#each
in singnificant sizes where performance/memory usage has a noticable effect? I somewhat doubt that.
I can see that something like this could be useful for iterating StringLiteral
(and BytesLiteral
). But maybe we should focus on those use cases specifically and not so much on RangeLiteral
.
Some yielding methods in the macro language like
RangeLiteral#each
allocate a new node on each iteration:https://github.com/crystal-lang/crystal/blob/f17b565cd5cd9bd96dbba85d1e94c7d2cacbf21b/src/compiler/crystal/macros/methods.cr#L1115-L1125
This means
{% (0...10000).each { } %}
allocates 10000NumberLiteral
nodes. However, since all these variables have the same node type, and sinceCrystal::NumberLiteral#value=
exists, it is actually possible to use a single node for all iterations:Thus if we know that the iteration variable won't be used outside the block, there should be a way to opt in to this behavior:
This only makes sense for
RangeLiteral#each
and technically the keys forNamedTupleLiteral#each
, because other similar methods likeArrayLiteral#each
are heterogeneous or do not allocate new nodes per iteration. The main benefit of this approach is being able to defineStringLiteral#each_char
in a similar manner, since such a method is presumbaly avoided for performance reasons; andBytesLiteral#each_byte
, if a new syntax is invented for #2886.