Maison > développement back-end > Tutoriel Python > Pour les boucles et les compréhensions dans Elixir - transformation du code impératif

Pour les boucles et les compréhensions dans Elixir - transformation du code impératif

Linda Hamilton
Libérer: 2024-12-04 15:05:11
original
172 Les gens l'ont consulté

For loops and comprehensions in Elixir - transforming imperative code

Dans cet article, nous aborderons quelques utilisations courantes des boucles for et des compréhensions en Python, comment analyser une boucle existante et comment les transformer en leurs expressions équivalentes dans Elixir, en utilisant les fonctions du module Enum et des compréhensions.

Nous nous concentrerons sur :

  • transformer une collection de données grâce à une fonction (carte)
  • filtrage des valeurs dans ou hors d'une collection (filtre)
  • produire une valeur ou une structure globale unique, telle qu'une moyenne (réduire ou plier)

Nous terminerons par un exemple basique qui combine les trois !

Python

Pour les boucles

En Python, les for boucles comportent généralement un traitement entrelacé - les étapes sont combinées dans la même clause ou le même corps. Voici un exemple qui met au carré les deux premiers nombres pairs :

result = 0
for num in [1, 2, 3, 4, 5]:
    if num % 2 == 0:
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

Un défi de ce corps entrelacé est de :

  1. identifier chaque étape, et…
  2. déterminez de quel type d'étape il s'agit.

Séparer chaque étape vous permet de comprendre les transformations en cours, d'éliminer celles qui sont inutiles et de réécrire ces étapes dans une autre construction de langage ou une fonction de niveau supérieur.

Annoter la fonction ci-dessus entraîne :

result = 0
for num in [1, 2, 3, 4, 5]:
    ## Filter
    if num % 2 == 0:
        ## Reduce (result += ) and Map (num ** 2)
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

Les étapes

En conséquence, l'ordre des étapes est :

  1. Filtre les nombres impairs "out"/les nombres pairs "in"
  2. Map les nombres (par exemple 2) sur leur numéro carré correspondant (par exemple 4)
  3. Réduire à une somme des nombres pairs au carré

Compréhensions

Les

Compréhensions en Python sont des moyens simples de mapper et de filtrer des collections telles que des listes et des dictionnaires. Ils n'offrent pas de moyen de réduire le résultat, mais nous pouvons utiliser des fonctions intégrées comme sum pour transformer ce qui précède afin de traiter le résultat de la compréhension :

result = sum(num ** 2 for num in [1, 2, 3, 4, 5] if num % 2 == 0)
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion

Avec les compréhensions, l'expression divise l'étape map (num ** 2) et filter (si num % 2 == 0) clairement. la somme est l'étape réduire ici.

Il est facile de parcourir ces expressions de compréhension en Python, et cela place une limite supérieure utile à la complexité d'une compréhension.

Avec ce contexte et une meilleure compréhension de la structure et des limites des constructions de traitement de Python, passons à la réécriture du code Python ci-dessus en utilisant les compréhensions d'Elixir et les pipelines Enum !

Cartographie : Enum.map et générateurs

Comment pouvons-nous écrire l'étape en carrés ? Dans Elixir, c'est simple !

Utilisation d'Enum.map :

result = 0
for num in [1, 2, 3, 4, 5]:
    if num % 2 == 0:
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

et en utilisant des compréhensions (pour) :

result = 0
for num in [1, 2, 3, 4, 5]:
    ## Filter
    if num % 2 == 0:
        ## Reduce (result += ) and Map (num ** 2)
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le <- représente une expression générateur, générant des valeurs à utiliser dans le corps de l'expression for, après do:

Filtrage : Enum.filter et filtres

Facile à faire avec Enum.filter (ou Enum.reject) :

result = sum(num ** 2 for num in [1, 2, 3, 4, 5] if num % 2 == 0)
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion

Nous voudrons filtrer les nombres impairs avant qu'ils ne soient mis au carré, nous les plaçons donc au bon endroit dans le pipeline - avant Enum.map.

A l'aide des compréhensions, on peut ajouter une deuxième expression en tête de la compréhension, un filtre, qui est un test booléen :

Enum.map([1, 2, 3, 4, 5], & &1 ** 2)
Copier après la connexion

