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)
}
aashish tamsya
quelle

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
}
AdamPro13
quelle
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] */
Andy Fedoroff
quelle
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
Bobby
quelle
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.

jood
quelle
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
BharathRao
quelle
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.

Димис Сетиус
quelle