A.ExRange (Aja v0.4.1) View Source
Exclusive ranges are an exact copy of regular ranges (see Range
),
except that they exclude the second parameter.
Why/when would you need exclusive ranges?
The most typical use case would be when using 1..n
for loops based
on a parameter n >= 0
:
iex> incorrect = fn n -> for i <- 1..n, do: "id_#{i}" end
iex> incorrect.(3) # works fine in general...
["id_1", "id_2", "id_3"]
iex> incorrect.(0) # weird bug at edge case!
["id_1", "id_0"]
To fix it, you would typically need to match the n == 0
case and handle
it differently, which is adds noise.
With exclusive ranges like 0 ~> n
, you get to keep the compact and elegant
approach from above, while having a correct algorithm that covers the edge case:
iex> correct = fn n -> for i <- 1 ~> n + 1, do: "id_#{i}" end
iex> correct.(3) # works fine
["id_1", "id_2", "id_3"]
iex> correct.(0) # edge case works fine too
[]
Exclusive ranges can be either increasing (start <= stop
) or
decreasing (start > stop
). The start
parameter is included
(except if start == stop
), the stop
parameter is always excluded.
An exclusive range is represented internally as a struct
A.ExRange{start: start, stop: stop}
and can be used as is.
The A.~>/2
convenience macro makes it possible to have a more compact
syntax, similar to ../2
.
It is totally optional and needs to be imported:
iex> import A
iex> import A, only: [~>: 2] # more selective
Examples:
iex> A.ExRange.new(5)
#A<0 ~> 5>
iex> range = 0 ~> 5
#A<0 ~> 5>
iex> start ~> stop = range
iex> {start, stop}
iex> {0, 4}
iex> Enum.to_list(range)
[0, 1, 2, 3, 4]
iex> Enum.count(range)
5
iex> Enum.member?(range, 5)
false
iex> Enum.member?(range, 4)
true
iex> Enum.to_list(3 ~> 0)
[3, 2, 1]
Just like Range
s, such function calls are efficient memory-wise
no matter the size of the range. The implementation of the Enumerable
protocol uses logic based solely on the endpoints and does
not materialize the whole list of integers.
Link to this section Summary
Link to this section Types
Specs
Link to this section Functions
Specs
Checks if two ranges are disjoint.
Examples
iex> A.ExRange.disjoint?(1 ~> 6, 6 ~> 9)
true
iex> A.ExRange.disjoint?(6 ~> 1, 6 ~> 9)
true
iex> A.ExRange.disjoint?(1 ~> 6, 5 ~> 9)
false
iex> A.ExRange.disjoint?(1 ~> 6, 2 ~> 7)
false
Specs
Creates a new exclusive range.
start
defaults to 0.
Examples
iex> A.ExRange.new(0, 100)
#A<0 ~> 100>
iex> A.ExRange.new(10)
#A<0 ~> 10>