Domanda

Un mio amico e io stavamo discutendo riguardo al currying e all'applicazione parziale di funzioni in Javascript e siamo giunti a conclusioni molto diverse sulla fattibilità di entrambe.Mi è venuta in mente questa implementazione di Function.prototype.curry, che è stata la base della nostra discussione:

Function.prototype.curry = function() {
    if (!arguments.length) return this;

    var args = Array.prototype.slice.apply(arguments);
    var mmm_curry = this, args;

    return function() {
        var inner_args = Array.prototype.slice.apply(arguments);
        return mmm_curry.apply(this, args.concat(inner_args));
    }

}

Che viene utilizzato come segue:

var vindaloo = function(a, b) {
    return (a + b);
}

var karahi = vindaloo.curry(1);
var masala = karahi(2);
var gulai = karahi(3);

print(masala);
print(other);

Il cui output è il seguente in Spidermonkey:

$ js curry.js
3
4

La sua opinione era che dal momento che Javascript function la primitiva non supporta nativamente "applicazione parziale di funzioni", è completamente sbagliato fare riferimento alla funzione associata alla variabile karahi come parzialmente applicato.La sua argomentazione era che quando il vindaloo la funzione viene sottoposta a currying, la funzione stessa viene applicata completamente e viene restituita una chiusura, non una "funzione applicata parzialmente".

Ora, la mia opinione è che, sebbene Javascript in sé non fornisca il supporto per l'applicazione parziale nella sua function primitive (a differenza, ad esempio, di ML o Haskell), ciò non significa che non è possibile creare una funzione di ordine superiore del linguaggio che sia in grado di incapsulare il concetto di una funzione parzialmente applicata.Inoltre, pur essendo "applicata", l'ambito della funzione è ancora vincolato alla chiusura restituita dalla stessa facendola rimanere "parzialmente applicata".

Che è corretto?

È stato utile?

Soluzione

Tecnicamente stai creando una funzione nuova di zecca che richiama la funzione originale.Quindi, se la mia comprensione delle funzioni parzialmente applicate è corretta, questa non è una funzione parzialmente applicata.Una funzione applicata parzialmente sarebbe più vicina a questa (nota che questa non è una soluzione generale):

vindaloo.curry = function(a) {
    return function(b) {
        return a + b;
    };
};

IIUC, questa non sarebbe ancora una funzione parzialmente applicata.Ma è più vicino.Una vera funzione parzialmente applicata sarebbe effettivamente simile a questa se potessi esaminare il codice:

function karahi(b) {
    return 1 + b;
};

Quindi, tecnicamente, il tuo metodo originale È semplicemente restituendo una funzione legata all'interno di una chiusura.L'unico modo che mi viene in mente per applicare veramente parzialmente una funzione in JavaScript sarebbe analizzare la funzione, applicare le modifiche e quindi eseguirla tramite un eval().

Tuttavia, la tua soluzione è una buona applicazione pratica del concetto a JavaScript, quindi in pratica raggiunge l'obiettivo, anche se non è tecnicamente esatto.

Altri suggerimenti

Penso che sia perfettamente bene parlare dell'applicazione parziale della funzione in JavaScript - se funziona come un'applicazione parziale, allora deve essere uno.In quale altro modo lo chiameresti?

Come il tuo curry La funzione raggiunge il suo obiettivo è solo un dettaglio di implementazione.Allo stesso modo potremmo avere un'applicazione parziale nelle specifiche ECMascript, ma quando IE la implementerei proprio come hai fatto tu, non avresti modo di scoprirlo.

I dettagli tecnici non mi interessano: se la semantica rimane la stessa e, a tutti gli effetti, la funzione si comporta come se fosse davvero una funzione parzialmente applicata, a chi importa?

Ero un accademico sulle cose, ma preoccuparmi di tali particolari alla fine non porta a termine il vero lavoro.

Personalmente, utilizzo MochiKit;ha una bella funzione partial() che aiuta nella creazione di tale.Lo adoro.

Dovresti controllare Funzioni JavaScript al curry.Non ho ancora completamente capito la sua funzione al curry, ma potrebbe avere la tua risposta.

Modificare:Concordo comunque con la tua valutazione.

La sua opinione era che, poiché la funzione primitiva Javascript non supporta nativamente "l'applicazione di funzioni parziali"

Puoi fare il curry in ES6 in modo abbastanza elegante:

> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top