`toggled` or `isFalse` property/method on bool for use with KeyPath APIs

@Saklad5 you very precisely explicate the core of the issue here (emphasis mine). Your language needs to go into a proposal. I personally applaud your perspective to not only mention the benefits that adding support for operators in key paths would grant by expanding the discussion to the potential benefits of key path support for subscript methods.

What are subscript methods? I think key paths for subscripts are already supported as ["Swift": 5.5][keyPath: \.["Swift"]] works.

Yes, key path subscripts works as expected.

I believe the author @danhalliday was referring to these when mentioning subscript methods.

extension Collection where Indices.Iterator.Element == Index {

  subscript (safe index: Index) -> Iterator.Element? {
      return indices.contains(index) ? self[index] : nil
  }
}

let x = [1, 2, 3]

print(x[keyPath: <#...#>])

I always forget that replies don't appear as replies when they are first posted, thus the deleted previous comment. Someone link me to the discussion forum JIRA I'll file a ticket. :smiley:

I'm still confused, sorry. Isn't x[keyPath: \.[safe: 2]] enough? Or else, are you talking about unapplied subscript as object, like x[keyPath: \.[safe:]](2) (not possible now)?

1 Like

I believe it is only possible to use subscript methods in key paths terminally.

What you want is the ! operator, which already exists. You should not be using anything else for negation.

2 Likes

You are correct. The first expression you posted works. Here it is in an example,

struct Struct {
  var value: Int
}

let x = [Struct(value: 1), Struct(value: 2), Struct(value: 3)]

x[keyPath: \.[safe: 2]?.value] // 3

@Saklad5 does this not provide your need? Or were you looking for an expression like, to quote @ensan, x[keyPath: \.[safe:]](2) to work?

1 Like

I’m clearly confused about where you can use subscript key paths. I’m fairly sure you can’t, for instance, reference a value inside a dictionary that is itself a value inside a dictionary. Not in one expression, at least.

["Swift": ["5.5": 5.5]][keyPath: \.["Swift"]?["5.5"]] works.
But I know there are cases subscript key paths cause compile error saying "subscript index of type 'T in a key path must be Hashable". Maybe this?

class A { 
    subscript(_ a: A) -> Int { 42 } 
}
A()[keyPath: \.[A()]]

You can reference a value inside a dictionary that is itself a value inside a dictionary.

let dictionary = ["x": ["y": "z"]]
dictionary[keyPath: \.["x"]?["y"]] // z

As for @ensan's example, you can get around the error by using a standard library type like NSObject.


class A: NSObject {
    subscript(_ a: A) -> Int { 42 }
}
A()[keyPath: \.[A()]] // 42

This was due to the implementation of SE-0188.

1 Like