Funktion Currying in Swift

Apr 03 2023
Einführung: Function Currying ist eine Technik der funktionalen Programmierung, die eine Funktion mit mehreren Argumenten in eine Reihe von Funktionen mit jeweils einem einzigen Argument umwandelt. Ein amerikanischer Mathematiker namens Haskell Curry hat diese Technik entwickelt, deshalb wird sie Currying genannt.

Einführung:

Function Currying ist eine Technik der funktionalen Programmierung, die eine Funktion mit mehreren Argumenten in eine Reihe von Funktionen umwandelt, die jeweils ein einzelnes Argument verwenden.

Ein amerikanischer Mathematiker namens Haskell Curry hat diese Technik entwickelt, deshalb wird sie Currying genannt.

Daher kann eine Funktion wie f(a, b, c, …) in f(a)(b)(c)… umgewandelt werden.

Dieser Prozess gibt für jedes Argument eine neue Funktion zurück, bis alle Argumente bereitgestellt wurden und die ursprüngliche Funktion ausgewertet werden kann. Die resultierenden Funktionen, auch Curry-Funktionen genannt , können kombiniert und zusammengesetzt werden, um komplexere Funktionen zu erstellen.

Currying ermöglicht eine partielle Funktionsanwendung , bei der einige Argumente an eine Funktion übergeben werden und eine neue Funktion zurückgegeben wird, die die verbleibenden Argumente erwartet.

Beispiel 1: Einfache Add-Funktion

Betrachten Sie beispielsweise die folgende Funktion, die zwei Argumente akzeptiert:

func add(_ x: Int, _ y: Int) -> Int {
    return x + y
}

add(2, 3) // output: 5

  1. Diese Funktion erwartet nur zwei Argumente.
  2. Wir können die Funktion add nicht mit mehr als zwei Parametern aufrufen.

func curriedAdd(_ x: Int) -> (Int) -> Int {
    return { y in
        return x + y
    }
}

// Now we can call this curried function like this:

print(CurriedAdd(2)(3)) // 5

// we can also call it like this

let addTwo = curriedAdd(2) // (Int) -> Int
print(addTwo(3)) // 5

// Add three numbers using curried function.

curriedAdd(CurriedAdd(5)(2))(3) // 10

Beispiel 2: Erstellen von URLs

In diesem Beispiel erstellen wir eine Liste von URL-Strings mit der Funktion „ createURL “, die baseURL und path als Argumente verwendet und beim Aufruf mit diesen Parametern einen neuen URL-String zurückgibt.

func createURL(_ baseURL: String, _ path: String) -> String {
    let scheme = "https";
    return "\(scheme)://\(baseURL)/\(path)"
}

// create URLs for our main site
let homeURL = createURL("mysite.com", "");
let loginURL = createURL("mysite.com", "login");
let productsURL = createURL("mysite.com", "products");
let contactURL = createURL("mysite.com", "contact-us");

// create URLs for our careers site
let careersHomeURL = createURL("mysite-careers.com", "");
let careersLoginURL = createURL("mysite-careers.com", "login");

func curriedCreateURL(_ baseURL: String) -> (String) -> String {
    return { path in
        let scheme = "https";
        return "\(scheme)://\(baseURL)/\(path)"
    }
}

// we create a new functions with the baseURL value returns another function.
let createSiteURL = curriedCreateURL("mysite.com");
let createCareersURL = curriedCreateURL("mysite-careers.com");

// create URLs for our main site
let homeURLCurried = createSiteURL("");
let loginURLCurried = createSiteURL("login");
let productsURLCurried = createSiteURL("products");
let contactURLCurried = createSiteURL("contact-us");

// create URLs for our career site
let careersHomeURLCurried = createCareersURL("");
let careersLoginURLCurried = createCareersURL("login");

Als Nächstes haben wir Teilfunktionsanwendungen wie createSiteURL und createCareersURL erstellt , die wir zum Erstellen neuer URLs verwenden. Durch die Verwendung von Function Currying haben wir die Wiederholung der Basis-URL in Funktionsaufrufen eliminiert.

Beispiel 3: Teure Prozesse isolieren

Nehmen wir an, wir haben eine große Stichprobe von Daten eines Paketunternehmens, die eine riesige Liste von Paketen aus verschiedenen Ländern zusammen mit ihren Lieferadressen und dem Erstellungsdatum enthält.

var globalParcels: Parcels = [
    Parcel(createdDate: 1,
           location: "US",
           shippingAddress: ....
           ),
    Parcel(createdDate: 2,
           location: "AUS",
          shippingAddress: ....
           ),
    Parcel(createdDate: 3,
           location: "US",
           shippingAddress: ....
           )
    // .........
]

func sortParcelsByCountry(_ parcels: Parcels, _ country: String, _ sortOrder: String) -> Parcels {
    let countryParcels = parcels.filter({ $0.location == country })
    if sortOrder == "ascending" {
        return countryParcels.sorted { $0.created > $1.created }
    } else {
        return countryParcels.sorted { $0.created < $1.created }
    }
}

let ausParcelsAsc = sortParcelsByCountry(globalParcels, "AUS", "ascending")
let ausParcelsDsc = sortParcelsByCountry(globalParcels, "AUS", "descending")

func sortParcels(_ parcels: Parcels) -> (String) -> (String) -> Parcels {
    return { country in
        let countryParcels = parcels.filter({ $0.location == country })
        return { sortOrder in
            if sortOrder == "ascending" {
                return countryParcels.sorted { $0.created > $1.created }
            } else {
                return countryParcels.sorted { $0.created < $1.created }
            }
        }
    }
}

let sortAusParcelsBy = sortParcels(globalParcels)("AUS");

let ausParcelsAsc1 = sortAusParcelsBy("ascending");
let ausParcelsDsc1 = sortAusParcelsBy("descending");

Abschluss:

Function Currying ist bei der funktionalen Programmierung nützlich, da es einen flexibleren und wiederverwendbaren Code ermöglicht. Indem wir eine Funktion in eine Folge kleinerer Funktionen zerlegen, können wir sie auf verschiedene Weise zusammensetzen, um neue Funktionen mit unterschiedlichem Verhalten zu erstellen.

Currying macht unseren Code:

  1. Reiniger.
  2. Weniger sich wiederholende Parameterübergaben und weniger ausführlicher Code.
  3. Zusammensetzbarer.
  4. Mehr wiederverwendbar.