So List.range
has quite nice ergonomics in terms of the record {start, end}
where start can be e.g. At 5
or After 5
. But I find that some of the cases are very unintuitive, when combined with the fact that specifying a range with a start after an end should give a reversed list. So for example, what would you expect the following cases to give? (I hid the result of calling this in the repl behind spoilers, if you want to guess before checking.)
List.range { start: After 5, end: Before 5 }
List.range { start: After 5, end: At 5 }
List.range { start: At 5, end: Before 5 }
For me at least, it is very confusing that After
and Before
change meaning depending on wether the list is enumerated forwards or backwards. Especially since what you use for those values will determine the direction of the list in the first place.
I can imagine this leading to some very confusing bugs if e.g. I am using some program that is calling this function with arbitrary integers n
and m
that change depending on some context.
Not sure I have a proper question about this, but wanted to know if this has been thought about before at least. Maybe there is some good reason why it works this way?
I would expect all of those to panic at first glance due to looping the list range, but maybe that is wrong, haven't checked. Empty lists may also be valid
My gut feeling is that if this ends up being error prone, we probably should stop inferring the direction and instead depend on step for reversing a range.
To be fair, if we made the step positive by default, you would get all the exact same answers for these examples. Those ranges all end before they start.
I think not inferring the direction is one way to make it more clear. Another could be to infer the direction but always interpret After as +1, and Before as -1. Then it would be After and Before as the numbers appear on the number line, not in the inferred direction
Also, I would be fine preemptively changing this. Probably would be a good discussion to kick off in a new thread in #ideas. I think it shouldn't be hard to come up with some confusing examples
That is a good point on before and after.
Though normally, I think end before means include one less element in the list, so it wouldn't depend on direction.
Same with start after in my mind. Kinda like building the full list them dropping the first elem
Ah ok. So I guess the semantics of start: After 5, end: At 5 would be "find the list of integers between 5 and 5 ([5]), then drop the first element because we start After 5, which gives []".
Yes thinking of it like that, then the other examples also makes sense. First enumerate all the values, and then drop values depending on if After and Before are used.
Yeah, I think that is the goal semantics. Maybe it just needs to be documented better
Last updated: Jul 05 2025 at 12:14 UTC