[Pitch] Add KeyPaths Boolean custom operators

While what you're talking about should be part of the standard library, negation is too common to not be in the standard library too. Just like toggle(), the lack of it won't last. Everybody needs it, all the time.

(toggled, as shown above, is not an accurate name for this, however—"toggled" means you flip the thing via mutation first and then return the flipped value. That doesn't work with key paths.)

public extension Bool {
  /// Toggle, and return the new value.
  var toggled: Self {
    mutating get {
      toggle()
      return self
    }
  }
}

I don't think the other ones add anything.

(\.value == false)
{ $0.value == false }

The general form works for key path expressions:

infix operator …

public func … <Root, Value, Transformed>(
  value: @escaping (Root) -> Value,
  transform: @escaping (Value) -> Transformed
) -> (Root) -> Transformed {
  { transform(value($0)) }
}

public prefix func !<Root>(
  getBool: @escaping (Root) -> Bool
) -> (Root) -> Bool {
  getBool…(!)
}

But you also need the specialized form to deal with key paths when they're variables:

public extension KeyPath {
  /// - Returns: A closure that returns a transformed `Value`.
  func map<Transformed>(
    _ transform: @escaping (Value) -> Transformed
  ) -> (Root) -> Transformed {
    { transform($0[keyPath: self]) }
  }
}

public extension KeyPath where Value == Bool {
  static prefix func !(keypath: KeyPath) -> (Root) -> Value {
    keypath.map(!)
  }
}
1 Like