L'expression rem(n, 2) == 0 élimine ensuite tous les éléments qui renvoient faux (ou nul), laissant [2, 4] comme nombres réellement transmis au corps (do : n ** 2) de la compréhension.

Réduire -> Enum.reduce et réduire :

En utilisant Enum.reduce/2, nous pouvons convertir une liste de nombres au carré en leur somme en l'ajoutant à un accumulateur. Le premier élément est utilisé comme valeur initiale de l'accumulateur si on ne précise pas de valeur initiale pour l'accumulateur (Enum.reduce/3), et c'est pratique ici :

for n <- [1, 2, 3, 4, 5], do: n ** 2
Copier après la connexion

Avec les compréhensions, nous avons encore plus de puissance que l'équivalent Python. Nous pouvons ajouter une étape de réduction en ajoutant une autre clause en tête :

[1, 2, 3, 4, 5]
|> Enum.filter(& rem(&1, 2) == 0)
|> Enum.map(& &1 ** 2)




</p>
<p>faire deux changements ici :</p>

<ol>
<li>ajout d'une clause réduire: 0 en tête, pour préciser que l'on va accumuler une valeur dont la valeur initiale est 0</li>
<li>changer le corps for pour capturer une valeur acc (l'accumulateur) à laquelle nous pouvons ajouter la valeur au carré actuelle.</li>
</ol>

<h2>
  
  
  Fonctions intégrées : Enum.sum
</h2>

<p>En règle générale, nous devons exprimer les données que nous souhaitons transformer de la manière la plus élevée possible. Il est utile de considérer Enum.reduce comme la transformation fonctionnelle de niveau le plus bas, puisque tous les autres traitements de données peuvent être réécrits en fonction de celle-ci.</p>

<p>Le module Enum contient de nombreuses fonctions de niveau supérieur, impliquant généralement la réduction d'une liste de valeurs à une seule valeur globale, comme une somme, un maximum ou un minimum. Dans ce cas, nous aimerions la somme des éléments.</p>

<p>Pour les pipelines Enum, c'est simple :<br>
</p>

<pre class="brush:php;toolbar:false">for n <- [1, 2, 3, 4, 5], rem(n, 2) == 0, do: n ** 2
Copier après la connexion

Il n'existe aucun moyen de représenter ces fonctions d'agrégation de haut niveau dans les compréhensions, nous pouvons donc diriger le résultat de la compréhension vers un appel Enum.sum comme ceci, de la même manière que nous l'avons fait en Python :

[1, 2, 3, 4, 5]
|> Enum.filter(& rem(&1, 2) == 0)
|> Enum.map(& &1 ** 2)
|> Enum.reduce(& &1 + &2)
Copier après la connexion

Le mélange de différentes formes doit généralement être évité, surtout si la transformation est simple, car cela entraîne moins de charge mentale pour le lecteur - la forme réduire : ci-dessus est en fait plus claire à lire bien qu'elle soit de niveau inférieur.

Quelle expression d’Elixir est la meilleure ?

Pour résumer, nous nous retrouvons avec deux formes qui pourraient être considérées comme idiomatiques. Pour les pipelines Enum :

result = 0
for num in [1, 2, 3, 4, 5]:
    if num % 2 == 0:
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

et compréhensions :

result = 0
for num in [1, 2, 3, 4, 5]:
    ## Filter
    if num % 2 == 0:
        ## Reduce (result += ) and Map (num ** 2)
        result += num ** 2
print(result)  # Output: 20
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le code facile à lire doit être simple à parcourir, sans ambiguïté ni trébuchement sur les expressions. Je pense que les deux formulaires remplissent ce critère, comme :

  1. ils suivent une seule forme cohérente - soit des pipelines Enum, soit des compréhensions
  2. chaque expression correspond à une seule étape de traitement
  3. il peut être lu de haut en bas ou de gauche à droite sans interruption

Conclusion

L'écriture de ces transformations peut être effectuée de plusieurs manières différentes dans Elixir, et il est facile pour une base de code de varier les styles, d'autant plus que le code change et que le traitement devient plus compliqué avec le temps.

PureType peut décomposer et analyser les pipelines et les compréhensions Enum pour les représenter sous leur forme la plus claire et la plus idiomatique, en apprenant vos préférences et en augmentant la lisibilité et la clarté de votre code pour les autres membres de l'équipe. Essayez-le aujourd'hui !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal