[Swift] Ein Hinweis zu Funktion und Schließung

Ich habe für mich selbst gelernt, also mach dir eine Notiz

import Foundation

//Die Verarbeitung kann vereinheitlicht werden
//Funktionen sind eine Art Schließung
//Die Wartbarkeit und Lesbarkeit kann verbessert werden, indem der Prozess ausgeschnitten und geschrieben wird.
// function
/*
Funktionsname(Argumentname: Type, Argumentname: Type ...) ->Rückgabetyp{
Anweisung, die ausgeführt wird, wenn eine Funktion aufgerufen wird
Geben Sie den Rückgabewert bei Bedarf mit einer return-Anweisung zurück
}
 */

func double(_ x: Int) -> Int {
    return x * 2
}

double(2) // 4
//Ausführungsmethode
//let Konstante name = Funktionsname (Argumentname 1: Argument 1, Argumentname 2: Argument 2...)
func functionWithDiscardResult() -> String {
    return "Discardable"
}

_ = functionWithDiscardResult() // Discardable
//Streit
func printInt(_ int: Int) {
    print(int)
}

printInt(1) // 1
//Name des externen Arguments und Name des internen Arguments
//Externes Argument = wird beim Aufruf verwendet
//Internes Argument = was in der Funktion verwendet wird
/*
Funktionsfunktionsname (internes Argument: Typ, externes Argument internes Argument: Typ){}
 */


func invite(user: String, to group: String) {
    print("\(user) is invited to \(group)")
}

invite(user: "tanaka", to: "kendo club")

//Auslassung externer Argumente_Benutze das
func sum(_ int1: Int, _ int2: Int) -> Int {
    return int1 + int2
}

sum(10, 10) // 20
//Standardargument
//Sie können alles setzen
func greet(user: String = "Anonymos") {
    print("Hello \(user)")
}

greet() // Hello Anonymos
greet(user: "tanaka") 
//Es gibt drei Argumente, die das Suchwort, den Sortierschlüssel und die aufsteigende Reihenfolge angeben.
//Da Sie lediglich ein Suchwort benötigen, können Sie Standardeinstellungen für unnötige Argumente festlegen.
//Wenn Sie nur nach dem Suchschlüsselwort suchen möchten oder wenn Sie nach dem Sortierschlüssel usw. suchen möchten, können Sie dies mit einer Funktion erledigen.
func search(byQuery query: String,
            sortKey: String = "id",
            ascending: Bool = false) -> [Int] {
    return [1, 2, 3]
}

search(byQuery: "query")

//In-Out-Argument
//Fügen Sie bei der Neuzuweisung zu einem Argument innerhalb einer Funktion außerhalb der Funktion inout oder einen Fehler hinzu
//Kann als temporärer Wert eingegeben werden
//Fügen Sie & hinzu, um das inout-Argument aufzurufen
//Fehler, wenn nicht angehängt: Wert des Typs übergeben'String' to an inout parameter requires explicit '&'
func greetA(user: inout String) {
    if user.isEmpty {
        user = "Anonymos"
    }
    print("Hello \(user)")
}
var user: String = ""
greetA(user: &user)

//Argument variabler Länge Argument, das eine beliebige Anzahl von Werten empfängt
//Verdienst: Machen Sie den Aufrufer der Funktion nicht darauf aufmerksam, dass es sich um ein Array handelt
//Bis zu eins in einer Funktion
//Werden Sie ein Array-Typ
func printA(strings: String...) {
    if strings.count == 0 {
        return
    }

    print("first: \(strings[0])")

    for str in strings {
        print("element: \(str)")
    }
}

printA(strings: "abc", "def","ghi")

//first: abc
//element: abc
//element: def
//element: ghi
//Argumentprüfung
func stringA(from: Int) -> String {
    return "\(int)"
}

let int = 1
let double = 1.0

