slice (slice v0.0.1)

View Source

Python-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

Slice index.

A 1-based offset.

Range indexes.

Range start index.

Range stop index.

Functions

Calculate the index for a slice element.

Calculate start position and length for a slice range.

Types

index()

-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.

offset()

-type offset() :: pos_integer().

A 1-based offset.

range()

-type range() :: {start(), stop()}.

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.

start()

-type start() :: undefined | integer().

Range start index.

It may be omitted with undefined to mean the start of the list.

stop()

-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

index/2

-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.

range/2

-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.