Questa funzionalità del linguaggio JavaScript può aiutarti a riordinare il tuo codice e ti darà un nuovo apprezzamento su come funzionano le funzioni.

Le funzioni curry possono aiutarti a rendere il tuo codice JavaScript più leggibile ed espressivo. La tecnica del currying è ideale quando si desidera scomporre la logica complessa in porzioni di codice più piccole, autonome e più gestibili.

Scopri tutto sulle funzioni curry in JavaScript, come utilizzare la tecnica del currying delle funzioni per creare funzioni parzialmente applicate, nonché casi d'uso reali sia per le funzioni eseguite che per quelle parzialmente applicate funzioni.

Cos'è il curry?

Il curry prende il nome dal matematico Haskell B. Curry, e il concetto deriva dal Lambda calcolo. Il currying prende una funzione che riceve più di un parametro e la suddivide in una serie di funzioni unarie (a un parametro). In altre parole, una funzione curry accetta solo un parametro alla volta.

Un esempio base di curry

Di seguito è riportato un esempio di una funzione curry:

instagram viewer
functionbuildSandwich(ingredient1) {
return(ingredient2) => {
return(ingredient3) => {
return`${ingredient1},${ingredient2},${ingredient3}`
}
}
}

IL buildSandwich() La funzione restituisce un'altra funzione: una funzione anonima che riceve il file ingrediente2 discussione. Quindi, questa funzione anonima restituisce un'altra funzione anonima che riceve ingrediente3. Infine, quest'ultima funzione restituisce il modello letterale, un modo di stringhe di formattazione in JavaScript.

Ciò che hai creato è una funzione annidata in cui ciascuna funzione chiama quella sottostante fino a raggiungere la fine. Ora, quando chiami buildSandwich() e passagli un singolo parametro, restituirà la parte della funzione di cui devi ancora fornire gli argomenti:

console.log(buildSandwich("Bacon"))

Puoi vedere dall'output che buildSandwich restituisce una funzione:

Per completare la chiamata alla funzione, dovresti fornire tutti e tre gli argomenti:

buildSandwich("Bacon")("Lettuce")("Tomato")

Questo codice passa "Pancetta" alla prima funzione, "Lattuga" alla seconda e "Pomodoro" all'ultima funzione. In altre parole, il buildSandwich() La funzione è in realtà suddivisa in tre funzioni, ciascuna delle quali riceve un solo parametro.

Sebbene sia perfettamente valido eseguire il curry utilizzando le funzioni tradizionali, tutti gli annidamenti possono diventare piuttosto brutti quanto più si approfondisce. Per aggirare questo problema, puoi utilizzare le funzioni freccia e sfruttare la loro sintassi più pulita:

const buildMeal = ingred1 =>ingred2 =>ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;

Questa versione rifattorizzata è più concisa, un vantaggio dell'utilizzo funzioni freccia rispetto a funzioni regolari. Puoi chiamare la funzione nello stesso modo in cui hai fatto con la precedente:

buildMeal("Bacon")("Lettuce")("Tomato")

Funzioni del curry parzialmente applicate

Le funzioni applicate parzialmente sono un uso comune del currying. Questa tecnica prevede di fornire solo gli argomenti necessari alla volta (invece di fornire tutti gli argomenti). Ogni volta che invochi una funzione passando tutti i parametri richiesti, dici di aver "applicato" quella funzione.

Diamo un'occhiata ad un esempio:

const multiply = (x, y) => x * y;

Di seguito è riportata la versione al curry di moltiplicazione:

const curriedMultiply = x =>y => x * y;

IL curryMultiply() la funzione riceve il X argomento per la prima funzione e per la seconda funzione, moltiplica entrambi i valori.

Per creare la prima funzione parzialmente applicata, chiamare curryMultiple() con il primo parametro e assegnare la funzione restituita a una variabile:

const timesTen = curriedMultiply(10)

