Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

This paper also participates inProject DigginTo win the creative gift package and challenge the creative incentive money.

I met the where

You’ve probably seen where in Swift.

Let’s start with a simple example, Sequence protocol source code:

public protocol Sequence { /// A type representing the sequence's elements. associatedtype Element where Self.Element ==  Self.Iterator.Element /// A type that provides the sequence's iteration interface and /// encapsulates its iteration state. associatedtype Iterator : IteratorProtocol }Copy the code

Associatedtype Element where self.element == self.iterator. Element the associatedtype Element must be of the same type as the Element in Iterator.

Where here represents a strong constraint.

If you’ve ever written an SQL statement by hand, you’ll understand the following:

let sql = "SELECT * FROM messageTable WHERE \(adminId) = ? AND \(companyId) = ? AND (\(self.typeId) = 0 OR \(self.typeId) = 1)"
Copy the code

Select * from table WHERE (adminId, companyId, typeId, 0, typeId, 1, companyId, companyId);

Is comparing WHERE in Swift to WHERE in SQL very semantically similar?

Note: In SQL, WHERE can also be written as WHERE.

So what are the uses of where in Swift?

Where is used for generic constraints

Let’s start with an example:

Struct Cat<T>: Animal {// struct Cat<T>: Animal {//Copy the code

If we want to make a more specific constraint on T, say we want the cat’s playmate to be an animal, how do we write it?

We can just write it like this:

struct Cat<T: Animal>: Animal {
    let playmate: T
}
Copy the code

You can also write:

struct Cat<T>: Animal where T: Animal {
    let playmate: T
}
Copy the code

Both are constraints on the generic T.

Where is used to specify the type

Struct Person {let age: Int let name: String} "season") let p2 = Person(age: 20, name: "soso") let p3 = Person(age: 30, name: "sola") let array = [p1, p2, p3]Copy the code

I want to print the name of the Person in an array like [Person] in one go how do I do that?

You say, why is that so hard? Just map it:

[p1, p2, p3].map { $0.name }
Copy the code

But what if the [Person] array’s method of printing name is used frequently and you want to wrap it into a method?

At this point, it would be nice to write an Array classification for where:

extension Array where Element == Person {
    func printName() {
        map {
            print($0.name)
        }
    }
}
Copy the code

[p1, p2, p3].printName().

Where is used to determine the condition of the for loop

Let array = [p1, p2, p3] let array = [p1, p2, p3] let array = [p1, p2, p3]

Normally we might write something like this:

For person in array {if person. Age == 20 {// do other business}}Copy the code

But we can write it more succinctly by using where:

For person in array where person. Age == 20 {Copy the code

Compare, two for loops, which one do you prefer?

Of course, another idea is to use the advanced function filter or the element that satisfies the condition first, and then do other business processing.

conclusion

Swift’s WHERE has a slightly similar taste to WHERE in SQL.

In Swift the common use of where is as follows:

  • For generic constraints, many generic constraints can be expressed in the form T: XXX, but the value of where comes into play when there is an associatedType association.

    Let’s take an example of the Collection protocol:

    public protocol Collection : Sequence {
    
        @available(*, deprecated, message: "all index distances are now of type Int")
    
        typealias IndexDistance = Int
    
        associatedtype Element
    
        /// A type that represents a position in the collection.
        ///
        /// Valid indices consist of the position of every element and a
        /// "past the end" position that's not valid for use as a subscript
        /// argument.
        associatedtype Index : Comparable where Self.Index == Self.Indices.Element, Self.Indices.Element == Self.Indices.Index, Self.Indices.Index == Self.SubSequence.Index, Self.SubSequence.Index == Self.Indices.Indices.Element, Self.Indices.Indices.Element == Self.Indices.Indices.Index, Self.Indices.Indices.Index == Self.SubSequence.Indices.Element, Self.SubSequence.Indices.Element == Self.SubSequence.Indices.Index, Self.SubSequence.Indices.Index == Self.Indices.Indices.Indices.Element, Self.Indices.Indices.Indices.Element == Self.Indices.Indices.Indices.Index, Self.Indices.Indices.Indices.Index == Self.SubSequence.Indices.Indices.Element, Self.SubSequence.Indices.Indices.Element == Self.SubSequence.Indices.Indices.Index, Self.SubSequence.Indices.Indices.Index == Self.SubSequence.Indices.Indices.Indices.Element, Self.SubSequence.Indices.Indices.Indices.Element == Self.SubSequence.Indices.Indices.Indices.Index
    }
    Copy the code

    Drag the code block to see an example of Index.

  • As well as being used for generic constraints, WHERE can also be used directly to specify the type, making it easier to write functions.

  • Where constraints and specification of generic parameters in writing functions abound in officially written apis:

    public func dynamicTypeSize<T>(_ range: T) -> some View where T : RangeExpression, T.Bound == DynamicTypeSize
    Copy the code
  • Where can be used to constrain its conditions in a for loop to simplify code and improve semantics.


We are in the usual use of what to usewhereWelcome to discuss and throw bricks.

Please answer me. Have you seen the Index of Collection agreement? Could you tell me something about it?


We’ll see you next time.