let str1 = stringA(from: int)
// let str2 = stringA(from: double) // error
// Cannot convert value of type 'Double' to expected argument type 'Int'
//Rückgabewert
//keine Rückkehr
func greetB(user: String) {
    print("Hello \(user)")
}

greetB(user: "tanaka")
//Das gleiche wie oben
func greetC(user: String) -> Void {
    print("Hello \(user)")
}
greetC(user: "tanaka")

//Implizite Rückgabe
//Wenn nur der Rückgabewert, kann die Rückgabe weggelassen werden
func makeMassage(toUser user: String) -> String {
    "Hello, \(user)"
}

//Dies ist ein Fehler
// Missing return in a function expected to return 'String'
/*
Wenn es einen anderen Wert als den Rückgabewert gibt, kann die Rückgabe nicht weggelassen werden.
func makeMassage1(toUser user: String) -> String {
    print(user)
    "Hello, \(user)"
}
 */

//Schließung
/*
Verarbeitung einer Gruppe von Variablen und Konstanten im Bereich
 { (Argument 1: Typ, Argument 2: Typ)->Rückgabewert in
Anweisung ausgeführt, wenn der Abschluss ausgeführt wird
Geben Sie den Rückgabewert bei Bedarf mit einer return-Anweisung zurück
}
 */

//Nimmt ein Argument vom Typ Int und gibt den Rückgabewert vom Typ Int zurück, der verdoppelt wird (Int) → Der Abschluss des Int-Typs wird ausgeführt
let doubleA = {(x: Int) -> Int in
    return x * 2
}
doubleA(2) // 4
//Da der Schließungstyp wie ein normaler behandelt werden kann, kann er auch als variabler oder konstanter Typ oder als Funktionsargument verwendet werden.
let closure: (Int) -> Int
func someFunctionAA(x: (Int) -> Int) {}

closure = { int in
    return int * 2
}
closure(1)

//Typinferenz
var closureA: (String) -> Int

//Wenn das Argument und der Rückgabewert angegeben sind
closureA = { (str: String) -> Int in
    return str.count
}
closureA("abc") // 3
//Wenn weggelassen
closureA = { str in
    return str.count * 2
}
closureA("abc") // 6
//Fehler, wenn der Typ nicht entschieden wird
// Unable to infer type of a closure parameter 'str' in the current context
//let butClosure = { str in
//    return str.count * 2
//}

//Ausführungsmethode
//Die Aufrufmethode entspricht der Funktion
//Fügen Sie () am Ende des Variablennamens oder Konstantennamens hinzu, dem der Abschluss zugewiesen ist, und geben Sie das Argument in () ein.,’Nach Trennzeichen anordnen
//Der Rückgabewert wird einer Variablen oder Konstante zugewiesen
//Lassen Sie Konstantenname = Variablenname (Argument 1, Argument 2)
//Variablen und Konstanten, denen der Abschluss zugeordnet ist, werden als Abschlussart vom Typ abgeleitet.
//Anzahl der Zeichenfolgen zählen
//Das gleiche wird gemacht, aber der Schreibstil ist anders
let lengthOfString = { (string: String) -> Int in  // (String) -> Int
    return string.count
}
lengthOfString("abcdefghijklmnopqrstuvwxyz") // 26

func lengthOfStringA(_ string: String) -> Int {
    return string.count
}
lengthOfStringA("abcdefghijklmnopqrstuvwxyz") // 26
//Streit
//Closer kann keine externen und Standardargumente verwenden
//Gleich wie das Weglassen des Arguments
let add = { (x: Int, y: Int) -> Int in
    print(x + y)
    return x + y
}
add(1,2) // 3
func addFunc(_ x: Int, _ y: Int) -> Int {
    print(x + y)
    return x + y
}

addFunc(1, 2) // 3
//Kurzes Argument Weglassen des Argumentnamens
// $0 oder so$1 kann verwendet werden
let isEqual: (Int, Int) -> Bool = {
    return $0 == $1
}

