@function __base-flatten($list, $is-deep: false, $is-strict: false, $from-index: 1) {
    $index: $from-index;
    $length: length($list);
    $result-index: 1;
    $result: ();

    @while ($index <= $length) {
        $value: nth($list, $index);

        @if __is-map-like($value)
        and __is-length(length($value))
        and __is-list-like($value) {
            @if ($is-deep) {
                $value: __base-flatten($value, $is-deep, $is-strict);
            }

            $value-index: 1;
            $value-length: length($value);

            @while ($value-index <= $value-length) {
                $result: append($result, nth($value, $value-index));
                $value-index: $value-index + 1;
            }
        } @else if not ($is-strict) {
            $result: append($result, $value);
        }

        $index: $index + 1;
    }

    @return $result;
}


@function __flatten-deep($list, $args...) {
    $length: if(__is-list-like($list), length($list), 0);

    @return if($length > 0, __base-flatten($list, true), ());
}


@function __flatten($list, $is-deep: false, $guard: null) {
    $length: if(__is-list-like($list), length($list), 0);

    @if $guard and __is-iteratee-call($list, $is-deep, $guard) {
        $is-deep: false;
    }

    @return if($length > 0, __base-flatten($list, $is-deep), ());
}


/// Flattens a nested list. If `$is-deep` is `true` the list is recursively
/// flattened, otherwise it is only flattened a single level.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to flatten.
/// @param {boolean} $is-deep [false] - Specify a deep flatten.
/// @returns {List} Returns the new flattened list.
/// @example scss
/// $foo: _flatten((1, (2, 3, (4,))));
/// // => (1, 2, 3, (4,));
/// 
/// // using `$is-deep`
/// $foo: _flatten((1, (2, 3, (4,))), true);
/// // => (1, 2, 3, 4);

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


/// Recursively flattens a nested list.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to recursively flatten.
/// @returns {List} Returns the new flattened list.
/// @example scss
/// $foo: _flatten-deep((1, (2, 3, (4,))));
/// // => (1, 2, 3, 4);

@function _flatten-deep($args...) {
    @return call(get-function('__flatten-deep'), $args...);
}
