Wat betekenen $0 en $1 in Swift Closures?

Kan iemand uitleggen wat $0en $1betekenen in swift?

Meer voorbeeld

array.forEach {
    actions.append($0)
}

Antwoord 1, autoriteit 100%

$0is de eerste parameter die in de sluiting wordt doorgegeven. $1is de tweede parameter, enz. De sluiting die je liet zien is een afkorting voor:

let sortedNumbers = numbers.sort { (firstObject, secondObject) in 
    return firstObject > secondObject
}

Antwoord 2, autoriteit 50%

TL;DR

Snelle 5.5

$0en $1zijn de eerste en tweede steno-argumenten van Closure(ook bekend als Shorthand Argument Namesof SANin het kort). De steno-argumentnamen worden automatisch geleverd door Swift. Naar het eerste argument kan worden verwezen door $0, naar het tweede argument kan worden verwezen door $1, naar het derde door $2, enzovoort.

Zoals u weet, is een Sluitingeen op zichzelf staand blok van functionaliteit (een functie zonder naam) die kan worden doorgegeven en gebruikt in uw code. Sluiting heeft verschillende namen in andere programmeertalen en ook kleine verschillen in betekenis – het is Lambdain Python en Kotlin, of Blockin C en Obj-C.

Een sluiting inkorten

let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]

1. Normale functie

func backward(_ n1: String, _ n2: String) -> Bool {
    return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)
/* RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"] */

2. Inline sluitingsuitdrukking

reverseOrder = coffee.sorted(by: { (n1: String, 
                                    n2: String) -> Bool in return n1 > n2 } )

3. Type afleiden uit context

reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )

4. Impliciete opbrengst van sluitingen met één expressie

reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )

5. Namen van steno-argumenten

reverseOrder = coffee.sorted(by: { $0 > $1 } )
/* $0 and $1 are closure’s first and second String arguments. */

6. Operatormethoden

reverseOrder = coffee.sorted(by: >)
/* RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"] */

Hogere orde functie mapmet puntnotatie

let companies = ["bmw", "kfc", "ibm", "htc"]
let uppercased = companies.map { (item) -> String in item.uppercased() }
/* RESULT: ["BMW", "KFC", "IBM", "HTC"] */

Shorthand Argumentnaam in HOF map

let uppercased = companies.map { $0.uppercased() }
/* RESULT: ["BMW", "KFC", "IBM", "HTC"] */

SAN in HOF filtermet operator voor rest

let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let filteredNumbers = numbers.filter { ($0 % 2) == 0 }
print(filteredNumbers)
/* RESULT: [2, 4, 6, 8, 10] */

SAN in Variadische functies

Variadische functies zijn functies die een willekeurig aantal parameters accepteren. Verkorte argumentnamen zijn perfect voor dergelijke gevallen.

fileprivate func dessert(_ fruits: String...) -> Bool {
    return fruits.contains { $0 == "Apple" }
}
let contains = dessert("Mango", "Durian", "apple")
print(contains)
/* RESULT:  false */

Herhalen van $0

let cubedNumber = { $0 * $0 * $0 } (25)
print(cubedNumber)
/* RESULT:  25^3 = 15625 */

Drie steno-argumentnamen – $0, $1, $2

let math: (Int8, Int8, Int8) -> Int8 = { $0 + $1 - $2 }
func feedClosure() -> (Int8, Int8, Int8) -> Int8 {
    return math
}
feedClosure()(10, 20, 100)
/* RESULT:  (10 + 20 - 100) = -70 */

Vijf SAN’s – $0, $1, $2, $3, $4

let factorial = { $0 * $1 * $2 * $3 * $4 } (1, 2, 3, 4, 5)
print(factorial)
/* RESULT:  5! = 120 */

Toetsenpadexpressie

In Swift 5.2 hebt u toegang tot parameters van elke instantie via sleutelpadexpressie:

struct Lighter {
    let manufacturer: String
    let refillable: Bool
}
let zippo = Lighter(manufacturer: "Zippo", refillable: true)
let cricket = Lighter(manufacturer: "Cricket", refillable: false)
let lighters: [Lighter] = [zippo, cricket]
let refillableOnes = lighters.map(\.refillable)
print(refillableOnes)
/* RESULT:  [true, false] */

Natuurlijk kunt u ook een bekende syntaxis gebruiken:

Gewone syntaxis – $0.property:

let refillableOnes = lighters.map { $0.refillable }
print(refillableOnes)
/* RESULT:  [true, false] */

Shorthand Argumentnaam met een subscript

let arrays: [[String]] = [["Hello", "Hola"], ["world", "mundo"]]
let helloWorld = arrays.compactMap { $0[0] }
print(helloWorld)
/* RESULT:  ["Hello", "world"] */

Nog een voorbeeld met een subscript:

let dictionaries: [[Int8: Any?]] = [[1: "x"], [2: nil], [3: "z"]]
let values = dictionaries.compactMap { $0[$0.startIndex].value }
print(values) 
/* RESULT:  ["x", "z"] */