isEqual(1,1) // true
isEqual(2,1) // false
let keisan: (Int, Int) -> Int = {
    return $0 + $1
}
keisan(1,2) // 3
//Bei Verwendung von abgekürzten Argumenten wird der Typ des Arguments nicht in der Abschlussdefinition angegeben. Daher tritt ein Fehler auf, wenn der Typ nicht von außen abgeleitet werden kann.
//Wenn Sie es unachtsam verwenden, handelt es sich in der Regel um einen Code mit geringer Lesbarkeit, bei dem Sie nicht wissen, was das Argument bedeutet.
//Es kann sehr einfach sein, daher ist es besser, es positiv zu verwenden
let numbers = [10,20,30,40]
//offiziell
// func filter(_ isIncluded: (Int) throws -> Bool) rethrows -> [Int]
// filter(isIncluded: (Int) throws -> Boo)
//Das Folgende ist dasselbe wie das, was ich tue, aber es ist leicht zu lesen, weil es weggelassen wird
let aaaaaa = numbers.filter { val -> Bool in
    val > 20
}
let bbbbbb = numbers.filter { val in
    val > 20
}
let moreThenTwenty = numbers.filter { $0 > 20 }

aaaaaa          // [30, 40]
bbbbbb          // [30, 40]
moreThenTwenty  // [30, 40]
//Rückgabewert
//Keiner
let emptyReturnValueClosure: () -> Void = {}
//Da ist einer
let singleReturnValueClosure: () -> Int = { return 1 }
// ()Und Void sind gleich, aber im Falle eines Abschlusses verwenden Sie Void, wenn es keinen Rückgabewert gibt
// ❌ () -> ()
// ❌ Void -> Void
// ⭕️ () -> Void
//Erfassen von Variablen und Konstanten mit Abschlüssen
/*
Normalerweise können im lokalen Bereich definierte Variablen und Konstanten nicht außerhalb des lokalen Bereichs verwendet werden.
Die Variablen und Konstanten, auf die im einstufigen Abschluss verwiesen wird
Auch wenn der Bereich, in dem der Abschluss ausgeführt wird, nicht der lokale Bereich ist, in dem Variablen und Konstanten definiert sind
Verfügbar beim Schließen des Verschlusses
Dies liegt daran, dass der Abschluss Verweise auf Variablen und Konstanten in einem eigenen definierten Bereich enthält.
Dies wird als Erfassung bezeichnet
 */

let greeting: (String) -> String
/*-----------------------------*/
do {
    let symbol = "!"
    greeting = { user in
        return "Hello, \(user)\(symbol)"
    }
}

greeting("ken") // "Hello, ken!"
// symbol :::Fehler, weil das Symbol in einem anderen Bereich definiert ist
// Cannot find 'symbol' in scope
//Da die konstante Begrüßung außerhalb des Bereichs do deklariert ist, kann sie außerhalb des Bereichs do verwendet werden.
//Das Konstantensymbol kann nicht außerhalb verwendet werden, da es im Rahmen von do deklariert ist.
//Der der konstanten Begrüßung zugewiesene Abschluss kann jedoch außerhalb von do ausgeführt werden, obwohl intern ein Symbol verwendet wird.
//Dies wird erreicht, indem der Abschluss durch Erfassen einen Verweis auf Variablen und Konstanten in seinem eigenen definierten Bereich enthält.
//Das Ziel der Erfassung ist nicht der Wert, der in der Variablen oder Konstante enthalten ist, sondern die Variable oder das konstante Vertrauen.
//Daher werden Änderungen an den erfassten Variablen in der Ausführung des Abschlusses berücksichtigt.
//Beispiel
//Im Folgenden erhöht der dem konstanten Zähler zugewiesene Abschluss den Wert der Variablenanzahl bei jeder Ausführung um 1.
//Der Anfangswert der Variablenanzahl ist 0, aber da die Variable selbst erfasst wird, werden auch Aktualisierungen der Variablen beibehalten.
//Daher ist es bei jeder Ausführung ein anderer Wert.
let counter: () -> Int

