Skip to content
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

Doc PR to clarify range usage #37875

Closed
wants to merge 10 commits into from
115 changes: 99 additions & 16 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,38 @@ function _colon(start::T, step, stop::T) where T
end

"""
range(start[, stop]; length, stop, step=1)
range(start; stop, length) # any one keyword, step = 1
range(start, stop; length, step) # any one keyword
range(start; stop, length, step) # any two keywords

Given a starting value, construct a range either by length or from `start` to `stop`,
optionally with a given step (defaults to 1, a [`UnitRange`](@ref)).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

step does not default to 1 when length is specified.

step does not default to 1 when stop is a positional argument. range(1,5) does not work but range(1,5, step=1) does.

The only time step defaults to 1 is when using stop as a positional argument: range(1,stop=5)

One of `length` or `stop` is required. If `length`, `stop`, and `step` are all specified, they must agree.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If length, stop, and step are all specified, they must agree.

length, stop, and step cannot be all specified:

julia/base/range.jl

Lines 166 to 167 in 01d89c6

_range(start::Real, step::Real, stop::Real, length::Integer) = # range(a, step=s, stop=b, length=l)
throw(ArgumentError("Too many arguments specified; try passing only one of `stop` or `length`"))

_range(start::Real, step::Real, stop::Real, length::Integer) = # range(a, step=s, stop=b, length=l)
    throw(ArgumentError("Too many arguments specified; try passing only one of `stop` or `length`"))

Construct at an `AbstractRange`, given a starting value and one or two required keyword arguments.

If `length` and `stop` are provided and `step` is not, the step size will be computed
automatically such that there are `length` linearly spaced elements in the range.

If `step` and `stop` are provided and `length` is not, the overall range length will be computed
automatically such that the elements are `step` spaced.
`start` is the first value of range. `stop` is the upper bound of the range. `length` is the number of
elements of range. `step` is the difference between each element of the range.

Special care is taken to ensure intermediate values are computed rationally.
To avoid this induced overhead, see the [`LinRange`](@ref) constructor.
If the only keyword is `stop` or `length` and all arguments are integers this results in a `UnitRange`.
Otherwise it constructs an `AbstractRange` for which any two of `stop, length, step`
can be specified. Giving all three will result in an error.
`stop` may be a keyword, or the 2nd positional argument along with another keyword argument.

`stop` may be specified as either a positional or keyword argument.
See the Extended help for more details.

!!! compat "Julia 1.1"
`stop` as a positional argument requires at least Julia 1.1.

# Examples
```jldoctest
julia> range(1, length=100)
1:100
julia> range(2, length=100)
2:101

julia> range(1, stop=100)
1:100
julia> range(3, stop=100)
3:100

julia> range(4, stop=100, step=2)
4:2:100

julia> range(1, stop=3.3)
1.0:1.0:3.0

julia> range(1, step=5, length=100)
1:5:496
Expand All @@ -86,7 +91,85 @@ julia> range(1, 10, length=101)

julia> range(1, 100, step=5)
1:5:96

julia> julia> range(1,5)
ERROR: ArgumentError: At least one of `length` or `step` must be specified
[...]

julia> range(1; stop=5, length=5, step=1)
ERROR: ArgumentError: Too many arguments specified; try passing only one of `stop` or `length`
[...]
```

# Extended help
range(start; length)
range(start; stop)

range(start; stop, length)
range(start, stop; length)

range(start; stop, step)
range(start, stop; step)

range(start; length, step)

The above forms of `range` are the only acceptable forms of the range call.

## Arguments

mkitti marked this conversation as resolved.
Show resolved Hide resolved
The relationship of the arguments is described by the following equation
written as an expression that must evaluate to true.

`start + step * (length-1) <= stop`

### `length` argument specified

If `length` is given as the sole keyword argument, `step` is assumed to be 1.0.

### `stop` argument specified

`stop` serves only as an upper bound and may be included as the last element.
If `stop` is given as the sole keyword argument, `step` is assumed to be 1.0.
If `stop` is given as a positional argument, a keyword argument of either
`length` or `step` must be specified per below.

### `stop` and `length` specified

If `length` and `stop` are provided and `step` is not, the step size will be computed
automatically such that there are `length` linearly spaced elements in the range inclusive
of `stop`.

### `stop` and `step` specified

If `step` and `stop` are provided and `length` is not, the overall range length will be computed
automatically such that the elements are `step` spaced. The last element of the range
may not be `stop` in this case.

### `length` and `stop` specified

If `length` and `step are provided and `stop` is not, then the resulting range will include
`length` elements that are `step` spaced. The last element will be
`stop = start + step * (length-1)`.

### `length`, `stop`, and `step` cannot be all specified

An [`ArgumentError`](@ref) will be thrown if all three keyword arguments are specified.

## `UnitRange` construction

To specify a [`UnitRange`](@ref) where `step` is 1, use one of the following
where `start`, `length`, and `stop` are all integers.
* range(start, length=length)
* range(start, stop=stop)
* `start:stop`
* `(:)(start,stop)`

Specifying a `step` of 1 explicitly, does not result in a [`UnitRange`](@ref).

## Rationally computed intermediate values

Special care is taken to ensure intermediate values are computed rationally.
To avoid this induced overhead, see the [`LinRange`](@ref) constructor.
"""
range(start; length::Union{Integer,Nothing}=nothing, stop=nothing, step=nothing) =
_range(start, step, stop, length)
Expand Down