@function __base-matches-function-1($map, $args...) {
  $value: __this("value");
  $key: __this("key");

  @return __is-truthy($map) and map-has-key($map, $key) and $value ==
    __get($map, $key);
}

@function __base-matches-function-2($map, $args...) {
  @return __base-is-match(
    $map,
    __this("props"),
    __this("values"),
    __this("strict-compare-flags")
  );
}

@function __base-matches($source, $is-cloned: false) {
  $props: map-keys($source);
  $length: length($props);
  $_: __scope();

  @if ($length == 1) {
    $key: nth($props, 1);
    $value: __get($source, $key);
    $_: __this("key", $key);
    $_: __this("value", $value);

    @if (__is-strict-comparable($value)) {
      $result: __bind("__base-matches-function-1");
      $_: __scope(false);

      @return $result;
    }
  }

  $values: (); // list
  $strict-compare-flags: (); // list

  @while ($length > 0) {
    $value: __get($source, nth($props, $length));
    $values: __set($values, $length, $value);
    $strict-compare-flags: __set(
      $strict-compare-flags,
      $length,
      __is-strict-comparable($value)
    );
    $length: $length - 1;
  }

  $values: __to-list($values);
  $strict-compare-flags: __to-list($strict-compare-flags);
  $_: __this("props", $props);
  $_: __this("values", $values);
  $_: __this("strict-compare-flags", $strict-compare-flags);
  $result: __bind("__base-matches-function-2");
  $_: __scope(false);

  @return $result;
}

@function __matches($source) {
  @return __base-matches($source, true);
}

/// Creates a function which performs a deep comparison between a given map
/// and `source`, returning `true` if the given map has equivalent property
/// values, else `false`.
///
///
/// @access public
/// @group Utility
/// @param {Map} $source The map of property values to match.
/// @returns {Function} Returns the new function.
/// @example scss
/// $users: (
///   ( 'user': 'barney', 'age': 36, 'active': true ),
///   ( 'user': 'fred',   'age': 40, 'active': false )
/// );
/// $foo: _filter($users, _matches(( 'age': 40, 'active': false )));
/// // => (( 'user': 'fred', 'age': 40, 'active': false ),)

@function _matches($args...) {
  @return call(get-function("__matches"), $args...);
}