do {
    var count = 0
    counter  = {
        count += 1
        return count
    }
}

counter() // 1
counter() // 2
counter() // 3
counter() // 4
counter() // 5

//Näher als Argument
//Als Spezifikation, die nur gültig ist, wenn ein Abschluss als Argument einer Funktion oder eines anderen Abschlusses verwendet wird
//Hat Attribute und einen abschließenden Abschluss
//Attribute sind zusätzliche Informationen, die Sie für Abschlüsse angeben
//Trailing Closure ist eine Spezifikation zur Verbesserung der Lesbarkeit von Funktionen, die Argumente annehmen.
//Attributspezifikation
/*
Es gibt zwei Attribute
  - escaping
  - autoclosure
Funktionsname(Argument: @ Attributname, Abschlussartname){
Anweisung, die ausgeführt wird, wenn eine Funktion aufgerufen wird
 }
 */

//func or(_ lhs: Bool, _ rhs: @autoclosure () -> Bool) -> Bool {
//    if lhs {
//        return true
//    } else {
//        return rhs()
//    }
//}
//
//or(true, false) // true
// escaping
//Näher, der asynchron ausgeführt wird
/*
Ein Attribut, das angibt, dass der als Funktionsargument übergebene Abschluss außerhalb des Funktionsumfangs verbleibt.
Der Compiler bestimmt anhand des Vorhandenseins oder Nichtvorhandenseins des Escape-Attributs, ob der Abschluss erfasst werden muss.
Wenn der Abschluss außerhalb des Funktionsumfangs gehalten werden kann, dh wenn das Escape-Attribut erforderlich ist
Eine Erfassung ist erforderlich, da sie bis zur Ausführung des Abschlusses außerhalb des Funktionsumfangs aufbewahrt werden muss.
 */

var queue = [() -> Void]()

//Fügt der Array-Warteschlange den als Argument angegebenen Abschluss hinzu
//Mit anderen Worten, die Schließung dieses Arguments wird außer Reichweite gehalten
//Daher muss das Escape-Attribut im Argument der Enqueue-Funktion angegeben werden.
//Wenn nicht angegeben, tritt ein Kompilierungsfehler auf.
func enqueue(operation: @escaping () -> Void) {
    queue.append(operation)
}

enqueue {
    print("executed")
}
enqueue {
    print("executed")
}
queue.forEach { $0() }

//Schließer ohne das Escape-Attribut können nicht außerhalb des Funktionsumfangs gehalten werden
//Die Ausführung des Abschlusses muss innerhalb des Funktionsumfangs erfolgen
//Der an die Funktion executeTwice übergebene Abschluss verfügt nicht über das Escape-Attribut, sondern wird nur im Rahmen der Funktion ausgeführt, sodass kein Kompilierungsfehler auftritt.
func executeTwice(operation: () -> Void) {
//Laufen hier
    operation()
    operation()
}

executeTwice {
    print(("executed"))
}


//Verzögerungsbewertung durch Schließen der automatischen Schließung
//Attribut zur Realisierung der Verzögerungsbewertung durch Umschließen des Arguments
//Oder eine Funktion, die zwei Argumente vom Typ Bool akzeptiert und die logische Summe zurückgibt
//Ermitteln der logischen Summe || Eine Funktion, die sich genauso verhält wie der Operator

func or(_ lhs: Bool, _ rhs: Bool) -> Bool {
    if lhs {
        print("true")
        return true
    } else {
        print(rhs)
        return rhs
    }
}

or(true, false)

//Das erste Argument ist lhs()
//Kehren Sie rhs zum zweiten Argument zurück
//Innerhalb der Funktionen lhs und rhs führen wir print aus, damit wir sehen können, ob jede Funktion ausgeführt wurde.

