[swift-evolution] Add AnyHashable to the standard library

Dmitri Gribenko gribozavr at gmail.com
Fri Jul 22 17:32:58 CDT 2016


Hi,

The implementation of SE-0116 "Import Objective-C id as Swift Any type"
requires a type-erased container for hashable values.

We are proposing to add such a type-erased container under the name
AnyHashable to the standard library.

This proposal is additive, source-breaking changes are discussed in SE-0116.

/// A type-erased hashable value.////// Forwards equality comparisons
and hashing operations to an/// underlying hashable value, hiding its
specific type.////// You can store mixed-type keys in `Dictionary` and
other/// collections that require `Hashable` by wrapping mixed-type
keys in/// `AnyHashable` instances://////     let descriptions:
[AnyHashable : Any] = [///         AnyHashable("😄"): "emoji",///
   AnyHashable(42): "an Int",///         AnyHashable(Int8(43)): "an
Int8",///         AnyHashable(Set(["a", "b"])): "a set of strings"///
   ]///     print(descriptions[AnyHashable(42)]!)      // prints "an
Int"///     print(descriptions[AnyHashable(43)])       // prints
"nil"///     print(descriptions[AnyHashable(Int8(43))]!) // prints "an
Int8"///     print(descriptions[AnyHashable(Set(["a", "b"]))]!) //
prints "a set of strings"public struct AnyHashable {
  /// Creates an opaque hashable value that wraps `base`.
  ///
  /// Example:
  ///
  ///     let x = AnyHashable(Int(42))
  ///     let y = AnyHashable(UInt8(42))
  ///
  ///     print(x == y) // Prints "false" because `Int` and `UInt8`
  ///                   // are different types.
  ///
  ///     print(x == AnyHashable(Int(42))) // Prints "true".
  public init<H : Hashable>(_ base: H)

  /// The value wrapped in this `AnyHashable` instance.
  ///
  ///     let anyMessage = AnyHashable("Hello")
  ///     let unwrappedMessage: Any = anyMessage.base
  ///     print(unwrappedMessage) // prints "hello"
  public var base: Any
}
extension AnyHashable : Equatable, Hashable {
  public static func == (lhs: AnyHashable, rhs: AnyHashable) -> Bool
  public var hashValue: Int {
}

We are adding convenience APIs to Set<AnyHashable> that allow using
existing Set APIs with concrete values that conform to Hashable. For
example:

func contains42(_ data: Set<AnyHashable>) -> Bool {
  // Works, but is too verbose:
  // return data.contains(AnyHashable(42))

  return data.contains(42) // Convenience API.
}

extension Set where Element == AnyHashable {
  public func contains<ConcreteElement : Hashable>(
    _ member: ConcreteElement
  ) -> Bool

  public func index<ConcreteElement : Hashable>(
    of member: ConcreteElement
  ) -> SetIndex<Element>?

  mutating func insert<ConcreteElement : Hashable>(
    _ newMember: ConcreteElement
  ) -> (inserted: Bool, memberAfterInsert: ConcreteElement)

  @discardableResult
  mutating func update<ConcreteElement : Hashable>(
    with newMember: ConcreteElement
  ) -> ConcreteElement?

  @discardableResult
  mutating func remove<ConcreteElement : Hashable>(
    _ member: ConcreteElement
  ) -> ConcreteElement?
}

Convenience APIs for Dictionary<AnyHashable, *>:

extension Dictionary where Key == AnyHashable {
  public func index<ConcreteKey : Hashable>(forKey key: ConcreteKey)
    -> DictionaryIndex<Key, Value>?

  public subscript(_ key: _Hashable) -> Value? { get set }

  @discardableResult
  public mutating func updateValue<ConcreteKey : Hashable>(
    _ value: Value, forKey key: ConcreteKey
  ) -> Value?

  @discardableResult
  public mutating func removeValue<ConcreteKey : Hashable>(
    forKey key: ConcreteKey
  ) -> Value?
}


Dmitri

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160722/507867d1/attachment.html>


More information about the swift-evolution mailing list