Maison  >  Article  >  interface Web  >  Implémentation de Compose dans la programmation fonctionnelle JavaScript

Implémentation de Compose dans la programmation fonctionnelle JavaScript

黄舟
黄舟original
2017-03-02 14:49:291724parcourir

L'article précédent a présenté l'implémentation de javascript (currying) dans curry la programmation fonctionnelle. Bien sûr, ce curry est un curry de paramètres limités, je l'essaierai quand j'en aurai. opportunité. Le genre de curry qui ajoute des paramètres infinis. Cette fois, nous parlons principalement de javascript une autre fonction très importante dans la programmation fonctionnelle compose Le rôle de la fonction compose est de combiner des fonctions et de connecter des fonctions en série. plusieurs fonctions. La sortie d'une fonction est le paramètre d'entrée d'une autre fonction. Une fois que la première fonction commence à s'exécuter, l'exécution sera déduite comme des dominos.

Introduction

Par exemple, si vous avez une telle exigence, vous devez saisir un nom. Ce nom est composé de firstName, lastName, puis afficher le nom en tout. lettres majuscules. Par exemple, si vous entrez jack, smith nous l'imprimerons, ‘HELLO,JACK SMITH’.

Nous envisageons d'utiliser une combinaison de fonctions pour résoudre ce problème. Nous avons besoin de deux fonctions greeting, toUpper

var greeting = (firstName, lastName) => 'hello, ' + firstName + ' ' + lastName
var toUpper = str => str.toUpperCase()
var fn = compose(toUpper, greeting)
console.log(fn('jack', 'smith'))
// ‘HELLO,JACK SMITH’

C'est l'utilisation générale de composer. attention à Il y a les points suivants : les paramètres de

  • compose sont des fonctions, et ce qui est renvoyé est aussi une fonction

  • car en plus des paramètres acceptés de la première fonction, les paramètres acceptés par les autres fonctions sont les valeurs de retour de la fonction précédente, donc les paramètres de la fonction initiale sont 多元, tandis que les valeurs acceptées des autres fonctions sont 一元

  • compsoeLa fonction peut accepter n'importe quel paramètre. Tous les paramètres sont des fonctions, et le sens d'exécution est 自右向左 La fonction initiale doit être placée dans le paramètre 最右面

. Connaître ces trois Après avoir cliqué, il est facile d'analyser le processus d'exécution de l'exemple précédent Lors de l'exécution de

, la fonction initiale est fn('jack', 'smith'), le résultat de l'exécution. est passé à greeting en tant que paramètre, puis toUpper est exécuté pour obtenir le résultat final. Par conséquent, permettez-moi de mentionner brièvement les avantages de composer. Si vous souhaitez ajouter une autre fonction de traitement, vous n'en avez pas besoin. pour modifier toUpper. Il suffit d'exécuter un fn. Par exemple, si nous voulons ajouter un autre compose, il suffit de le faire. on voit qu’il est très pratique à maintenir et à développer. trim

Mise en œuvre
var trim = str => str.trim()
var newFn = compose(trim, fn)
console.log(newFn('jack', 'smith'))

J'ai fini d'analyser l'exemple, conformément au principe fondamental, je souhaite toujours explorer comment

est implémenté. Tout d'abord, je vais expliquer comment je l'ai implémenté, et puis explorons à nouveau comment les deux principales bibliothèques de

programmation fonctionnelle,

et

, sont implémentées. Le processus d'implémentation de compose est très fonctionnel. javascriptlodash.jsMon implémentationramda.jsramda.jsMon idée est que puisque la fonction s'exécute comme un domino, j'ai d'abord pensé à la récursion. Implémentons cela étape par étape

Tout d'abord,

Renvoyer une fonction. . Afin d'enregistrer l'exécution de la récursion, enregistrez la longueur des paramètres

et ajoutez un nom

à la fonction renvoyée. composecomposelen Ce qu'il faut faire dans le corps de la fonction est d'exécuter en continu les fonctions dans f1 et d'utiliser le résultat de l'exécution de la fonction précédente comme paramètre d'entrée de la fonction d'exécution suivante.

est nécessaire pour enregistrer l'exécution de la liste de fonctions
var compose = function(...args) {
    var len = args.length
    return function f1() {

    }
}
.

argscountC'est l'idée. Bien sûr, ce n'est pas possible. Il n'y a pas de condition de sortie récursive lorsque la dernière fonction est exécutée, c'est-à-dire lorsque args est . À l'heure actuelle, une chose à noter est qu'en cas de sortie récursive, le curseur

doit revenir à l'état initial. Enfin, ajoutez le code
var compose = function(...args) {
    var len = args.length
    var count = len - 1
    var result
    return function f1(...args1) {
        result = args[count].apply(this, args1)
        count--
        return f1.call(null, result)
    }
}

count pour implémenter cette fonction 0. Plus tard, j'ai découvert que la récursion peut être complètement implémentée en utilisant l'itération. Cela semble plus facile à comprendre en utilisant la fonction count. En fait, c'est ainsi que

est implémenté.
var compose = function(...args) {
        var len = args.length
        var count = len - 1
        var result
        return function f1(...args1) {
            result = args[count].apply(this, args1)
            if (count <= 0) {
                count = len - 1
                return result
            } else {
                count--
                return f1.call(null, result)
            }
        }
    }

composeL'idée d'implémenter whilelodash.js

est la même que ci-dessus, mais elle est implémentée de manière itérative. Je publierai son code source pour y jeter un œil

<.>lodash On peut voir que l'implémentation originale de

est celle de

, mais elle fournit également lodash de

, avec une couche supplémentaire de vérification de fonction, et ce qui est reçu est
var flow = function(funcs) {
    var length = funcs.length
    var index = length
    while (index--) {
        if (typeof funcs[index] !== &#39;function&#39;) {
            throw new TypeError(&#39;Expected a function&#39;);
        }
    }
    return function(...args) {
        var index = 0
        var result = length ? funcs[index].apply(this, args) : args[0]
        while (++index < length) {
            result = funcs[index].call(this, result)
        }
        return result
    }
}
var flowRight = function(funcs) {
    return flow(funcs.reverse())
}
, pas

, et à partir de cette ligne lodash nous pouvons voir que le tableau peut être vide, ce qui montre qu'il est très strict. Ce que j'ai écrit manquait de cette gestion rigoureuse des exceptions. 从左到右从右到左ConclusionflowRight数组Cette fois, j'ai principalement présenté les principes et les méthodes d'implémentation de la fonction 参数序列 en programmation fonctionnelle. Pour des raisons d'espace, j'ai mis l'implémentation du code source var result = length ? funcs[index].apply(this, args) : args[0] que je prévois. à analyser ci-dessous. Présentons-le dans un article. On peut dire que le

implémenté par

est plus fonctionnel et doit être analysé séparément.

Ce qui précède est le contenu implémenté par compose 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