func orA(_ lhs: Bool, _ rhs: Bool) -> Bool {
    if lhs {
        print("true")
        return true
    } else {
        print(rhs)
        return rhs
    }
}

func lhs() -> Bool {
    print("lhs()Wurde ausgeführt")
    return true
}

func rhs() -> Bool {
    print("rhs()Wurde ausgeführt")
    return false
}

orA(lhs(), rhs())

//Trailing Closure Notation zur Beschreibung des Argumentabschlusses in Klammern
/*
Trailing Closure ist eine Notation, die durch Schreiben des Closures in () ausgeführt werden kann, wenn das letzte Argument der Funktion Closure ist.
 */

func execute(parameter: Int, handler: (String) -> Void) {
    handler("parameter is \(parameter)")
}

//Wenn Sie den hinteren Verschluss nicht verwenden
execute(parameter: 1, handler: { string in
    print(string)
})

//Bei Verwendung eines nachlaufenden Verschlusses
execute(parameter: 2) { print($0) }

//Wenn es nur ein Argument gibt, kann der Funktionsaufruf () auch weggelassen werden.
func executeA(handler: (String) -> Void) {
    handler("executed")
}

//das Gleiche
executeA { valure in
    print(valure)
}
//das Gleiche
executeA { print($0) }

//Funktion als Verschluss
/*
Da eine Funktion eine Art Abschluss ist, kann sie als Abschluss behandelt werden. Um eine Funktion als Abschluss zu verwenden, beziehen Sie sich auf die Funktion nur mit dem Funktionsnamen.
Indem Sie eine Funktion als Abschluss behandeln, können Sie sie einer Funktion, Variablen oder Konstante zuweisen oder ein Argument einer anderen Funktion übergeben.
lass konstanten Namen=Funktionsname
Der Ausdruck kann sogar Argumente enthalten, die mit multipliziert werden
lass konstanten Namen=Funktionsname(Argumentname 1:Argumentname 2:)
 */

func doubleA(_ x: Int) -> Int {
    return x * 2
}

let function = doubleA
function(43)

//Indem Sie den Abschluss, der das Argument der Funktion ist, als Funktion definieren, können Sie doppelte Abschlüsse kombinieren oder kombinieren.
//Sie können dem Verschluss einen aussagekräftigen Namen geben
//Stellen Sie sich den Fall vor, in dem der Abschluss, der das Argument der Funktion ist, nicht als Funktion definiert ist.
// Array<Element>Verwenden der Typenkarte,{ $0 * 2 }Ich benutze den Verschluss zweimal
//Die Map-Methode gibt eine neue Sammlung zurück, die jeweils durch den durch den Abschluss angegebenen Prozess konvertiert wird.
let array1 = [1,2,3]
let doubleArray1 = array1.map { $0 * 2 }

let array2 = [4,5,6]
let doubleArray2 = array2.map { $0 * 2 }

doubleArray1
doubleArray2

//Indem die Funktion als Abschluss behandelt wird, kann das obige Beispiel wie folgt umgeschrieben werden:
func doubleB(_ x: Int) -> Int {
    return x * 2
}

let array1B = [1,2,3]
let doubleArray1A = array1B.map(doubleB)

let array2B = [4,5,6]
let doubleArray2A = array2B.map(doubleB)

//Duplizieren Sie, indem Sie Closure als Funktion definieren{ $0 * 2 }Stellen Sie den Prozess an einem Ort zusammen
//Es kann geschnitten werden, indem der Inhalt des Prozesses mit dem Namen doubleB angegeben wird, sodass es zu einem besser lesbaren Code wird.

//Initialisierung von Variablen und Konstanten mithilfe von Abschlussausdrücken
//In einigen Fällen kann der Abschlussausdruck verwendet werden, um das Verständnis der Initialisierung komplexer Werte zu erleichtern.
//Angenommen, Sie möchten einen Typ implementieren, der 3x3 Quadrate ausdrückt.
//Die Masse wird in einem zweidimensionalen Array modelliert und jeder Wert wird direkt im Literal definiert.
var board = [ [1,1,1], [1,1,1], [1,1,1] ]
board