A questo punto il codice ha “applicato parzialmente” l'art curryMultiply() funzione. Quindi quando vuoi chiama volteDieci(), devi solo passargli un numero e il numero verrà automaticamente moltiplicato per 10 (che è memorizzato all'interno della funzione applicata):

console.log(timesTen(8)) // 80

Ciò ti consente di basarti su un'unica funzione complessa creando da essa più funzioni personalizzate, ciascuna con la propria funzionalità bloccata.

Dai un'occhiata a un esempio più vicino a un caso d'uso reale di sviluppo web. Di seguito hai un aggiornamentoElemText() funzione che accetta un elemento id alla prima chiamata, il contenuto della seconda chiamata, quindi aggiorna l'elemento in base a id e il contenuto che hai fornito:

const updateElemText = id = content
=> document.querySelector(`#${id}`).textContent = content

// Lock the element's id into the function:
const updateHeaderText = updateElemText('header')

// Update the header text
updateHeaderText("Hello World!")

Composizione di funzioni con funzioni al curry

Un altro uso comune del currying è la composizione della funzione. Ciò ti consente di chiamare piccole funzioni, in un ordine specifico, e combinarle in un'unica funzione più complessa.

Ad esempio, in un ipotetico sito di e-commerce, ecco tre funzioni che potresti voler eseguire una dopo l'altra (in ordine preciso):

const addCustomer = fn =>(...args) => {
console.log("Saving customer info")
return fn(...args)
}

const processOrder = fn =>(...args) => {
console.log(`processing order #${args[0]}`)
return fn(...args);
}

let completeOrder = (...args) => {
console.log(`Order #${[...args].toString()} completed.`);
}

Si noti che questo codice utilizza il file permettere parola chiave per definire il file ordine completo() funzione. Ciò consente di riassegnare un valore alla variabile e ne fa parte come funziona l'ambito in JavaScript.

Successivamente, devi chiamare le funzioni in ordine inverso (dall'interno verso l'esterno) perché vorresti aggiungere prima i clienti:

completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")

Questo ti darà il seguente output:

Se dovessi scrivere le funzioni di cui sopra nel modo normale, il codice sarà simile a questo:

functionaddCustomer(...args) {
returnfunctionprocessOrder(...args) {
returnfunctioncompleteOrder(...args) {
// end
}
}
}

Quando chiami il aggiungiCliente() funzione e passi gli argomenti, stai iniziando dall'interno e procedendo verso l'inizio della funzione.

Convertire una funzione normale in una funzione al curry con una funzione al curry

Se prevedi di utilizzare molto le funzioni curry, puoi semplificare il processo con una funzione di supporto.

Questa funzione convertirà qualsiasi funzione normale in una funzione curry. Utilizza la ricorsione per gestire un numero qualsiasi di argomenti.

const curry = (fn) => {
return curried = (...args) => {
if (fn.length !== args.length) {
return curried.bind(null, ...args)
}

return fn(...args);
}
}

Questa funzione accetterà qualsiasi funzione scritta standard che riceve più di un parametro, restituendo una versione modificata di quella funzione. Per vederlo in azione, usa questa funzione di esempio che prende tre parametri e li somma insieme:

const total = (x, y, z) => x + y + z

Per convertire questa funzione, chiamare il file curry() funzione e passaggio totale come argomento:

const curriedTotal = curry(total)

Ora per chiamare la funzione, devi solo passare tutti gli argomenti:

console.log(curriedTotal(10)(20)(30)) // 60

Ulteriori informazioni sulle funzioni in JavaScript

Le funzioni di JavaScript sono estremamente flessibili e le funzioni di currying ne sono solo una piccola parte. Esistono molti altri tipi di funzioni come funzioni freccia, funzioni di costruzione e funzioni anonime. Familiarizzare con queste funzioni e i loro componenti è fondamentale per padroneggiare JavaScript.