-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Tuple#[](Range)
with compile-time range literals
#10379
Support Tuple#[](Range)
with compile-time range literals
#10379
Conversation
def codegen_tuple_indexer(type, value, index : Range) | ||
case type | ||
when TupleInstanceType | ||
tuple_types = type.tuple_types[index].map &.as(Type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's so convenient that implementing []
with range is actually done by using []
with a range :-)
When I initially thought about this I thought it would be more complex because of all the indexing logic involved... but it's already there!
def [](range : Range) | ||
{% raise "Tuple#[](Range) can only be called with range literals known at compile-time" %} | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is fine for now. But eventually returning an Array
is fine too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great!! I left a couple of optional suggestions.
Tuple#[](index : Int)
returns the element in the proper type ifindex
is an integer literal known at compile-time. This PR adds aTuple#[](range : Range)
pseudo-overload that only supports compile-time range literals, and returns the elements in a proper sub-tuple type:The motivation is to enable #132 for
Tuple
values on the RHS, without creating temporaryArray
s: (only one layer of decomposition is considered here)It is assumed that the Crystal compiler should transform the above multi-assign expression into the following, in a purely syntactic manner:
The method supports incomplete and exclusive ranges to match the behaviour of other
#[](Range)
methods, even though the expansion here doesn't require them.The range index corresponding to the splat variable is always known at compile-time, because it can be deduced from the number of non-splat variables before and after it; thus it suffices to implement the special case for
Tuple
s where this range is a constant expression. (The same syntactic transformation already works out of the box for types that implement#[](Range)
, likeArray
.)On the other hand, the only sensible return type of
Tuple(*T)#[](Range)
for runtime range arguments isArray(Union(*T))
. This PR does not address this discrepancy at all, that's left to #7619. Method lookup bypasses prelude definitions of(Named)Tuple#[]
if a compile-time indexer is found, so the compile-time error seen in the top example will not be triggered by constant range literals.The documentation for this method does not take #10243 into account.
Also see the Gitter discussion that led up to this.