# operator (\~=)

[Swift](https://lochiwei.gitbook.io/ios/swift) ⟩ [Patterns](https://lochiwei.gitbook.io/ios/swift/pattern-matching) ⟩

{% hint style="warning" %}
⭐️ 注意：在自訂 \~= 運算時，一定要遵循 <mark style="color:purple;">**`pattern ~= value`**</mark> 的模式。

```swift
func ~=<P, V>(pattern: P, value: V) -> Bool
```

{% endhint %}

{% hint style="info" %}
Swift uses various <mark style="color:orange;">**overloads**</mark> of the <mark style="color:purple;">**`~=`**</mark> operator to do <mark style="color:red;">**pattern matching**</mark>, which also lets us <mark style="color:orange;">**define our own overloads**</mark> ... 👉 [Sundell](https://www.swiftbysundell.com/articles/pattern-matching-in-swift/#under-the-hood-with-custom-matching)
{% endhint %}

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="info" %}
[Ole](https://oleb.net/blog/2015/09/swift-pattern-matching/) 提及如何設計一個 generic operator：

```swift
func ~=<T>(pattern: (T) -> Bool, value: T) -> Bool {
    return pattern(value)
}
```

{% endhint %}

{% hint style="info" %}
[Sundell](https://www.swiftbysundell.com/articles/defining-custom-patterns-in-swift/) 提及如何設計一個 generic pattern：

```swift
// Sundell 的做法等於是將 Ole 的做法包裝在一個 struct 裡面，
// 但兩者的精神是一樣的。
struct Pattern<Value> {
    let match: (Value) -> Bool
}

func ~=<T>(pattern: Pattern<T>, value: T) -> Bool {
    pattern.match(value)
}
```

{% endhint %}
{% endtab %}

{% tab title="💈例一" %}
💾 程式：[replit](https://replit.com/@pegasusroe/pattern-matching-operator#main.swift)

```swift
// -----------------------------
//     ⭐ custom ~= operator 
// -----------------------------

// matches a "boolean keypath into a type" (instance.booleanProperty)
// against an "instance of that type"      (instance)
// ⭐ matching pattern: "pattern" ~= "value"
func ~=<T>(keypath: KeyPath<T, Bool>, instance: T) -> Bool {
    // ⭐ \.isNumber ~= Character("3") returns Character("3").isNumber
    return instance[keyPath: keypath]
}

// extension
extension Character {
    func expressYourself() {
        switch self {

            // built-in ~=
            case "<"        : print("\(self) is an Element tag")
            case "#"        : print("\(self) is a Hash tag")

            // ⭐ custom ~= applied here
            case \.isNumber : print("\(self) is a Number")
            case \.isNewline: print("\(self) is a NewLine")

            default         : print("\(self) is something else")
        }
    }
}

// ------------
//     main 
// ------------

let chars: [Character] = [
    "<", "#", "8", "\n", "x"
]

chars.forEach { $0.expressYourself() }
// < is an Element tag
// # is a Hash tag
// 8 is a Number
//
//  is a NewLine
// x is something else
```

{% endtab %}

{% tab title="💈例二" %}
💾 程式：[replit](https://replit.com/@pegasusroe/pattern-matching-operator#main.swift)

```swift
// ⭐ `str ~= person` returns `str == person.name`
func ~=(str: String, person: Person) -> Bool {
    return str == person.name
}

// custom type
struct Person {
    let name : String
}

extension Person {
    func areYou(_ name: String) {
        switch name {

            // ⭐ custom ~= applied here
            case self.name: print("Hey it's me!")

            default   : print("Not me")
        }
    }
}

let joe = Person(name: "Joe")
joe.areYou("Joe")               // Hey it's me!
```

{% endtab %}

{% tab title="📗 參考" %}

* [x] Ole ⟩ [Pattern Matching in Swift](https://oleb.net/blog/2015/09/swift-pattern-matching/) (⭐️ 重點)
* [ ] Sundell ⟩&#x20;
  * [x] [Using key paths in switch statements](https://www.swiftbysundell.com/tips/using-key-paths-in-switch-statements/) ⭐️ (💈例一)
  * [ ] [Defining custom patterns in Swift](https://www.swiftbysundell.com/articles/defining-custom-patterns-in-swift/) - model the "pattern" concept into a generic custom type <mark style="color:red;">**`struct`**</mark> <mark style="color:purple;">**`Pattern<Value>`**</mark>. (⭐️ 重點)
    {% endtab %}

{% tab title="👥 相關" %}

* [op](https://lochiwei.gitbook.io/ios/swift/op "mention") - all operators
* [enum-case-pattern](https://lochiwei.gitbook.io/ios/swift/pattern-matching/enum-case-pattern "mention")
* [filter-cases](https://lochiwei.gitbook.io/ios/swift/type/category/basic/enum/filter-cases "mention")
* [generic-types](https://lochiwei.gitbook.io/ios/swift/type/category/generic-types "mention") - about generic functions/types.
* [key-path](https://lochiwei.gitbook.io/ios/features/key-path "mention") - pattern matching using [<mark style="color:orange;">**keypath**</mark>](https://lochiwei.gitbook.io/ios/features/key-path). (💈例一)
* [casereflectable](https://lochiwei.gitbook.io/ios/swift/debugging/casereflectable "mention") - custom protocol for enum <mark style="color:orange;">**case name**</mark> & <mark style="color:orange;">**associated values**</mark>.
* [switch-on-other-types](https://lochiwei.gitbook.io/ios/swift/pattern-matching/sentence-patterns/switch-on-other-types "mention") - switch on <mark style="color:orange;">**custom types**</mark>.
  {% endtab %}

{% tab title="🗣 討論" %}

* [\~= operator in Swift](https://stackoverflow.com/questions/38371870/operator-in-swift) ⭐️ (💈例二)
  {% endtab %}

{% tab title="❓" %}
{% hint style="warning" %}

{% endhint %}
{% endtab %}
{% endtabs %}
