10
votes

Comment écrire un code idiomatique de clojure (+ fonctionnel)?

Je viens de commencer à pirater avec de la grojure et, bien que j'adore la langue, je ne comprends pas comment faire certaines choses idiomatiquement.

Écrire une application Web à l'aide de Compojure, voici l'une de mes actions de contrôleur: xxx

J'écris cela de manière très impérative. Utilisation de tellement let S / si s / faire s, je ne peux pas m'empêcher de penser que je fais quelque chose de très faux. Comment voudrais-je écrire cela fonctionnellement?

Voici le pseudocode pour ce que j'essaie de faire xxx

merci beaucoup!


0 commentaires

3 Réponses :


5
votes

Les styles de programmation fonctionnels encouragent à l'aide de fonctions de niveau supérieur tels que la carte, réduire et filtrer, elles vous obligent également à faire face à des structures de données immuables la plupart du temps. Rien n'est faux avec votre code jusqu'à présent, car vous n'avez pas cassé aucune règle de programmation fonctionnelle. Cependant, vous pouvez améliorer votre code un peu, comme la combinaison de lecteurs et si vous utilisez si-let.


0 commentaires

3
votes

Cela semble raisonnable et, étant donné que vos seuls effets secondaires sont "nécessaires", c'est-à-dire d'ajouter à la session, je ne l'appellerais pas terriblement impératif. Il y a trois changements que je ferais, bien que le troisième est facultatif:

  • Comme une autre réponse suggérée, changez le si / laisse par paire dans un seul si-let . .
  • Utilisez (: FOO Bar) pour les recherches de mots clés sur une carte, pas (barre: foo) . C'est juste le moyen standard de le faire .
  • Ne vous inquiétez pas de créer un local pour nouvel utilisateur , puisque vous ne l'utilisez qu'une seule fois; Vous pouvez simplement l'aligner.

    Il y a un autre changement que je ne ferais pas, car je pense que cela réduirait la lisibilité. Cependant, c'est une question de style et de jugement, alors je vais le mentionner comme quelque chose que vous pensez. Remarquez comment chaque branche du si met fin au labyrinthe dans un appel à resp / redirection : vous pouvez extraire tous ces appels au niveau supérieur. et puis décider quels arguments lui passeront. Combiné avec les autres changements, il ressemblerait à: xxx


1 commentaires

C'est bien. Merci beaucoup!



8
votes

Il n'y a rien de non fonctionnel sur si - c'est une construction parfaitement bonne et purement fonctionnelle qui évalue une expression conditionnelle. Trop de si s dans un endroit peut-être un signe d'avertissement que vous devriez utiliser une construction différente (par exemple, Cond? Polymorphisme avec protocoles? MultiMethods? Une composition des fonctions d'ordre supérieur?)

faire est plus délicat: si vous avez un faire, cela implique que vous faites quelque chose pour un effet secondaire , qui est définitivement non fonctionnelle. Dans votre cas Connexion et UTILISATEUR / CREATE apparaît comme étant les coupables latéraux ici ici.

Que devriez-vous faire sur les effets secondaires? Eh bien, ils sont parfois nécessaires, alors le défi est de savoir comment votre structure votre code pour s'assurer que les effets secondaires sont contrôlés et gérables (entièrement refactés dans une zone de danger de manutention spéciale de sorte que le reste de votre code puisse rester propre et purement fonctionnel. ).

Dans votre cas, vous pourriez envisager:

  • Passer la fonction "Utilisateur / Authentification" dans le cadre de votre entrée (par exemple, dans une forme de carte de contexte). Cela vous permettra de passer dans des fonctions d'authentification testées, par exemple lorsque vous ne souhaitez pas utiliser la vraie base de données.
  • Renvoie un drapeau "authentifié avec succès" dans le cadre de la sortie. Cela seraient alors pris par une fonction de gestionnaire de niveau supérieur qui pourrait être responsable de l'exécution de tous les effets secondaires liés à la signature.
  • renvoie alternativement un drapeau "nouvel utilisateur" dans le cadre de la sortie, que la fonction de gestionnaire reconnaît et effectue une configuration utilisateur requise.

3 commentaires

Merci beaucoup pour la longue réponse détaillée! À quoi ressemblerait une fonction de gestionnaire / créer une fonction de fonction? Et qu'entendez-vous par les drapeaux? La fonction retournerait les chaînes appropriées?


Il y a beaucoup d'options. Une solution pourrait être d'avoir une liste d'effets secondaires "actions" dans votre carte de réponse que la fonction de gestionnaire exécute en séquence. Vous voudrez peut-être également examiner comment fonctionne une partie du middleware anneau.


En effet, la construction "if-then-tree" a été inventée par John McCarthy, le créateur de LISP, spécifiquement pour faciliter la programmation fonctionnelle. en.wikipedia.org/wiki/mccarthy_formalisme