@function __range($start, $end: null, $step: null) {
    @if ($step and $step != 0 and __is-iteratee-call($start, $end, $step)) {
        $end: null;
        $step: null;
    }

    $start: if(__is-integer($start), $start, if(__is-truthy($start), 1, 0));
    $step: if($step == null, 1, if(__is-integer($step), $step, if($step, 1, 0)));

    @if ($end == null) {
        $end: $start;
        $start: 0;
    } @else {
        $end: if(__is-integer($end), $end, if($end, 1, 0));
    }

    $index: 1;
    $length: max(ceil(($end - $start) / (if($step == 0, 1, $step))), 0);
    $result: ();

    @while ($index <= $length) {
        $result: append($result, $start);
        $start: $start + $step;
        $index: $index + 1;
    }

    @return $result;
}


/// Creates a list of numbers (positive and/or negative) progressing from
/// `$start` up to, but not including, `$end`. If `$end` is not specified it
/// defaults to `$start` with `$start` becoming `0`. If `$start` is less than
/// `$end` a zero-length range is created unless a negative `$step` is specified.
///
///
/// @access public
/// @group Utility
/// @param {number} $start [0] - The start of the range.
/// @param {number} $end - The end of the range.
/// @param {number} $step [1] - The value to increment or decrement by.
/// @returns {List} Returns the new list of numbers.
/// @example scss
/// $foo: _range(4);
/// // => (0, 1, 2, 3)
/// $foo: _range(1, 5);
/// // => (1, 2, 3, 4)
/// $foo: _range(0, 20, 5);
/// // => (0, 5, 10, 15)
/// $foo: _range(0, -4, -1);
/// // => (0, -1, -2, -3)
/// $foo: _range(1, 4, 0);
/// // => (1, 1, 1)
/// $foo: _range(0);
/// // => ()

@function _range($args...) {
    @return call(get-function('__range'), $args...);
}