Of bekijk dit voorbeeld:

let sett: Set<String> = ["One", "", "Three"]
sett.map {
    switch $0.isEmpty {
        case true:
            print("Empty")
        case false:
            print("Element \($0) isn't empty")
    }
}
/*   RESULT:   "Element Three isn't empty"  */
/*             "Empty"                      */
/*             "Element One isn't empty"    */

Shorthand-argumentnaam in voltooiingshandler

let completionHandler: ((Bool) -> Void)? = {
    if $0 {
        print("It is true, sister...")
    } else {
        print("False")
    }
}
completionHandler?(true)
/* RESULT:  It is true, sister... */

De normale syntaxis is echter als volgt:

let completionHandler: ((Bool) -> Void)? = { sayTheTruth in
    if sayTheTruth {
        print("It is true, sister...")
    } else {
        print("False")
    }
}
completionHandler?(false)
/* RESULT:  False */

SAN in ForEach-structuur in SwiftUI

let columns: [GridItem] = Array(repeating: .init(.fixed(70)), count: 5)
var body: some View {
    ScrollView {
        LazyVGrid(columns: columns) {
            ForEach((1...10), id: \.self) {
                Text("\($0)").frame(maxWidth: .infinity)
            }
        }
    }
}
/*   RESULT:   1  2  3  4  5   */
/*             6  7  8  9  10  */

Operatormethode versus SAN

Operatormethode:

let records: [Int] = [110, 108, 107, 109, 108]
public func averageSpeed(records: [Int]) throws -> Int {
    let average = records.reduce(0, +) / records.count
    return average
}
try averageSpeed(records: records)
/* RESULT:  108 */

Shorthand-argumentnamen $0 en $1:

public func averageSpeed(records: [Int]) throws -> Int {
    let average = records.reduce(0) { $0 + $1 } / records.count
    return average
}
try averageSpeed(records: records)
/* RESULT:  108 */

Swift vs Kotlin vs Python

Laten we ook eens kijken hoe de lambda van Kotlin lijkt op de sluiting van Swift:

Snel

let element: [String] = ["Argentum","Aurum","Platinum"]
let characterCount = element.map { $0.count }
print(characterCount)
/* RESULT:  [8, 5, 8] */ 

Kotlin

Vaak heeft de lambda-expressie van Kotlin maar één parameter met een impliciete naam: it.

val element = listOf("Argentum","Aurum","Platinum")
val characterCount = element.map { it.length }
println(characterCount)
/* RESULT:  [8, 5, 8] */

But in Python there's no equivalent of Shorthand Argument Name.

Python

element = ["Argentum","Aurum","Platinum"]
characterCount = list(map(lambda x: len(x), element))
print(characterCount)
# RESULT:  [8, 5, 8]

Antwoord 3, autoriteit 23%

Het vertegenwoordigt shorthanded argumenten die naar een afsluiting zijn gestuurd, dit voorbeeld splitst het op:

Swift 4:

var add = { (arg1: Int, arg2: Int) -> Int in
    return arg1 + arg2
}
add = { (arg1, arg2) -> Int in
    return arg1 + arg2
}
add = { arg1, arg2 in
    arg1 + arg2
}
add = {
    $0 + $1
}
let result = add(20, 20) // 40

Antwoord 4, autoriteit 4%

De verwijzen naar de eerste en tweede soort argumenten. Hier vergelijkt sort2 elementen en rangschikt ze.
Je kunt Swift officiële documentatieopzoeken voor meer informatie info:

Swift geeft automatisch namen van steno-argumenten aan inline
sluitingen, die kunnen worden gebruikt om te verwijzen naar de waarden van de sluitingen
argumenten met de namen $0, $1, $2, enzovoort.


Antwoord 5, autoriteit 3%

Aanvullend op @Bobby’s antwoord wil ik graag een voorbeeld toevoegen

var add: (Int,Int,Int)->Int
add = {
//So here the $0 is first argument $1 is second argument $3 is third argument
    return $0 + $1 + $2
//The above statement can also be written as $0 + $1 + $2 i.e is return is optional
}
let result = add(20, 30, 40) 
print(result) // Prints 90

Antwoord 6

Het zijn verkorte argumentnamen.

Swift geeft automatisch steno-argumentnamen aan inline-afsluitingen, die kunnen worden gebruikt om naar de waarden van de argumenten van de afsluiting te verwijzen met de namen $0, $1, $2, enzovoort.

Als u deze steno-argumentnamen gebruikt in uw sluitingsuitdrukking, kunt u de lijst met argumenten van de sluiting weglaten uit de definitie, en het aantal en type van de steno-argumentnamen worden afgeleid uit het verwachte functietype. Het sleutelwoord in kan ook worden weggelaten, omdat de sluitingsexpressie volledig uit de body bestaat:

   reversed = names.sort( { $0 > $1 } )

Hier verwijzen $0 en $1 naar de eerste en tweede String-argumenten van de sluiting.

Other episodes