//Anstatt dieses zweidimensionale Array direkt zu definieren, sollten Sie das Verfahren zum Generieren des zweidimensionalen Arrays beschreiben.
//Generieren Sie 3X3-Quadrate, indem Sie 3 Zeilen mit 3 1s generieren
// Array<Element>Geben Sie initializer init ein(reqwationg:count)Erzeugt einen Wert mit sich wiederholenden Argumenten, die durch die Anzahl der Zählungen hinzugefügt werden
var boardA = Array(repeating: Array(repeating: 1, count: 3), count: 3)
boardA // [[1, 1, 1], [1, 1, 1], [1, 1, 1]]
//Jetzt müssen Sie nicht jedes Element des Arrays angeben.
//Array zum Kombinieren von Variableninitialisierungsausdrücken zu einem<Element>Die verschachtelten Formeln für die Typgenerierung machten es schwierig, die Struktur herauszufinden.
//Ebenfalls. Es wird notwendig, den festen Wert von 3 an zwei Stellen zu verwalten.
//Der Abschlussausdruck kann verwendet werden, um eine Reihe von Implementierungen von Initialisierungsprozeduren zu einem einzigen Ausdruck zu kombinieren. Im folgenden Beispiel kann jeder verschachtelte Ausdruck verwendet werden, um eine Reihe von Initialisierungsprozeduren zu implementieren. Kann eine Formel sein,
//Im folgenden Beispiel werden die verschachtelten Ausdrücke der Konstantenzeile bzw. -platine zugewiesen, um das Verständnis der Generierung zu erleichtern.
//Da die Anzahl der Quadrate auf einer Seite nach der Deklaration ebenfalls als Konstante verwendet wird, kann die Verwaltung vereinheitlicht werden.
var boardB: [[Int]] = {
    let sideLength = 3
    let row = Array(repeating: 1, count: sideLength)
    let board = Array(repeating: row, count: sideLength)
    return board
}()

boardB  // [[1, 1, 1], [1, 1, 1], [1, 1, 1]]

//Selbst wenn der Initialisierungsprozess von Variablen und Konstanten kompliziert ist, wird auf diese Weise leicht verständlich, wie die Anfangswerte generiert werden.

Recommended Posts

[Swift] Ein Hinweis zu Funktion und Schließung
Ein Memo über den Fluss von Rails und Vue
Hinweise zu Java GC
Hinweise zum Umfang
Eine grobe Anmerkung zu Ruby-Arrays und Hash-Objekten
Private Notiz über AtomicReference
Informationen zum Hinzufügen einer ähnlichen Funktion
Ein Hinweis zum Seed-Feature von Ruby on Rails
Hinweise zu Spaltenfamilien in RocksDB
Rufen Sie C-Sprachfunktionen von Swift aus auf
Ein Java-Ingenieur verglich Swift, Kotlin und Java.
Beachten Sie, dass Junit 4 zu Android Studio hinzugefügt wurde
[Swift] [Anfänger] Ich habe viel nach #selector gesucht
Anmerkungen um th: Feld th: jedes th: Objekt von Thymeleaf
Behandeln Sie Swift-Funktionen und -Verschlüsse als Zeiger für C-Sprachfunktionen
Ein Memorandum über Tabellendatentypen und -befehle (Rails)
Fragen und Antworten zu JDK
Über Bean und DI
Über Klassen und Instanzen
Über bekommt und bekommt.chomp
Über Weiterleiten und Weiterleiten
[Swift] Über den Aufzählungstyp
Über Kapselung und Vererbung
Informationen zu Serializable und serialVersionUID
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich habe JAX-RS ausprobiert und mir das Verfahren notiert
Fügen Sie dem Swift-Button (und auch dem Kreis) einen Schatten hinzu.