Jekyll2019-11-22T12:34:27+00:00/feed.xmlDamien MorardI share my passion about Computer Science and programming. You can find posts about my research, some tutorials in programming, or just sharing my knowledge. I particularly use the Swift language, created by Apple.Damien MorardClosures, Partial application and currying (Part 1/2) (Swift)2019-08-13T00:00:00+00:002019-08-13T00:00:00+00:00/tutorial/2019/08/13/closure-en<h2 id="introduction">Introduction</h2>
<p>Are you afraid by this title?
Do not go away and take time to demystify these concepts, understanding how it works.</p>
<h2 id="welcome-to-the-fantastic-world-of-closures">Welcome to the fantastic world of closures</h2>
<p>Look at <a href="https://docs.swift.org/swift-book/LanguageGuide/Closures.html">Swift</a> documentation and what we have about closures.</p>
<blockquote>
<p>“Closures are self-contained blocks of functionality that can be passed around and used in your code.”</p>
</blockquote>
<p>Is not it like a toolbox?
In this box, we could have the tools, use them to get/modify the result.
This seems a bit general, however the documentation keeps going:</p>
<blockquote>
<p>“Closures can capture and store references to any constants and variables from the context in which they are defined.”</p>
</blockquote>
<p>I think we need to clarify some notions to have a better understanding of the theory.
A closure is like an environment, a memory which keeps values that we have defined in.
Variables are only known in the scope where you declared them.
For instance:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">foo</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="mi">3</span>
<span class="c1">// 3</span>
<span class="nf">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">// Use of unresolved identifier 'x'</span>
<span class="nf">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</code></pre></div></div>
<p>In this example, we have a function “<em>foo</em>” which declare a variable a variable “<em>x</em>”.
This variable is only known inside the function.
When we get out, we do not know “<em>x</em>” anymore.
We have the same behavior for a closure.
Hence, we have variables, and functionalities that are just functions.</p>
<p>Later, we will see more information about closures.
For now, we focus on how we can use them in Swift.</p>
<p>What is Swift tells us about the syntactic representation of closures?</p>
<blockquote>
<p>“Closure expression syntax has the following general form:”</p>
</blockquote>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span> <span class="p">(</span><span class="n">parameters</span><span class="p">)</span> <span class="o">-></span> <span class="k">return</span> <span class="n">type</span> <span class="k">in</span>
<span class="n">statements</span>
<span class="p">}</span>
</code></pre></div></div>
<p>One of the main defaults which is difficult with closure is its syntax.
We need to identify each component to understand how it works.</p>
<p>Let’s take an example:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">clos</span> <span class="o">=</span> <span class="p">{(</span><span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">}</span>
<span class="c1">// Print 42</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">clos</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">22</span><span class="p">))</span>
</code></pre></div></div>
<p>We can see a closure as a function without a name, calling from the variable which is bound to “<em>clos</em>”.
Same as a function, closures have inputs, its type and the output type.
The key word “<em>in</em>” replaces the separation between the signature and the body.
The key word “<em>return</em>” is the same as usual.
If you decide to call this closure, you can make it use the name “<em>clos</em>” as a function name.
You add inputs and you are ready to go!
You easily understand that we just make an addition, but there is nothing exciting.</p>
<p>Let’s look at another example, using a closure in function inputs.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">apply</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span><span class="n">_</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">(</span><span class="kt">Int</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">op</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The “<em>apply</em>” function takes two Integer and will apply an operation on them.
Do you understand the signature “<em>op: (Int, Int) -> Int</em> “?
It means that the label “<em>op</em>” is waiting a function or a closure which takes two Integers as inputs and return an Integers.
Just a coincidence (or not), our last closure has the same signature.
So, we can call our function like this:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Retourne 42</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="n">clos</span><span class="p">))</span>
</code></pre></div></div>
<p>Are you beginning to understand?
We have a way to make it easier, without declaring the closure before:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Any functions/closures having the signature “<em>(Int, Int) -> Int</em> “ can be used as a parameter for “<em>op</em>”.</p>
<p>Do you want syntactics tips to help you?
Let’s go !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>(Traduction en cours)</p>
<p>Did you see that we omit type parameter?
Why does it work so?
Thanks to the type <a href="https://en.wikipedia.org/wiki/Type_inference">inference</a>! (Not a black magic)
At the time we declared the function “<em>apply</em>”, Swift already know the waiting type, seeing that we gave them at the function declaration.
Swift automatically makes the association, and it is wonderful no?
However, we are far to see all the things that we can do again!
Next!</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">in</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Does not need a return?
Indeed, when there is any ambiguity about the return value, Swift understands that the operation “<em>x+y</em>” is just the return value.
After the “<em>in</em>” parameter, you can add as many parameters as many codes as needed.
It is not finished yet, we have a way to do better!</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{</span><span class="nv">$0</span> <span class="o">+</span> <span class="nv">$1</span><span class="p">})</span>
</code></pre></div></div>
<p>Have I been too far?
Test from yourself and you will see that it works!
In this piece of code, we do not distinguish the signature and the body of our closure.
From the same principle of the type inference, Swift can guess what we are waiting.
How can we get value parameters?
“<em>$0</em> “ et “<em>$1</em> “ are generic names that Swift use by default, taking input values.</p>
<p>Are you a bit lost?
Take back the signature “<em>op: (Int, Int) -> Int</em> “.
Here “<em>$0</em>” is just the first Integer and “<em>$1</em>” the second.
The order of input parameters corresponds to the order of the parameters in the signature function.
Therefore, Swift has binding values with predefined names.
Last syntactic thing before I left you with closures!</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">)</span> <span class="p">{</span><span class="nv">$0</span> <span class="o">+</span> <span class="nv">$1</span><span class="p">}</span>
</code></pre></div></div>
<p>When the last parameter of your function is a closure, you can just call like this.
Do not even need to give the parameter names, only need to write a closure between curly braces.
All the last closures work with this syntax.
Nevertheless, do not forget the readability of your code!</p>
<p>This part is now ended, keep going on the next part of partial application!</p>
<p><a href="../../../2019/08/15/partial-application-en.html">Partie 2: Partial application and currying</a></p>DamienIntroductionLes closures, l’application partielle et la curryfication (Partie 2/2) (Swift)2019-08-10T00:00:00+00:002019-08-10T00:00:00+00:00/tutorial/2019/08/10/partial-application-fr<p>Si vous n’avez pas encore lu la première partie, c’est <a href="../../../2019/08/09/closure-fr.html">ici</a> !
Il est important de bien comprendre les notations utilisées lors de la précédente partie.</p>
<h2 id="lapplication-partielle">L’application partielle</h2>
<p>J’espère déjà que la boîte noire que représente les closures pour certains ne vous concerne plus.
Vous vous doutez bien que si nous avons vu les closures, ce n’est pas pour tout oublier et changer complètement de registre !</p>
<p>L’application <strong>partielle</strong> a pour principe d’initialiser des variables en fonction d’où nous nous situons dans l’appel d’une fonction/closure.
Imaginons que vous fassiez des pizzas (de A à Z).
En premier lieu vous allez faire la pâte, et seulement ensuite vous mettrez les ingrédients.
Vous êtes d’accord que la même pâte est utilisé peu importe les ingrédients que vous mettez (Les Italiens me pardonneront) ?
C’est un peu la même chose pour nous, parfois nous allons avoir des ingrédients qui seront toujours présent peu importe ce que nous faisons par la suite.</p>
<h3 id="lexemple-du-poids">L’exemple du poids</h3>
<p>Prenons un exemple plus concret !
Vous souvenez vous de vos cours de physique ?
Ne vous inquiétez pas, nous n’allons rien voir de bien compliqué.
Vous savez sûrement que la gravité n’est pas la même sur la Terre que sur la Lune.
Nous avons la formule suivante en physique :</p>
<p><code class="highlighter-rouge">P = m * g</code> (<em>P</em> étant le poids, <em>m</em> la masse et <em>g</em> la gravité).
La masse et le poids sont deux choses distinctes !</p>
<p>La gravité de la Terre est de 9.81 N/kg, et supposons une masse de 70 kg.
Nous obtenons alors <em>P = 9.81</em> * <em>70</em> (N), qui est le poids sur Terre d’une personne avec une masse particulière.
Après cette légère paranthèse, vous allez comprendre pourquoi je vous ai introduit ces quelques notions.</p>
<p>Je veux désormais créer une fonction permettant de calculer le poids d’une personne sur Terre.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">poidsTerre</span><span class="p">(</span><span class="nv">m</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Double</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">m</span> <span class="o">*</span> <span class="mf">9.81</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">poidsTerre</span><span class="p">(</span><span class="nv">m</span><span class="p">:</span> <span class="mi">70</span><span class="p">))</span>
</code></pre></div></div>
<p>Si maintenant j’aimerai avoir le poids d’une personne sur la Lune, comment suis-je censé faire ?
Je dois écrire une nouvelle fonction pour changer une seule valeur ?</p>
<p>Heureusement, il y a un moyen plus générique de le faire pour ne pas avoir à écrire une nouvelle fonction à chaque fois que nous voulons connaître notre poids sur une planète différente !</p>
<p>Je vous propose le code ci-dessous faisant appel à l’application partielle:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">poids</span><span class="p">(</span><span class="nv">g</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Double</span> <span class="p">{</span>
<span class="kd">func</span> <span class="nf">foo</span><span class="p">(</span><span class="nv">m</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Double</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">m</span> <span class="o">*</span> <span class="n">g</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">foo</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Wooooooow, c’est peut-être ce que vous êtes entrain de vous dire.
Je vous l’accorde, il y a pas mal de différences entre les deux versions, mais nous allons décortiquer tout cela ensemble.
La première principale différence est la signature de la fonction.
En effet, nous ne retournons pas directement un “<em>Double</em>”, mais une fonction qui prend un “<em>Double</em>” et retourne un “<em>Double</em>”.
C’est ce que signifie le retour “<em>(Double) -> Double</em>”.
Cette syntaxe vous rappelle sûrement ce que nous avons vu avec les opérations de la partie précédente.</p>
<p>Il nous faut donc retourner une fonction, c’est pour cette raison que nous avons créé “<em>foo</em>”, qui a la signature “<em>(Double) -> Double</em>” (exactement ce que nous voulons).
Cette seconde fonction fait juste l’application de la formule vu plus haut.
Nous prenons bien soin de remarquer que nous retournons “<em>foo</em>” et non “<em>foo(…)</em>”.
Ce n’est absolument pas la même chose, d’un côté nous retournons la fonction, et de l’autre nous retournons l’appel à cette fonction !</p>
<p>La signature de “<em>foo</em>” est “<em>(Double) -> Double</em>” tandis que celle de l’appel de “<em>foo(…)</em>” est “<em>Double</em>”.
Surtout que pour appeler la fonction <em>foo(…)</em> il nous faudrait un paramètre que nous n’avons pas encore.
Vous voulez vous en convaincre ?
À ce moment tenter d’afficher le résultat de l’appel de “<em>poids</em>” avec “<em>g</em>”.
Réfléchissez deux minutes avant de passer à la suite.</p>
<p>…</p>
<p>Allez on regarde !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Retourne (Function)</span>
<span class="k">let</span> <span class="nv">poidsTerre</span> <span class="o">=</span> <span class="nf">poids</span><span class="p">(</span><span class="nv">g</span><span class="p">:</span><span class="mf">9.81</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">poidsTerre</span><span class="p">)</span>
<span class="c1">// Retourne (Double) -> Double</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">type</span><span class="p">(</span><span class="nv">of</span><span class="p">:</span> <span class="n">poidsTerre</span><span class="p">))</span>
</code></pre></div></div>
<p>Swift nous dit que le résultat est une fonction, dont vous connaissez la signature !
Si nous désirons connaître le résultat pour une masse particulière, il nous faut appeler cette nouvelle fonction avec le paramètre de “<em>foo</em>”.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Possibilité 1</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">poids</span><span class="p">(</span><span class="nv">g</span><span class="p">:</span><span class="mf">9.81</span><span class="p">)(</span><span class="mi">70</span><span class="p">))</span>
<span class="c1">// Possibilité 2</span>
<span class="k">let</span> <span class="nv">poidsTerre</span> <span class="o">=</span> <span class="nf">poids</span><span class="p">(</span><span class="nv">g</span><span class="p">:</span><span class="mf">9.81</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">poidsTerre</span><span class="p">(</span><span class="mi">70</span><span class="p">))</span>
</code></pre></div></div>
<p>Tout l’intérêt réside dans la possibilité 2, nous pouvons initialiser une variable avec une gravité particulière.
Nous nous en servons ensuite comme d’une nouvelle fonction qui attend en paramètre la masse.
C’est quand même plus pratique d’avoir à déclarer une seule fonction, que vous pouvez aisément mettre dans une variable.</p>
<p>Je viens de vous montrer le fonctionnement général, cependant il vous faudra pratiquer ces notions pour que cela devienne intuitif.</p>
<h3 id="une-définition-plus-complète-de-la-closure">Une définition plus complète de la closure</h3>
<p>Avez-vous remarqué le lien avec les closures ?
Depuis le début nous nous en servons, les closures sont partout !
Quand nous déclarons “<em>poidsTerre</em>”, nous gardons en mémoire une closure.
Le concept que nous avons vu jusqu’à maintenant restait simple, sans aborder vraiment sa consistance même !</p>
<p>Au final, une closure ce n’est rien d’autre qu’une fonction accompagnée de son environnement lexical.
Un environnement lexical ? What is it ?
C’est simplement toutes les valeurs qui ont été capturées et qui peuvent être utilisées dans l’appel de notre fonction.
Prenons l’exemple de “<em>poidsTerre</em>” pour mieux comprendre.
Dans notre cas, “<em>poidsTerre</em>” est une closure contenant comme valeur capturé “<em>g</em>” étant égal à <em>9.81</em>, et une fonction foo.
Dire que nous avons capturé “<em>g</em>” revient à dire que notre variable sera connue dans l’appel de “<em>foo</em>”.
Cette notion est très large et fait partie de ce que nous appelons la <a href="https://fr.wikipedia.org/wiki/Port%C3%A9e_(informatique)">portée</a> (scope).
Nous ne nous étendrons pas sur ce sujet dans cet article, mais si vous désirez en savoir plus sur le fonctionnement je vous y encourage vivement !</p>
<p>Vous avez peut-être remarqué le nom de fonction “<em>foo</em>” qui n’a pas vraiment de signification.
Ce nom sera inconnu en dehors du corps de la fonction “<em>poids</em>”, et vous ne vous en servirez quasiment jamais (parce qu’il ne faut jamais dire jamais) !
Au moment de l’appelée avec “<em>poidsTerre</em>”, pas besoin de donner un nom de fonction, et pas non plus besoin de donner le nom du label.</p>
<p>Alors ce serait pas mieux de retourner directement une closure plutôt qu’une fonction dont le nom ne nous intéresse guère ?
Bien vu !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">poids</span><span class="p">(</span><span class="nv">g</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Double</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{(</span><span class="nv">m</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Double</span> <span class="k">in</span>
<span class="n">m</span><span class="o">*</span><span class="n">g</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Vous pouvez essayer de votre côté, nous avons exactement le même résultat attendu.
Nous avons repris la syntaxe des closures que nous avons vu dans la partie précédente.
C’est comme retournée une fonction sans nom, et ça tombe bien vu que nous n’en avons pas besoin !</p>
<p>L’application partielle permet de donner autant de paramètres que souhaités, de même que nous pouvons faire une cascade de closures qui demanderont chacunes diverses paramètres.</p>
<p>Nous sommes enfin parés pour attaquer la dernière partie avec la curryfication !</p>
<!-- [Partie 3: La curryfication](../../../2019/08/11/curryfication.html) -->
<h2 id="la-curryfication">La curryfication</h2>
<p>J’espère que vous êtes bien au clair avec les closures et l’application partielle vu que cette dernière partie va tout mettre à profit.</p>
<p>La curryfication est le principe de prendre une fonction avec “<em>n</em>” paramètres et de la transformer en “<em>n</em>” fonctions avec chacune un argument.</p>
<p>À l’inverse l’application partielle prend une fonction à “<em>n</em>” arguments et la transforme en “<em>m</em>” fonctions, avec “<em>m <= n</em>” (Nous avons au plus autant de fonctions que d’arguments).
Prenez le temps de relire ces phrase plusieurs fois si besoin.</p>
<p>Vous vous souvenez de l’exemple du poids de la dernière partie ?
Même si l’objectif n’était pas de curryfier notre fonction, c’est pourtant ce que nous avons fait.</p>
<p>Si nous regardons juste en terme de signature de fonctions, voici un exemple:
<code class="highlighter-rouge">(Int, Int) -> Int</code> devient <code class="highlighter-rouge">(Int) -> (Int) -> Int</code></p>
<p>Nous pouvons faire encore plus:
<code class="highlighter-rouge">(Int, Int, Int) -> Int</code> devient <code class="highlighter-rouge">(Int) -> (Int) -> (Int) -> Int</code></p>
<p>C’est bien joli mais je pense que vous voulez voir des exemples un peu plus concret.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Version classique</span>
<span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="n">_</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">add</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">22</span><span class="p">))</span>
<span class="c1">// Version curry</span>
<span class="kd">func</span> <span class="nf">addCurry</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span><span class="n">y</span> <span class="k">in</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">addCurry</span><span class="p">(</span><span class="mi">20</span><span class="p">)(</span><span class="mi">22</span><span class="p">))</span>
</code></pre></div></div>
<p>La version classique est plus intuitive à réaliser de prime abord.
La version “<em>addCurry</em>” reprend exactement toutes les notions abordées jusqu’à présent.
Nous avons simplement décomposé le second argument de la fonction dans notre closure.</p>
<p>Je vous montre aussi l’exemple à trois arguments tant que nous y sommes !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="n">_</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="n">_</span> <span class="nv">z</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">22</span><span class="p">))</span>
<span class="kd">func</span> <span class="nf">addCurry</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span><span class="n">y</span> <span class="k">in</span>
<span class="k">return</span> <span class="p">{</span><span class="n">z</span> <span class="k">in</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="o">+</span> <span class="n">z</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">add</span><span class="p">(</span><span class="mi">10</span><span class="p">)(</span><span class="mi">10</span><span class="p">)(</span><span class="mi">22</span><span class="p">))</span>
</code></pre></div></div>
<p>Nous prenons simplement chaque argument de la fonction “<em>add</em>” pour faire en sorte d’avoir des fonctions avec un unique argument.</p>
<p>Le principe de curryfication peut s’appliquer dans les deux sens, nous pouvons prendre une fonction pour la curryfier ou la decurryfier.</p>
<h3 id="différence-entre-application-partielle-et-curryfication">Différence entre application partielle et curryfication</h3>
<p>Au final, nous pourrions croire que la curryfication est un cas particulier de l’application partielle mais il existe une différence qui sépare ces deux notions.
L’application partielle n’a pas nécessité à avoir un type de retour, tandis que la curryfication retournera toujours une fonction à un argument jusqu’au dernier type de retour qui sera la valeur.
Cette nuance est subtile mais à le mérite d’exister, mais nous ne sommes pas ici pour débattre plus en détail sur ce sujet.</p>
<h3 id="avantage-de-la-curryfication">Avantage de la curryfication</h3>
<p>Quand vous curryfier une fonction, vous la transformez en ce que nous appelons une fonction “<strong>pure</strong>”, possédant une propriété très intéressante.
En effet les fonctions pures n’ont aucun effet de bord, c’est-à-dire qu’aucun comportement (mutation) non désirable dans le programme n’est possible.</p>
<p>Vous avez les mêmes avantages qu’avec l’application partielle:</p>
<ul>
<li>Une meilleure décomposition du code</li>
<li>Plus de clarté et de lisibilité du code</li>
<li>La possibilité de déclarer des variables à différents niveaux de l’exécution.</li>
<li>Vous pouvez plus facilement cibler à quel niveau vous désirez appliquer une modification.</li>
</ul>
<p>Je vous conseille vivement de tester par vous-même, c’est le meilleur moyen de vous en rendre compte.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Nous arrivons à la fin de notre série de tutoriel sur les closures, l’application partielle et la curryfication.
J’espère avoir démystifier ces principes, et surtout vous avoir apporté une meilleure compréhension globale sur le sujet.</p>
<p>Je n’ai pas couvert tous les cas, et certains sujets méritent encore d’être explorés plus en profondeur.
J’aurai l’occasion de revenir dans un article sur l’utilisation des closures dans les fonctions “<em>map</em>”, “<em>filter</em>” et “<em>reduce</em>”.</p>
<p>Si vous avez des remarques / suggestions n’hésitez pas, je tâcherai de les prendre en compte au mieux.</p>
<p>Merci de m’avoir lu et j’espère vous retrouver dans d’autres articles !</p>DamienSi vous n’avez pas encore lu la première partie, c’est ici ! Il est important de bien comprendre les notations utilisées lors de la précédente partie.Les closures, l’application partielle et la curryfication (Partie 1/2) (Swift)2019-08-09T00:00:00+00:002019-08-09T00:00:00+00:00/tutorial/2019/08/09/closure-fr<h2 id="introduction">Introduction</h2>
<p>Ce titre vous fait peur ? Ou plutôt les notions abordées sont effrayantes ?
Ne fuyez pas et prenez le temps à mes côtés de démystifier ses concepts, comprendre le fonctionnement derrière ce qui peut vous sembler être de la magie.</p>
<p>Disponible sur <a href="https://medium.com/@dmorard1/fermeture-closure-application-partielle-et-curryfication-en-swift-partie-1-3-4c2c6f2bce67">Medium</a>.</p>
<h2 id="bienvenue-dans-le-monde-fantastique-des-closures-ou-fermetures">Bienvenue dans le monde fantastique des closures (ou fermetures)</h2>
<p>Qu’est-ce que nous dit la documentation <a href="https://docs.swift.org/swift-book/LanguageGuide/Closures.html">Swift</a> à ce sujet ?</p>
<blockquote>
<p>“Closures are self-contained blocks of functionality that can be passed around and used in your code.”</p>
</blockquote>
<blockquote>
<p>“Les closures sont des blocs autonomes composés de fonctionnalités pouvant être passées et utilisées dans votre code”.</p>
</blockquote>
<p>Finalement, c’est pas un peu comme une boîte à outils ? Dans cette boîte nous pouvons imaginer avoir des outils, et les manipuler nous permet d’obtenir/modifier certaines pièces.
Cette définition reste un peu générale, mais la documentation ne s’arrête pas là:</p>
<blockquote>
<p>“Closures can capture and store references to any constants and variables from the context in which they are defined.”</p>
</blockquote>
<blockquote>
<p>“Les closures peuvent capturer et enregistrer des références pour n’importe quelles constantes ou variables du contexte dans laquelles elles sont définies.”</p>
</blockquote>
<p>Je pense que nous avons besoin de clarifier certaines notions de ces définitions pour bien comprendre la théorie.
Une closure c’est un peu comme un environnement, une mémoire qui va garder des valeurs que nous avons défini à l’intérieur.
C’est comme quand vous déclarez des variables, sauf qu’elles seront seulement accessible dans une certaine portée.
Je crois qu’un petit exemple ne fera pas de mal:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">foo</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">x</span> <span class="o">=</span> <span class="mi">3</span>
<span class="c1">// 3</span>
<span class="nf">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">// Use of unresolved identifier 'x'</span>
<span class="nf">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</code></pre></div></div>
<p>Dans ce petit exemple, nous avons une fonction “<em>foo</em>” qui déclare à l’intérieur une variable “<em>x</em>”.
Cette variable est visible seulement à l’intérieur de notre fonction, une fois sortie celle-ci n’existe plus.
C’est la même chose pour une closure !
Nous avons donc des variables, et des fonctionnalités qui ne sont rien d’autre que des fonctions.</p>
<p>Nous aurons l’occasion un peu plus tard de revenir en détail sur les closures.
Pour l’heure, regardons comment nous pouvons les manipuler en Swift.</p>
<p>Qu’est-ce que Swift nous dit-il par rapport à la représentation syntaxique des closures ?</p>
<blockquote>
<p>“Closure expression syntax has the following general form:”</p>
</blockquote>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span> <span class="p">(</span><span class="n">parameters</span><span class="p">)</span> <span class="o">-></span> <span class="k">return</span> <span class="n">type</span> <span class="k">in</span>
<span class="n">statements</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Cette syntaxe vous a l’air peut-être rude, et c’est sûrement le premier point qui fait défaut quand nous désirons manipuler des closures.
Il faut avant tout comprendre la syntaxe pour l’utiliser convenablement.</p>
<p>Prenons un petit exemple en utilisant ce que nous venons de voir.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">clos</span> <span class="o">=</span> <span class="p">{(</span><span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">}</span>
<span class="c1">// Retourne 42</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">clos</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">22</span><span class="p">))</span>
</code></pre></div></div>
<p>Nous pouvons voir une closure comme une fonction sans nom, qui est appelée grâce à la variable à laquelle elle a été liée (clos dans notre cas).
Comme une fonction nous avons des paramètres d’entrée, le type de ces paramètres et le type de sortie.
Plutôt que d’avoir la syntaxe des accolades pour séparer la signature et le corps de la fonction, nous avons le mot-clé “<em>in</em> “.
Nous avons pour terminer la valeur de retour que nous signalons aussi avec le mot-clé “<em>return</em> “.
L’appel de cette closure se fait exactement de la même manière que si le nom de notre fonction était <em>clos</em>.
C’est-à-dire qu’il nous suffit de passer à notre closure les paramètres attendus.
Vous aurez compris que notre closure fait simplement l’addition de nos deux paramètres, rien de très passionnant n’est-ce pas ?</p>
<p>Passons un cran au-dessus en supposant que nous avons cette fois une fonction prenant en paramètre une closure !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">apply</span><span class="p">(</span><span class="n">_</span> <span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span><span class="n">_</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">(</span><span class="kt">Int</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">op</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Nous avons désormais la fonction “<em>apply</em>”, qui prend deux entiers et va appliquer une opération sur ceux-ci.
Il faut être au clair sur la notation “<em>op: (Int, Int) -> Int</em> “.
Cela signifie que le paramètre “<em>op</em>” attend une fonction ou une closure qui prend deux entiers comme paramètres d’entrée, et retourne un entier.
Vous l’avez peut-être remarqué, mais la closure que nous avons écrite avant répond parfaitement à ces conditions.
Nous pouvons donc simplement appelée notre fonction ainsi :</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Retourne 42</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="n">clos</span><span class="p">))</span>
</code></pre></div></div>
<p>Vous commencez à comprendre ?
Nous pouvons même faire plus simple sans avoir à déclarer notre closure au préalable comme ceci :</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="nv">x</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">-></span> <span class="kt">Int</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Toutes les fonctions/closures ayant pour signature “<em>(Int, Int) -> Int</em> “ peuvent être utilisées comme paramètre de <em>op</em>, peu importe que celles-ci aient été déclarées avant ou directement à l’appel.</p>
<p>Vous voulez quelques petites astuces syntaxiques pour vous simplifier la vie ?
C’est parti !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">in</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Vous avez peut-être remarqué mais nous avons omis le type de nos paramètres, et même le type de sortie ! Pourquoi ça fonctionne alors ?
Dites merci à l’<a href="https://fr.wikipedia.org/wiki/Inf%C3%A9rence_de_types">inférence de type</a> et non à une magie obscure.
Au moment de déclarer la fonction <em>apply</em>, nous avons déjà dit à Swift les types que nous attendions.
Swift a automatiquement fait le rapprochement entre ce qu’il attend comme type et ce que vous lui donnez. C’est franchement génial non ?
Pourtant nous sommes loin d’avoir vu toutes les simplifications possibles.
Next !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">in</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="p">})</span>
</code></pre></div></div>
<p>Pas besoin de return ? Quand il n’y a aucune ambiguïté pour un cas aussi simple, Swift comprend que “<em>x+y</em> “ est la valeur de retour. Bien entendu, vous pouvez mettre autant de code que vous désirez après le “<em>in</em> “, cependant il faudra remettre un “<em>return</em> “ !</p>
<p>C’est pas encore fini, nous pouvons encore faire mieux !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="nv">op</span><span class="p">:</span> <span class="p">{</span><span class="nv">$0</span> <span class="o">+</span> <span class="nv">$1</span><span class="p">})</span>
</code></pre></div></div>
<p>J’ai été trop loin ? Testez et vous verrez que ça marche !
Dans ce code, nous n’avons même pas eu besoin de faire une quelconque différence entre signature et corps de fonction.
Par le même principe que l’inférence de type, dans cette situation Swift sait ce qu’il attend.
Comment récupérons-nous les valeurs de nos paramètres ?
“<em>$0</em> “ et “<em>$1</em> “ sont des noms conventionnels que Swift utilise par défaut, prenant les valeurs des paramètres d’entrée.</p>
<p>Un peu perdu ? Reprenons la signature de “<em>op: (Int, Int) -> Int</em> “.
Donc “<em>$0</em> “ correspond au premier entier et “<em>$1</em> “ au second.
L’ordre est important, car si nous avions par exemple “<em>op: (Int, String) -> Int</em> “, “<em>$1</em> “ serait alors une chaîne de caractères.
Swift a donc lié à des noms prédéfinis les valeurs, plutôt que nous donnions nous-mêmes le nom de celle-ci.
Pour le “<em>return</em> “ qui n’est pas nécessaire je vous renvoie à ce que j’ai dit plus haut.</p>
<p>Encore un petit truc pour la route purement syntaxique, mais qui vous facilitera sûrement la vie !</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">apply</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">22</span><span class="p">)</span> <span class="p">{</span><span class="nv">$0</span> <span class="o">+</span> <span class="nv">$1</span><span class="p">}</span>
</code></pre></div></div>
<p>Quand le dernier paramètre de votre fonction est une closure, vous pouvez l’appeler de cette manière.
Même pas besoin de donner le nom du paramètre, vous écrivez juste entre accolade votre closure.
Toutes les closures vues précédemment fonctionnent avec cette syntaxe.</p>
<p>Quand nous manipulons des fonctions aussi simple, vous conviendrez que nous pouvons nous simplifier la vie.
Il faut cependant toujours faire attention à la lisibilité.</p>
<p>Nous en avons terminé avec cette première partie sur les closures, passons sans plus tarder
à l’application partielle !</p>
<p><a href="../../../2019/08/10/partial-application-fr.html">Partie 2: L’application partielle et la curryfication</a></p>DamienIntroductionIntroduction2019-08-08T00:00:00+00:002019-08-08T00:00:00+00:00/personal/2019/08/08/first<p>Hello!
I am Damien and I decided to create my own website.
Why? Because I just want to share my passion of computer science!
Here I will share insights of my research, different kinds of tutorials and tips to enhance your (and my) knowledge on particular subjects, or (sometimes) simply just my opinion.</p>
<p>You can also find me on these social networks:</p>
<ul>
<li><a href="https://www.linkedin.com/in/damienmorard/">LinkedIn</a></li>
<li><a href="https://github.com/damdamo">Github</a></li>
</ul>DamienHello! I am Damien and I decided to create my own website. Why? Because I just want to share my passion of computer science! Here I will share insights of my research, different kinds of tutorials and tips to enhance your (and my) knowledge on particular subjects, or (sometimes) simply just my opinion.