@function __base-assign($map, $source, $customizer: false) {
    @if not __is-map-like($map) {
        @return $map;
    }

    $props: __keys($source);

    @if not $customizer {
        @return __base-copy($source, $map, $props);
    }

    @each $key in $props {
        $value: if(map-has-key($map, $key), __get($map, $key), $__undefined__);
        $result: __exec($customizer, $value, __get($source, $key), $key, $map, $source);

        @if ($result != $value)
        or ($value == null and not map-has-key($map, $key)) {
            $map: __set($map, $key, $result);
        }
    }

    @return $map;
}


@function __create-assigner-function($arguments...) {
    $assigner: __this('assigner');
    $length: length($arguments);
    $map: if($length >= 1, nth($arguments, 1), null);
    $customizer: null;

    @if ($length < 2 or $map == null) {
        @return $map;
    }

    @if ($length > 3 and __is-iteratee-call(nth($arguments, 2), nth($arguments, 3), nth($arguments, 4))) {
        $length: 2;
    }

    @if $length > 3 and __function-exists(nth($arguments, $length - 1)) {
        $length: $length - 1;
        $customizer: __bind-callback(nth($arguments, $length), nth($arguments, $length - 1), 5);
    } @else if $length > 2 and __function-exists(nth($arguments, $length)) {
        $length: $length - 1;
        $customizer: nth($arguments, $length + 1);
    }

    @for $index from 1 through $length {
        $source: nth($arguments, $index);

        @if ($source) {
            $map: __exec($assigner, $map, $source, $customizer);
        }
    }

    @return $map;
}


@function __create-assigner($assigner) {
    $_: __scope((
        'assigner': $assigner
    ));

    $scoped-function: __bind('__create-assigner-function');

    $_: __scope(false);

    @return $scoped-function;
}


@function __assign($arguments...) {
    $assigner: __create-assigner('__base-assign');

    @return __exec($assigner, $arguments...);
}


/// Assigns own enumerable properties of source map(s) to the destination
/// map. Subsequent sources overwrite property assignments of previous sources.
/// If `$customizer` is provided it is invoked to produce the assigned values.
/// The `$customizer` is bound to `$this-arg` and invoked with five arguments;
/// ($map-value, $map-value, $key, $map, $source).
///
///
/// @access public
/// @group Map
/// @param {Map} $map - The destination map.
/// @param {Map...} $sources... - The source maps.
/// @param {Function} $customizer [false] - The function to customize assigning values.
/// @param {*} $this-arg [null] - The `_this` binding of `$customizer`.
/// @returns {Map} Returns `map`.
///
/// @example scss
/// _assign(( 'user': 'barney' ), ( 'age': 40 ), ( 'user': 'fred' ));
/// // => ( 'user': 'fred', 'age': 40 )
///
/// // using a customizer callback
/// $defaults: _partial-right(_assign, _either);
/// _exec($defaults, (( 'user': 'barney' ), ( 'age': 36 ), ( 'user': 'fred' )));
/// // => ( 'user': 'barney', 'age': 36 )

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


/// @alias _assign

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