slice method
Returns a new list containing the elements of this from start
inclusive to end exclusive, skipping by step.
Example:
[1, 2, 3, 4].slice(start: 1, end: 3); // [2, 3]
[1, 2, 3, 4].slice(start: 1, end: 4, step: 2); // [2, 4]
start defaults to the first element if step is positive and to the
last element if step is negative. end does the opposite.
Example:
[1, 2, 3, 4].slice(end: 2); // [1, 2]
[1, 2, 3, 4].slice(start: 1); // [2, 3, 4]
[1, 2, 3, 4].slice(end: 1, step: -1); // [4, 3]
[1, 2, 3, 4].slice(start: 2, step: -1); // [3, 2, 1]
If start or end is negative, it will be counted backwards from the
last element of this. If step is negative, the elements will be
returned in reverse order.
Example:
[1, 2, 3, 4].slice(start: -2); // [3, 4]
[1, 2, 3, 4].slice(end: -1); // [1, 2, 3]
[1, 2, 3, 4].slice(step: -1); // [4, 3, 2, 1]
Any out-of-range values for start or end will be truncated to the
maximum in-range value in that direction.
Example:
[1, 2, 3, 4].slice(start: -100); // [1, 2, 3, 4]
[1, 2, 3, 4].slice(end: 100); // [1, 2, 3, 4]
Will return an empty list if start and end are equal, start is
greater than end while step is positive, or end is greater than
start while step is negative.
Example:
[1, 2, 3, 4].slice(start: 1, end: -3); // []
[1, 2, 3, 4].slice(start: 3, end: 1); // []
[1, 2, 3, 4].slice(start: 1, end: 3, step: -1); // []
Implementation
List<E> slice({int? start, int? end, int step = 1}) {
  final indices = sliceIndices(start, end, step, this.length);
  if (indices == null) {
    return <E>[];
  }
  final _start = indices.start;
  final _end = indices.end;
  final slice = <E>[];
  if (step > 0) {
    for (var i = _start; i < _end; i += step) {
      slice.add(this[i]);
    }
  } else {
    for (var i = _start; i > _end; i += step) {
      slice.add(this[i]);
    }
  }
  return slice;
}