Pergunta

Um amigo meu e eu estávamos tendo uma discussão sobre currying e aplicação de função parcial em Javascript, e chegamos a conclusões muito diferentes sobre se quer eram realizáveis. Eu vim com essa implementação de Function.prototype.curry, que foi a base da nossa discussão:

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

}

Que é usado como 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);

A saída do qual é como se segue em Aranha:

$ js curry.js
3
4

Sua opinião era de que uma vez que o Javascript function primitiva não suporta nativamente "aplicação de função parcial", é completamente errado para se referir à função ligada ao karahi variável como parcialmente aplicada. Seu argumento era que, quando a função vindaloo é curry, a própria função é completamente aplicada e um encerramento é devolvido, não uma "função parcialmente aplicada".

Agora, a minha opinião é que, enquanto em si Javascript não fornece suporte para aplicação parcial em suas primitivos function (digamos, ao contrário, ML ou Haskell), isso não significa que você não pode criar uma função de ordem superior da língua que é capaz de encapsular conceito de uma função parcialmente aplicada. Além disso, apesar de ser "aplicada", o escopo da função ainda está ligado ao fecho por devolvido lo fazendo com que permanecem "parcialmente aplicado".

O que é correto?

Foi útil?

Solução

Tecnicamente, você está criando uma função nova marca que chama a função original. Então, se o meu entendimento das funções parcialmente aplicadas estiver correta, isso não é uma função parcialmente aplicada. Uma função parcialmente aplicada estaria mais próximo a esta (nota que esta não é uma solução geral):

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

IIUC, isso ainda não seria uma função parcialmente aplicada. Mas é mais perto. Uma função parcialmente aplicada verdade seria realmente parecido com isso se você pode examinar o código:

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

Então, tecnicamente, o seu método original é apenas retornando uma função ligada dentro de um fechamento. A única maneira que eu posso pensar para realmente aplicar parcialmente uma função em JavaScript seria para analisar a função, aplicar as alterações, e depois executá-lo através de um eval ().

No entanto, a sua solução é uma boa aplicação prática do conceito de JavaScript, por isso, em termos práticos cumpre o objetivo, mesmo que isso não é tecnicamente exato.

Outras dicas

Eu acho que é perfeitamente OK para falar sobre aplicação de função parcial em JavaScript - se ele funciona como aplicação parcial, então deve Seja um. Quanto mais você nomeá-lo?

Como o caril função realiza o seu objetivo é apenas uma implementação detalhe. De forma semelhante poderíamos ter aplicação parcial na especificação ECMAScript, mas quando IE, então, implementá-lo exatamente como você fez, você teria nenhuma maneira de descobrir.

Os detalhes técnicos não importam para mim - se a semântica permanecem os mesmos e, para todos os efeitos, a função age como se fosse realmente uma função parcialmente aplicada, quem se importa?

Eu costumava ser tão acadêmico sobre as coisas, mas se preocupar com esses elementos não trabalhar de verdade no final.

Pessoalmente, eu uso MochiKit ; ele tem uma função agradável parcial () que ajuda na criação de tais. I adora.

Você deve verificar se Curried JavaScript . Eu não completamente envolvido minha cabeça em torno de sua função de curry, mas pode ter a sua resposta.

Edit:. Concordo com sua avaliação, no entanto

Sua opinião foi que desde que a função Javascript primitiva não suporta nativamente "aplicação de função parcial"

Você pode fazer currying em ES6 muito elegantemente:

> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top