@function __base-property-function($map: null, $args...) {
  $key: __this("key");

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

  $map: __to-map($map);

  @return if($map == null, null, __get($map, $key));
}

@function __base-property($key) {
  $_: __scope(
    (
      "key": $key
    )
  );
  $base-property-function: __bind("__base-property-function");
  $_: __scope(false);

  @return $base-property-function;
}

@function __property($key, $args...) {
  @return __base-property($key);
}

@function __property-of-function($key, $args...) {
  $map: __this("map");

  @return if($map == null, null, __get($map, $key));
}

@function __property-of($map, $args...) {
  $_: __scope(
    (
      "map": $map
    )
  );
  $property-of-function: __bind("__property-of-function");
  $_: __scope(false);

  @return $property-of-function;
}

/// Creates a function which returns the property value of `$key` on a given map.
///
///
/// @access public
/// @group Utility
/// @param {string} $key The key of the property to get.
/// @returns {Function} Returns the new function.
/// @example scss
/// $users: (
///   ( 'user': 'fred' ),
///   ( 'user': 'barney' )
/// );
///
/// $get-name: _property('user');
///
/// $foo: _map($users, $get-name);
/// // => ('fred', barney')
///
/// $foo: _pluck(_sort-by($users, $get-name), 'user');
/// // => ('barney', 'fred')

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

/// The inverse of `_property`; this method creates a function which returns
/// the property value of a given key on `$map`.
///
///
/// @access public
/// @group Utility
/// @param {Map} $map The map to inspect.
/// @returns {Function} Returns the new function.
/// @example scss
/// $map: ( 'a': 3, 'b': 1, 'c': 2 );
/// $foo: _map(('a', 'c'), _property-of($map));
/// // => (3, 2)
/// $foo: _sort-by(('a', 'b', 'c'), _property-of($map));
/// // => ('b', 'c', 'a')

@function _property-of($args...) {
  @return call(get-function("__property-of"), $args...);
}
