@function __base-invoke-iteratee($value, $index, $collection) {
    $function: __this('function');
    $args: __this('args');
    $index: __this('index');
    $result: null;

    @if __is-native($function) {
        $result: __exec($function, $value);
    } @else {
        $result: __exec($function, $value, $index, $collection, $args...);
    }

    $_: __this('result', append(__this('result'), $result));
    $_: __this('index', __this('index') + 1);

    @return true;
}


@function __base-invoke($collection, $method-name, $args...) {
    $index: 1;
    $is-func: __function-exists($method-name);
    $length: if(__is-map-like($collection), length($collection), 0);
    $result: ();
    $function: if($is-func,
        $method-name,
        if($value != null, __get($value, $method-name), false));

    @if $length == 0 {
        @return $result;
    }

    $_: __scope((
        'result': $result,
        'function': $function,
        'args': $args,
        'index': $index
    ));
    $iteratee: __bind('__base-invoke-iteratee');
    $_: __base-each($collection, $iteratee);
    $result: __this('result');
    $_: __scope(false);

    @return $result;
}


@function __invoke($collection, $method-name: '__identity', $args...) {
    @return __base-invoke($collection, $method-name, $args...);
}


/// Invokes the method named by `$method-name` on each element in `$collection`,
/// returning a list of the results of each invoked method. Any additional
/// arguments are provided to each invoked method. If `$method-name` is a function
/// it is invoked for, and `$this` bound to, each element in `$collection`.
///
///
/// @access public
/// @group Collection
/// @param {List|Map|string} $collection The collection to iterate over.
/// @param {Function|string} $method-name The name of the method to invoke or
///  the function invoked per iteration.
/// @param {Any...} $args... The arguments to invoke the method with.
/// @returns {List} Returns the list of results.
/// @example scss
/// $foo: _invoke(((5, 1, 7), (3, 2, 1)), '_sort');
/// // => ((1, 5, 7), (1, 2, 3))
/// $foo: _invoke((123, 456), '_split', '');
/// // => (('1', '2', '3'), ('4', '5', '6'))

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