I see. I didn't realize you were actually trying to support
ingredients["potato"].toggle()
So no, you're not talking about set-only properties. But you are talking about named subscripts, another one of my favorite missing features*! 
And I'm in agreement that contains
should be one of those, instead of a method.
var set: Set = [1, 2, 3]
XCTAssert(set.contains[3])
set.contains[1] = false
XCTAssertEqual(set, [2, 3])
var contains = set.contains
contains[3].toggle()
XCTAssertEqual(set, [2])
contains.set = { _, _, _ in }
contains[2].toggle()
XCTAssertEqual(set, [2])
var four: Set = [4]
withUnsafeMutablePointer(to: &four) {
contains.pointer = $0
XCTAssert(contains[4])
}
The way we can express this is not good enough, because it won't work on constants. Currently, you need to take an Objective-C-like approach, with functions/properties for the use case of get-only named subscripts
public extension SetAlgebra {
var contains: Subscript<Self, Element, Bool> {
mutating get {
.init(
&self,
get: Self.contains,
set: { set, element, newValue in
if newValue {
set.insert(element)
} else {
set.remove(element)
}
}
)
}
}
}
The way we can implement it ourselves works, but it'll break at some point if you abuse it past the one-liner typical use case. That is not good enough. They need to be in the language.
/// An emulation of the missing Swift feature of named subscripts.
/// - Note: Argument labels are not supported.
public struct Subscript<Root, Index, Value> {
public typealias Pointer = UnsafeMutablePointer<Root>
public typealias Get = (Root) -> (Index) -> Value
public typealias Set = (inout Root, Index, Value) -> Void
public var pointer: Pointer
public var get: Get
public var set: Set
}
public extension Subscript {
init(
_ pointer: Pointer,
get: @escaping Get,
set: @escaping Set
) {
self.pointer = pointer
self.get = get
self.set = set
}
subscript(index: Index) -> Value {
get { get(pointer.pointee)(index) }
nonmutating set { set(&pointer.pointee, index, newValue) }
}
}
β¦* Now that we have callAsFunction
, there's no reason for both ()
and []
syntax anymore. I say "named subscript", because that's what this kind of thing would be in older languages, but we probably should get rid of []
and allow assignment to the result of ()
s