@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...);
}
