Should Julia have a range(stop) similar to the Python range(stop)?
In Julia master (1.7.0-DEV), we recently merged an all keyword range(; start, stop, length, step) in #38041. In addition to allowing all range arguments to be specified by keywords, it enables new combinations of arguments such as range(; stop, length). This also helped to simplify and correct the documentation on range.
Two and three argument positional range(start, stop) and range(start, stop, length) is also on the way in #39228 after approval in #38750.
I have proposed in #39241 allowing for a single-keyword argument range(; stop) and range(; length) as essentially defined as follows:
range(; stop) = 1:stop
range(; stop::Integer) = Base.OneTo(stop)
range(; length::Integer) = Base.OneTo(length)
Python has range(stop), range(start, stop), and range(start, stop, step) where all arguments must be integers.
In #38750, range(stop) was also supported by triage to mean range(start = 1, stop = stop).
I prototyped the following implementation:
range(start; stop=nothing, length::Union{Integer,Nothing}=nothing, step=nothing) =
_range_positional(start, step, stop, length)
...
range(stop::Integer) = range_stop(stop)
_range_positional(stop::Any , step::Nothing, ::Nothing, len::Nothing) =
_range(nothing, nothing, stop, nothing) # One arg interpreted as `stop`, could be nothing
_range_positional(start::Any , step::Any , stop::Any, len::Any) =
_range(start, step, stop, len)
...
range_stop(stop) = oneunit(stop):stop
range_stop(stop::Integer) = OneTo(stop)
The main arguments in favor of range(stop):
-
start = 1is a reasonable default for one-based index language -
range(stop)meaning[1, 2, ..., stop]translates into the rough equivalent of Pythonāsrange(stop)meaning[0, 1, ..., stop-1]. They have a length ofstop. - Using
Base.OneTo(stop)when an Integer is given providing the same result aseachindex(A)whereAis an array.
The main arguments against range(stop):
- We already have
1:nwhich may be more idiomatic. -
range(stop)is unexpected afterrange(start, stop) - If you add keyword arguments, suddenly
stopbecomesstartdue torange(start; stop, length, step).
As an alternative to range(stop), I proposed exporting oneto(stop) since the meaning of that seems clearer to me and avoids most of the arguments against range(stop).
The discussion has been bouncing around pull requests for a while, but I thought I would broaden the conversation by bringing it here.
Do you think range(stop) or perhaps oneto(stop) may be useful syntax?