Was bedeuten $ 0 und $ 1 in Swift Closures?


75
let sortedNumbers = numbers.sort { $0 > $1 }
print(sortedNumbers)

Kann jemand erklären, was $0und $1was schnell bedeutet?

Mehr Probe

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

Antworten:


114

$0ist der erste Parameter, der an den Abschluss übergeben wird. $1ist der zweite Parameter usw. Der von Ihnen gezeigte Abschluss ist eine Abkürzung für:

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

Kann ich meine eigene Logik in einen Abschluss mit dem ersten und dem zweiten Parameter schreiben?
Aashish Tamsya

4
Ja, das ist der gesamte Zweck der Schließung.
AdamPro13

2
danke Kumpel, Ihre Antwort hat mir geholfen, den
größten

39

TL; DR

Swift 5.3

$0und $1sind die ersten und zweiten Kurzargumente von Closure (auch bekannt als Shorthand Argument Namesoder SANkurz). Die Namen der Kurzargumente werden automatisch von Swift bereitgestellt. Auf das erste Argument kann verwiesen werden $0, auf das zweite Argument kann verwiesen werden $1, auf das dritte Argument $2usw.

Wie Sie wissen, ist ein Closure ein in sich geschlossener Funktionsblock (eine Funktion ohne Namen), der weitergegeben und in Ihrem Code verwendet werden kann. Closure hat andere Namen in anderen Programmiersprachen sowie geringfügige Bedeutungsunterschiede - es ist Lambda in Python und Kotlin oder Block in C und Objective-C .


Schließen eines Verschlusses

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

1. Normale Funktion

func backward(_ n1: String, _ n2: String) -> Bool {
    return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)


/* RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"] */

2. Inline-Abschlussausdruck

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

3. Typ aus dem Kontext ableiten

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

4. Implizite Rückgaben von Einzelausdrucksabschlüssen

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

5. Kurzargumentnamen

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"] */


Funktion höherer Ordnung mapmit Punktnotation

let companies = ["bmw", "kfc", "ibm", "htc"]

let uppercasedCompanies = companies.map { (item) -> String in item.uppercased() }

/* RESULT: ["BMW", "KFC", "IBM", "HTC"] */

SAN in HOF mapmit Punktnotation

let uppercasedCompanies = companies.map { $0.uppercased() }

/* RESULT: ["BMW", "KFC", "IBM", "HTC"] */


SAN in HOF filtermit Restbetreiber

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] */


Wiederholen $0

let cubedNumber = { $0 * $0 * $0 } (25)

print(cubedNumber)

/* RESULT:  25^3 = 15625 */


Drei Stenografie Argument - Name - $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 */


Fünf SANs - $0, $1, $2, $3und$4

let factorial = { $0 * $1 * $2 * $3 * $4 } (1, 2, 3, 4, 5)

print(factorial)

/* RESULT:  5! = 120 */


Schlüsselpfadausdruck

In Swift 5.2 können Sie über den Schlüsselpfadausdruck auf Parameter jeder Instanz zugreifen:

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] */

Natürlich können Sie alternativ eine bekannte Syntax verwenden:

Regelmäßige Syntax -$0.property :

let refillableOnes = lighters.map { $0.refillable }

print(refillableOnes)

/* RESULT:  [true, false] */


Kurzargument Name mit einem Index

let arrays: [[String]] = [["Hello", "Hola"], ["world", "mundo"]]

let helloWorld = arrays.compactMap { $0[0] }

print(helloWorld)

/* RESULT:  ["Hello", "world"] */


Kurzargumentname im Completion Handler

let completionHandler: (Bool) -> Void = {
    if $0 {
        print("It is true, sister...")
    }
}

Die reguläre Syntax lautet jedoch wie folgt:

let completionHandler: (Bool) -> Void = { sayTheTruth in
    if sayTheTruth {
        print("It is true, sister...")
    }
}


Swift gegen Kotlin gegen Python

Lassen Sie uns auch sehen, wie Kotlins Lambda Swifts Schließung ähnelt:

Schnell

let element: [String] = ["Argentum","Aurum","Platinum"]

let characterCount = element.map { $0.count }

print(characterCount)

/* RESULT:  [8, 5, 8] */ 

Kotlin

Oft hat Kotlins Lambda-Ausdruck nur einen Parameter mit implizitem Namen :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] */

Ihr Python-Beispiel verwendet unnötigerweise ein Lambda. list(map(len, ....))würde genügen. Persönlich würde ich verwenden, es sei denn, in einem kritischen Leistungsabschnitt, [len(v) for v in ...]weil es sauberer und besser lesbar ist.
Martijn Pieters

Danke Martijn, ich werde darüber lesen und es reparieren.
Andy Fedoroff

1
Bitte fügen Sie eine schnelle Dokumentation hinzu. Link
AsifHabib

Hallo @AsifHabib! Welchen Docs-Link meinst du - offizielle Entwickler-Docs oder andere?
Andy Fedoroff

1
@AndyFedoroff Offizielle Dokumentation
AsifHabib

33

Es stellt Kurzargumente dar, die in einen Abschluss gesendet wurden. In diesem Beispiel wird Folgendes aufgeschlüsselt:

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

6
Da der Additionsoperator dieselbe Funktionssignatur wie dieser Abschluss hat, können Sie ihn noch weiter add = (+)
aufteilen

Es sollte den Typ mit var add:((Int, Int) -> Int) = ...explizit für die Fälle 3 und 4 in meinem schnellen 5-Test angeben .
Itachi

6

Die beziehen sich auf das erste und zweite Argument der Art. Hier werden sort2 Elemente verglichen und sortiert. Weitere Informationen finden Sie in der offiziellen Dokumentation von Swift :

Swift stellt Inline-Abschlüssen automatisch Kurzargumentnamen zur Verfügung, mit denen auf die Werte der Argumente des Abschlusses mit den Namen $ 0, $ 1, $ 2 usw. verwiesen werden kann.


3

Zusätzlich zu @ Bobbys Antwort möchte ich ein Beispiel hinzufügen

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

Dies kann nicht als Antwort gelten. Wenn Sie ein Beispiel hinzufügen möchten, bearbeiten Sie einfach die Antwort von
@ bobby

2

Es handelt sich um Kurzargumentnamen.

Swift stellt Inline-Abschlüssen automatisch Kurzargumentnamen zur Verfügung, mit denen auf die Werte der Argumente des Abschlusses mit den Namen $ 0, $ 1, $ 2 usw. verwiesen werden kann.

Wenn Sie diese Kurzargumentnamen in Ihrem Abschlussausdruck verwenden, können Sie die Argumentliste des Abschlusses in der Definition weglassen, und die Anzahl und der Typ der Kurzargumentnamen werden aus dem erwarteten Funktionstyp abgeleitet. Das Schlüsselwort in kann auch weggelassen werden, da der Abschlussausdruck vollständig aus seinem Körper besteht:

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

Hier beziehen sich $ 0 und $ 1 auf das erste und zweite String-Argument des Abschlusses.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.