Função Currying em Swift

Apr 03 2023
Introdução: Function currying é uma técnica em programação funcional que transforma uma função que recebe vários argumentos em uma série de funções, cada uma recebendo um único argumento. Um matemático americano chamado Haskell Curry desenvolveu essa técnica, por isso é chamada de currying.

Introdução:

Function currying é uma técnica em programação funcional que transforma uma função que recebe vários argumentos em uma série de funções, cada uma recebendo um único argumento.

Um matemático americano chamado Haskell Curry desenvolveu essa técnica, por isso é chamada de currying.

Portanto, uma função como f(a, b, c, …) pode ser convertida em f(a)(b)(c)….

Esse processo retorna uma nova função para cada argumento até que todos os argumentos tenham sido fornecidos e a função original possa ser avaliada. As funções resultantes, também chamadas de funções curried , podem ser combinadas e compostas para criar funcionalidades mais complexas.

Currying habilita o aplicativo de função parcial , onde alguns argumentos são passados ​​para uma função e uma nova função é retornada, esperando os argumentos restantes.

Exemplo 1: função de adição simples

Por exemplo, considere a seguinte função que recebe dois argumentos:

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

add(2, 3) // output: 5

  1. Esta função espera apenas dois argumentos.
  2. Não podemos chamar a função add com mais de dois parâmetros.

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

Exemplo 2: construção de URLs

Neste exemplo, criaremos uma lista de strings de URL usando a função ' createURL ', que usa baseURL e path como argumentos e retorna uma nova string de URL quando chamada com esses parâmetros.

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");

Em seguida, criamos aplicativos de função parcial , como createSiteURL e createCareersURL , que usamos para construir novos URLs. Ao usar currying de função, eliminamos a repetição da URL base em chamadas de função.

Exemplo 3: Isolar Processo Caro

Digamos que temos uma grande amostra de dados de uma empresa de encomendas, contendo uma enorme lista de encomendas de diferentes países junto com seus endereços de entrega e a data em que foram criadas.

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");

Conclusão:

Currying de função é útil na programação funcional porque permite um código mais flexível e reutilizável. Ao quebrar uma função em uma sequência de funções menores, podemos compô-las de várias maneiras para criar novas funções com diferentes comportamentos.

Currying fará nosso código:

  1. Limpador.
  2. Passagem de parâmetros menos repetitiva e código menos detalhado.
  3. Mais componíveis.
  4. Mais reutilizável.