@function __take($list, $n: 1, $guard: null) {
    $length: if($list, length($list), 0);

    @if __is-falsey($length) {
        @return ();
    }

    @if if($guard, __is-iteratee-call($list, $n, $guard), $n == null) {
        $n: 1;
    }

    $n: if(__is-number($n), $n, if(__is-truthy($n), 1, 0));

    @return __base-slice($list, 0, if($n < 0, 0, $n));
}


@function __take-right($list, $n: 1, $guard: null) {
    $length: if($list, length($list), 0);

    @if __is-falsey($length) {
        @return ();
    }

    @if if($guard, __is-iteratee-call($list, $n, $guard), $n == null) {
        $n: 1;
    }

    $n: $length - if(__is-number($n), $n, if(__is-truthy($n), 1, 0));

    @return __base-slice($list, if($n < 0, 0, $n));
}


@function __take-right-while($list, $predicate: '__identity', $this-arg: null) {
    $length: if($list, length($list), 0);

    @if __is-falsey($length) {
        @return ();
    }

    $predicate: __get-callback($predicate, $this-arg, 3);


    @while $length > 0
        and __is-truthy(__exec($predicate, nth($list, $length), $length, $list))
    {
        $length: $length - 1;
    }

    @return __base-slice($list, $length);
}


@function __take-while($list, $predicate: '__identity', $this-arg: null) {
    $length: if($list, length($list), 0);

    @if __is-falsey($length) {
        @return ();
    }

    $index: 1;
    $predicate: __get-callback($predicate, $this-arg, 3);

    @while $index <= $length
        and __is-truthy(__exec($predicate, nth($list, $index), $index, $list))
    {
        $index: $index + 1;
    }

    @return __base-slice($list, 0, $index - 1);
}


/// Creates a slice of `$list` with `$n` elements taken from the beginning.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to query.
/// @param {number} $n [1] - The number of elements to take.
/// @returns {List} Returns the slice of `$list`.
/// @example scss
/// $foo: _take((1, 2, 3));
/// // => (1,)
/// $foo: _take((1, 2, 3), 2);
/// // => (1, 2)
/// $foo: _take((1, 2, 3), 5);
/// // => (1, 2, 3)
/// $foo: _take((1, 2, 3), 0);
/// // => ()

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


/// Creates a slice of `$list` with `$n` elements taken from the end.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to query.
/// @param {number} $n [1] - The number of elements to take.
/// @returns {List} Returns the slice of `$list`.
/// @example scss
/// $foo: _take-right((1, 2, 3));
/// // => (3,)
/// $foo: _take-right((1, 2, 3), 2);
/// // => (2, 3)
/// $foo: _take-right((1, 2, 3), 5);
/// // => (1, 2, 3)
/// $foo: _take-right((1, 2, 3), 0);
/// // => ()

@function _take-right($args...) {
    @return call(get-function('__take-right'), $args...);
}


/// Creates a slice of `$list` with elements taken from the end. Elements are
/// taken until `$predicate` returns falsey. The predicate is bound to `$this-arg`
/// and invoked with three arguments; (value, index, list).
/// 
/// If a property name is provided for `$predicate` the created `_property`
/// style callback returns the property value of the given element.
/// 
/// If a value is also provided for `$this-arg` the created `_matches-property`
/// style callback returns `true` for elements that have a matching property
/// value, else `false`.
/// 
/// If a map is provided for `$predicate` the created `_matches` style
/// callback returns `true` for elements that have the properties of the given
/// object, else `false`.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to query.
/// @param {Function|Map|string} $predicate [_identity] - The function invoked
///  per iteration.
/// @param {*} $this-arg [null] - The `_this` binding of `$predicate`.
/// @returns {List} Returns the slice of `$list`.
/// @example scss
/// $users: (
///   ( 'user': 'barney',  'active': true ),
///   ( 'user': 'fred',    'active': false ),
///   ( 'user': 'pebbles', 'active': false )
/// );
/// 
/// // using the `_matches` callback shorthand
/// $foo: _pluck(_take-right-while($users, ( 'user': 'pebbles', 'active': false )), 'user');
/// // => ('pebbles',)
/// 
/// // using the `_matches-property` callback shorthand
/// $foo: _pluck(_take-right-while($users, 'active', false), 'user');
/// // => ('fred', 'pebbles')
/// 
/// // using the `_property` callback shorthand
/// $foo: _pluck(_take-right-while($users, 'active'), 'user');
/// // => ()

@function _take-right-while($args...) {
    @return call(get-function('__take-right-while'), $args...);
}


/// Creates a slice of `$list` with elements taken from the beginning. Elements
/// are taken until `$predicate` returns falsey. The predicate is bound to
/// `$this-arg` and invoked with three arguments; (value, index, list).
/// 
/// If a property name is provided for `$predicate` the created `_property`
/// style callback returns the property value of the given element.
/// 
/// If a value is also provided for `$this-arg` the created `_matches-property`
/// style callback returns `true` for elements that have a matching property
/// value, else `false`.
/// 
/// If a map is provided for `$predicate` the created `_matches` style
/// callback returns `true` for elements that have the properties of the given
/// object, else `false`.
///
///
/// @access public
/// @group List
/// @param {List} $list The list to query.
/// @param {Function|Map|string} $predicate [_identity] - The function invoked
///  per iteration.
/// @param {*} $this-arg [null] - The `_this` binding of `$predicate`.
/// @returns {List} Returns the slice of `$list`.
/// @example scss
/// $users: (
///   ( 'user': 'barney',  'active': false ),
///   ( 'user': 'fred',    'active': false ),
///   ( 'user': 'pebbles', 'active': true )
/// );
/// // using the `_matches` callback shorthand
/// $foo: _pluck(_take-while($users, ( 'user': 'barney', 'active': false )), 'user');
/// // => ('barney',)
/// 
/// // using the `_matches-property` callback shorthand
/// $foo: _pluck(_take-while($users, 'active', false), 'user');
/// // => ('barney', 'fred')
/// 
/// // using the `_property` callback shorthand
/// $foo: _pluck(_take-while($users, 'active'), 'user');
/// // => ()

@function _take-while($args...) {
    @return call(get-function('__take-while'), $args...);
}
