Maison >interface Web >js tutoriel >Implémentation de Curry dans la programmation fonctionnelle JavaScript

Implémentation de Curry dans la programmation fonctionnelle JavaScript

黄舟
黄舟original
2017-03-02 14:53:091426parcourir

Récemment j'apprends la programmation fonctionnelle JavaScript, et je suis très intéressé par le fameux curry La fonction curry peut accepter une fonction, appelons-la la fonction originale pour le moment, et elle renvoie un. fonction, curry.Fonction, la fonction curry renvoyée est très puissante. Pendant le processus d'exécution, elle renvoie en continu une fonction qui stocke les paramètres transmis jusqu'à ce que les conditions d'exécution de la fonction d'origine soient déclenchées. C'est plus général, donnons donc un exemple pour illustrer :

Fonction originale :

var add = (x, y) => x + y

Fonction Curry :

 var curryAdd = curry(add)

Cet ajout nécessite deux paramètres, mais notre exécution curryAdd peut transmettre moins de paramètres. Lorsque les paramètres transmis sont inférieurs aux paramètres requis par add, la fonction add ne sera pas exécutée. écrira ce paramètre et en renverra une autre. les paramètres entrants. Nous aurons une variable pour enregistrer les paramètres entrants. Si le nombre total de paramètres entrants est égal au nombre total de paramètres requis par l'ajout, nous activerons l'exécution du paramètre d'origine et il retournera ce que nous voulons. résultat.

// 此时只传入了一个参数 根据判断返回的是一个函数
    var add2 = curryAdd(2)
    // add2 = function(...) {}
// 此时累计传入了两个参数 等于了add需要参数的总和 所以返回的是一个结果
    // 相当于执行了add(2)(3)
    var result = add2(3)
    // result = 5

C'est plutôt bien, non ? Eh bien, notre objectif est d'écrire cette fonction magique du curry, et nous devons l'écrire sur une seule ligne, analysons comment l'écrire. d'abord, puis optimisez étape par étape.

D'après la description ci-dessus, jetons un coup d'œil à ce dont la fonction curry a besoin. Tout d'abord, nous avons besoin d'une variable pour stocker le nombre de paramètres de la fonction d'origine. Nous savons que cette fonction a un attribut appelé longueur, et c'est tout. Nous utilisons la limite pour le sauvegarder

    var curry = function(fn) {
         var limit = fn.length
         ...
    }

La fonction curry doit renvoyer une fonction, et cette fonction doit être exécutée. La question est, nous devons déterminer si l'exécution de cette fonction s'active. l'exécution de la fonction d'origine. Le problème se pose au-dessus des paramètres transmis. Fonction de retour ou résultat ? C'est en effet un problème. Écrivons d'abord le résultat renvoyé lorsque les paramètres transmis sont égaux aux paramètres requis par la fonction d'origine, nous exécutons la fonction d'origine fn

    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             }
         }
    }

, sinon nous renverrons un. stockage Il y a deux points ici pour la fonction des paramètres. L'un est que nous devons enregistrer l'historique des paramètres transmis. L'autre est ce que la fonction renvoyée doit faire

    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {

                 }
             }
         }
    }

Voir. Nous avons seulement besoin de renvoyer la fonction. L'accumulation des paramètres exécutés atteint l'objectif d'enregistrer les paramètres transmis, nous avons donc pensé à concat en args.concat(args2), et ainsi de suite. Ce que la fonction que nous retournons doit faire, c'est répéter. les choses ci-dessus, c'est-à-dire que les paramètres sont La fonction de args doit faire quelque chose, elle a donc besoin d'un nom, sinon nous ne pouvons pas l'exécuter, nous l'appelons JudgeCurry

Donc, comme nous l'avons dit, soit return une fonction ou exécuter la fonction d'origine.

    var curry = function(fn) {
         var limit = fn.length
         return function judgeCurry (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {
                     return judgeCurry.apply(null, args.concat(args2))                                     
                 }
             }
         }
    }

Nous avons enfin fini d'écrire cette fonction magique de curry. Elle est vraiment puissante lorsqu'elle est combinée avec la composition, c'est vraiment cool.

Notre objectif est d'écrire la fonction ci-dessus sur une seule ligne, une seule ligne ? Comment écrire ? Au fait, j'utilise ES6, donc j'ai passé beaucoup de temps

var currySingle = fn => judgeCurry = (...args) => args.length >= fn.length ? fn.apply(null, args) : 
(...args2) => judgeCurry.apply(null, args.concat(args2))

D'accord, voyons quel est le problème. Au fait, pour ne pas utiliser le paramètre limit, il faut attribuer. une valeur lors de son utilisation. L'affectation ne peut pas être effectuée sur une seule ligne, cela deviendra comme ceci

    var currySingle = fn => {
        var limit = fn.length
        var judgeCurry = null
        return judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2))
    }

Lorsque vous aurez besoin de juger les paramètres, fn.length est constamment évalué, mais la valeur de fn. .length est certain. Nous ne voulons pas l'évaluer à chaque fois, mais que dois-je faire si je ne veux pas utiliser de limite ? Vous avez dû penser à exécuter la fonction immédiatement ! !

var currySingle = fn => ((limit) => judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : 
(...args2) => judgeCurry.apply(null, args.concat(args2)))(fn.length)

Je dois soupirer devant la magie du javascript Enfin, nous avons écrit ce curry magique en une seule ligne.

Ce qui précède est le contenu de l'implémentation de curry dans la programmation fonctionnelle JavaScript. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn