Funkcja Curry w Swift
Wstęp:
Funkcja curry to technika programowania funkcjonalnego, która przekształca funkcję przyjmującą wiele argumentów w serię funkcji, z których każda przyjmuje jeden argument.
Technikę tę opracował amerykański matematyk Haskell Curry, dlatego nazywa się ją curry.
Dlatego funkcję taką jak f(a, b, c,…) można przekształcić w f(a)(b)(c)….
Ten proces zwraca nową funkcję dla każdego argumentu, dopóki nie zostaną podane wszystkie argumenty i można będzie ocenić pierwotną funkcję. Powstałe funkcje, zwane również funkcjami curry , można łączyć i komponować, aby uzyskać bardziej złożoną funkcjonalność.
Currying umożliwia częściowe zastosowanie funkcji , w którym niektóre argumenty są przekazywane do funkcji, a nowa funkcja jest zwracana, oczekując pozostałych argumentów.
Przykład 1: Prosta funkcja dodawania
Rozważmy na przykład następującą funkcję, która przyjmuje dwa argumenty:
func add(_ x: Int, _ y: Int) -> Int {
return x + y
}
add(2, 3) // output: 5
- Ta funkcja oczekuje tylko dwóch argumentów.
- Nie możemy wywołać funkcji add z więcej niż dwoma parametrami.
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
Przykład 2: Konstruowanie adresów URL
W tym przykładzie utworzymy listę ciągów adresów URL za pomocą funkcji „ createURL ”, która przyjmuje baseURL i ścieżkę jako argumenty i zwraca nowy ciąg adresów URL, gdy jest wywoływana z tymi parametrami.
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");
Następnie stworzyliśmy aplikacje funkcji częściowych , takie jak createSiteURL i createCareersURL , których używamy do konstruowania nowych adresów URL. Używając curry funkcji, wyeliminowaliśmy powtarzanie podstawowego adresu URL w wywołaniach funkcji.
Przykład 3: Wyizoluj kosztowny proces
Załóżmy, że mamy dużą próbkę danych z firmy kurierskiej, zawierającą ogromną listę paczek z różnych krajów wraz z ich adresami wysyłkowymi i datą ich utworzenia.
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");
Wniosek:
Curry funkcji jest przydatne w programowaniu funkcjonalnym, ponieważ pozwala na bardziej elastyczny i wielokrotnego użytku kod. Dzieląc funkcję na sekwencję mniejszych funkcji, możemy komponować je na różne sposoby, aby tworzyć nowe funkcje o różnych zachowaniach.
Curry sprawi, że nasz kod:
- Odkurzacz.
- Mniej powtarzających się parametrów i mniej rozwlekłego kodu.
- Bardziej komponowalny.
- Więcej wielokrotnego użytku.

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































