slice (slice v0.0.1)
View SourcePython-style slice calculations for Erlang lists.
It implements the index/2 and range/2 functions which convert slice indexes
(which are 0-based and may be negative) to actual indexes (which are 1-based
and strictly positive). They require the known length of the list to be able to
work out the resulting indexes and ranges.
It was inspired by the Python's "slice notation" which is convenient to quickly retrieve specific elements or sub-lists without having to calculate the start and end indexes manually.
The slice indexes are 0-based (meaning that the first element is at index 0),
however, the resulting indexes are 1-based and therefore suitable to be passed
to the standard lists:nth/2 and lists:sublist/3 functions.
Example of using a slice index.
List = [a, b, c, d, e].
1 = slice:index(length(List), 0). % The first element.
5 = slice:index(length(List), -1). % The last element.Example of using a slice range.
List = [a, b, c, d, e].
{1, 3} = slice:range(length(List), {undefined, 3}). % The first three elements.
{3, 3} = slice:range(length(List), {-3, undefined}). % The last three elements.
{2, 3} = slice:range(length(List), {1, -1}). % Without the first and last element.
{1, 5} = slice:range(length(List), {undefined, undefined}). % The whole list.Notice how the left or the right part of the range can be omitted. If both are omitted, the whole list is returned.
Summary
Types
-type index() :: integer().
Slice index.
A slice index, which may be positive (counting from the start, 0-based) or negative (counting from the end, -1 refers to the last element), to specify a single element.
-type offset() :: pos_integer().
A 1-based offset.
Range indexes.
A pair of indexes, which may be positive (counting from the start, 0-based) or negative (counting from the end, -1 refers to the last element), to specify a sub-list.
-type start() :: undefined | integer().
Range start index.
It may be omitted with undefined to mean the start of the list.
-type stop() :: undefined | integer().
Range stop index.
It may be omitted with undefined to mean the end of the list. When present,
it is exclusive, like in Python slices.
Functions
-spec index(non_neg_integer(), index()) -> offset() | out_of_range.
Calculate the index for a slice element.
It calculates the actual index for a slice element based on the known length of
the slice and the provided 0-based slice index. The resulting index is 1-based,
meaning that it can be used directly with the standard lists:nth/2 function.
If the provided index is out of range, it returns out_of_range.
-spec range(non_neg_integer(), {Start :: integer() | undefined, Stop :: integer() | undefined}) -> {offset(), pos_integer()} | no_range.
Calculate start position and length for a slice range.
It calculates a 1-based start position and a length from a pair of 0-based
slice indexes. The start and stop indexes may be negative, and undefined may
be used to omit either bound.
The stop index is exclusive, like in Python slices. The returned tuple can be
used directly with the standard lists:sublist/3 function.
If the resulting slice would be empty, it returns no_range.