<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le nid de dodo &#187; Théorie</title>
	<atom:link href="https://blog.developpez.com/dodo/pcategory/theorie/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/dodo</link>
	<description></description>
	<lastBuildDate>Sat, 19 Oct 2024 00:29:26 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Le constructeur, au croisement de tous les dangers</title>
		<link>https://blog.developpez.com/dodo/p12675/langage/le-constructeur-au-croisement-de-tous-les-dangers</link>
		<comments>https://blog.developpez.com/dodo/p12675/langage/le-constructeur-au-croisement-de-tous-les-dangers#comments</comments>
		<pubDate>Sun, 20 Jul 2014 09:37:31 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>
		<category><![CDATA[constructeur]]></category>
		<category><![CDATA[dodo]]></category>
		<category><![CDATA[fragile]]></category>
		<category><![CDATA[objet]]></category>
		<category><![CDATA[superclasse]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/dodo/?p=96</guid>
		<description><![CDATA[Les constructeurs sont, en dodo, là où le langage devient impératif. Le constructeur fait habituellement partie du baggage associé à la programmation orientée objet; cependant, ce n’est pas un composant essentiel de celle-ci. Il est tout à fait envisageable de faire de la programmation objet en se contentant de fonctions &#171;&#160;fabrique&#160;&#187; qui produisent des instances de classe en fonction de paramètres définis. Ce qui distingue un constructeur de ces dernières, c’est que le constructeur agit [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Les constructeurs sont, en dodo, là où le langage devient <em>impératif</em>.</p>
<p>Le <em>constructeur</em> fait habituellement partie du baggage associé à la programmation orientée objet; cependant, ce n’est pas un composant essentiel de celle-ci. Il est tout à fait envisageable de faire de la programmation objet en se contentant de <em>fonctions &laquo;&nbsp;fabrique&nbsp;&raquo;</em> qui produisent des instances de classe en fonction de paramètres définis.</p>
<p>Ce qui distingue un constructeur de ces dernières, c’est que le constructeur agit sur une instance déjà allouée de la classe et peut (ou parfois, doit) déléguer partie de l’initialisation de l’objet à la superclasse.</p>
<p>Cette dernière propriété est la source de bien des soucis pour le programmeur orienté objet.</p>
<p>Prenons un exemple:</p>
<div class="codecolorer-container c default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class A<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; make construireA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; self.<span style="color: #202020;">Init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; method Init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; F<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; method F<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Dans cet exemple, le constructeur ne fait finalement rien. Mais une sous-classe peut avoir davantage d’attributs:</p>
<div class="codecolorer-container c default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def B <span style="color: #339933;">=</span> new A is Mutable<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">int</span> x<br />
&nbsp; &nbsp; make construireB<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> x<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Super<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// invoquer construireA</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #202020;">self</span>.<span style="color: #202020;">x</span> <span style="color: #339933;">=</span> x<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; method <span style="color: #339933;">^</span>F<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>x <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LancerOgive<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Dans <em>B</em>, le constructeur de <em>A</em> ne semble plus du tout anodin: puisque <code class="codecolorer text default"><span class="text">x</span></code> n’est pas encore initialisé, il prend la valeur par défaut <strong>0</strong> quand le constructeur de <em>A</em> appelle <em>F()</em>, et la fonction au nom inquiétant <em>LancerOgive()</em> est invoquée!</p>
<p>Même si le développeur prend bien soin que <code class="codecolorer text default"><span class="text">self.x</span></code> ne soit jamais <strong>0</strong> tant qu’il n’y a pas d’attaque en cours contre la sûreté nationale dans les méthodes de <em>B</em>, il est trop tard. Et le pire est qu’il n’a pas forcément de contrôle sur la classe <em>A</em>; l’appel à la méthode <em>F()</em> pourrait avoir été ajouté après que tous les tests du programme soient passés. C’est un problème général des langages orientés objet, dit <em>&laquo;&nbsp;la superclasse fragile&nbsp;&raquo;</em>.</p>
<p>Pour résoudre cela on pourrait interdire au constructeur de <em>B</em> d’appeler le constructeur de <em>A</em> sur <code class="codecolorer text default"><span class="text">self</span></code>, mais il suffirait de remplacer cet appel avec celui de <em>self.Init()</em> pour retomber sur le même problème. En fin de compte, ce qui est important est que la variable <code class="codecolorer text default"><span class="text">x</span></code> soit initialisée avant tout appel aux méthodes de <em>A</em>.</p>
<p>A noter qu’en dodo, il n’est pas toujours possible de provoquer ce problème. Les conditions qui le permettent sont:</p>
<ul>
<li>Le type <em>A</em> est polymorphique (venant de <code class="codecolorer text default"><span class="text">class</span></code>)</li>
<p>Si ce n&rsquo;était pas le cas, la fonction <em>F()</em> appelée dans <em>Init()</em> serait celle de <em>A</em>, puisque <em>Init()</em> n’aurait pas moyen de savoir que <code class="codecolorer text default"><span class="text">self</span></code> est en réalité de type <em>B</em> et non <em>A</em>. Alors <em>LancerOgive()</em> ne serait pas invoquée.</p>
<li>Le type B réutilise le prototype de A (<code class="codecolorer text default"><span class="text">def B</span></code>)</li>
<p>Autrement, <em>B</em> ne pourrait pas invoquer la moindre méthode ou fonction de <em>A</em> sur <code class="codecolorer text default"><span class="text">self</span></code>, puisque la structure des instances de <em>B</em> et de <em>A</em> n’ont potentiellement rien en commun. Cela est permis en dodo, et dans ce cas <em>A</em> est utilisé comme une interface que <em>B</em> implémente à sa façon.</p>
<li>Le constructeur (ou une méthode) de <em>A</em> est invoqué avant que tous les attributs de <em>B</em> ne soient correctement initialisés.</li>
<p>Cela implique que ces attributs n’ont pas une valeur par défaut bien choisie.
</ul>
<p>J’ai mentionné le fait que dodo est un langage impératif par le biais des ses constructeurs. De fait, à l’intérieur d’un constructeur il est permis d’appeler d’autres constructeurs, appeler des méthodes avec effets de bord et aussi affecter de nouvelles valeurs aux attributs de l’objet, même si la classe n’est pas <em>Mutable</em> ou <em>Editable</em> (qui est une extension de Mutable).</p>
<p>Mais appeler des méthodes sur <code class="codecolorer text default"><span class="text">self</span></code>, alors que les attributs de <code class="codecolorer text default"><span class="text">self</span></code> peuvent encore changer, ne semble pas une bonne idée quand l’objet est sensé être constant. Les méthodes en question pourraient être déroutées quand les attributs de l’objet n’ont plus la valeur qu’ils prétendaient avoir. Pour cette raison dodo devrait imposer cette règle: affecter une nouvelle valeur aux attributs de l’objet n’est pas permis après que <code class="codecolorer text default"><span class="text">self</span></code> a été passé à une méthode ou un autre constructeur dans le constructeur de la classe. Cela s’applique uniquement aux objets qui ne sont pas <em>Mutable</em>.</p>
<p>Pour que le danger de la superclasse fragile affecte une classe dodo, il faut donc que la superclasse soit <em>Polymorphic</em>, qu’elle soit modifiée sans préavis, que la classe affectée soit <em>Mutable</em>, réutilise le prototype de la superclasse, n’ait pas de valeur par défaut bien choisie pour ses attributs et fasse appel à des méthodes ou constructeurs de la superclasse avant d&rsquo;être complètement initialisée.</p>
<p>Il n’est pas très difficile de réunir tous ces ingrédients mais il est encore plus facile d&rsquo;éviter le danger.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Type alias</title>
		<link>https://blog.developpez.com/dodo/p10974/langage/type_alias</link>
		<comments>https://blog.developpez.com/dodo/p10974/langage/type_alias#comments</comments>
		<pubDate>Sat, 21 Apr 2012 00:45:53 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il m&#8217;est apparu que dodo a parfois besoin d&#8217;interpréter une valeur de plusieurs façons. Par exemple, une valeur numérique doit pouvoir être interprétée comme une série de bits pour y appliquer des opérations binaires. Cela peut se faire à l&#8217;aide de fonctions de conversion. struct Int32bits is Countable, is Indexed, is Iterable { toInt =&#62; Integ32 } def Integ32 = new Integer(size: 32) { toBits =&#62; Int32bits } Integ32 n = 345 .n = n.toBits [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Il m&rsquo;est apparu que dodo a parfois besoin d&rsquo;interpréter une valeur de plusieurs façons. Par exemple, une valeur numérique doit pouvoir être interprétée comme une série de bits pour y appliquer des opérations binaires. Cela peut se faire à l&rsquo;aide de fonctions de conversion.</p>
<pre>struct Int32bits is Countable, is Indexed, is Iterable
{
   toInt =&gt; Integ32
}

def Integ32 = new Integer(size: 32)
{
   toBits =&gt; Int32bits
}

Integ32 n = 345
.n = n.toBits &lt;&lt; 1   # assigne à n en convertissant avec toInt
</pre>
<p>Cependant, on peut vouloir interpréter la valeur comme une série d&rsquo;octets au lieu de bits. Ou bien vouloir encore d&rsquo;autres interprétations&#8230; La définition du type ne peut pas prévoir toutes les permutations.</p>
<p>De plus, la fonction de conversion peut être difficile à écrire en dodo.</p>
<p>Le langage C offre deux alternatives bien connues pour résoudre cela: la coercion de type et l&rsquo;union. Ce sont deux mécanismes qui sont responsables pour grande partie du caractère dangereux de la programmation C, avec l&rsquo;utilisation des pointeurs.</p>
<p>Il faut noter que Java a aussi la coercion de type (avec des limites) mais pas les pointeurs. Comme Java est généralement considéré sûr, on pourrait juste le copier.</p>
<p>Mais je n&rsquo;aime pas me contenter de l&rsquo;existant <img src="https://blog.developpez.com/dodo/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /><br />
<span id="more-28"></span><br />
Voici quelques idées de travail.</p>
<p>Comme je l&rsquo;ai remarqué entre parenthèses plus haut, la coercion de type en Java est limitée. Il y a des coercions prédéfinies, comme <code class="codecolorer text default"><span class="text">(int) 'A'</span></code> qui convertit un caractère en son code Unicode (entier). Pour cela les fonctions de conversion font bien l&rsquo;affaire.</p>
<p>Il y a aussi les coercions d&rsquo;un type plus générique vers un type spécialisé, notamment pour le type <code class="codecolorer text default"><span class="text">Object</span></code> que l&rsquo;on veut réinterpréter comme un type particulier. C&rsquo;est une coercion dynamique dans le sens que Java vérifie que le type demandé est bien valide en cours d&rsquo;exécution (grâce à la façon dont Java fait le polymorphisme). Si la coercion est invalide on a un <code class="codecolorer text default"><span class="text">ClassCastException</span></code>.</p>
<p>Ce type de coercion ne résout pas le problème que je me posais, qui était, par exemple, de réinterpréter un entier comme une série d&rsquo;octets ou tout autre arrangement qui convient. Pour qu&rsquo;une telle coercion soit valide il faut simplement que le nouveau type occupe la même place en mémoire que l&rsquo;original, ou même moins de place.</p>
<p>Le type union de C semble une bonne solution. De plus, il permet de définir non pas juste deux, mais n&rsquo;importe quel nombre de types qui peuvent occuper le même emplacement mémoire. Le coût est qu&rsquo;il faut une variable pour désigner l&rsquo;union, puis si le type désiré contient plusieurs champs une autre variable dedans pour la structure. On se retrouve avec des constructions très imbriquées.</p>
<p>Je propose de se limiter à juste deux types simultanés. De plus, pour éviter les changements incontrôlés sur une valeur qui est normalement régie par des règles particulières, la valeur originale est copiée avant d&rsquo;être utilisée dans l&rsquo;union. Cette copie peut être retrouvée à l&rsquo;aide d&rsquo;une fonction de conversion. J&rsquo;appelle le type union <code class="codecolorer text default"><span class="text">alias</span></code> et la fonction de conversion <code class="codecolorer text default"><span class="text">unalias</span></code>:</p>
<pre>def n' = alias(n)
{
   byte[4] octets
}

.n'.octets[1] = n'.octets[3]
.n = n'    # conversion avec n'.unalias
</pre>
<p>Le problème est que l&rsquo;on ne veut pas nécessairement exposer la représentation mémoire d&rsquo;un objet, et surtout pas permettre de modifier un pointeur ou un attribut de taille en mémoire! On a déjà vu assez d&rsquo;horreurs en C.</p>
<p>Comment peut-on s&rsquo;assurer que la valeur retournée par <code class="codecolorer text default"><span class="text">alias</span></code> ou par <code class="codecolorer text default"><span class="text">unalias</span></code> est valide? Avez-vous des suggestions?</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La programmation parallèle en dodo &#8211; Partie 3 &#8211; Les tâches et les variables partagées</title>
		<link>https://blog.developpez.com/dodo/p8238/langage/la_programmation_parallele_en_dodo_parti_2</link>
		<comments>https://blog.developpez.com/dodo/p8238/langage/la_programmation_parallele_en_dodo_parti_2#comments</comments>
		<pubDate>Mon, 26 Oct 2009 10:07:53 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le modèle de programmation parallèle basé sur les tâches et la mémoire partagée est le plus répandu aujourd&#8217;hui, on le retrouve en particulier dans Java, C# et C avec OpenMP. Variables partagées Pour utiliser une variable dans plusieurs fonctions en parallèle, il faut la déclarer partagée. De cette façon elle peut être modifiée de façon atomique (sans état intermédiaire) par ces fonctions. Un exemple de déclaration est: Share(&#60;this: Personne&#62;) externe Il faut utiliser le service [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le modèle de programmation parallèle basé sur les tâches et la mémoire partagée est le plus répandu aujourd&rsquo;hui, on le retrouve en particulier dans Java, C# et C avec OpenMP.<br />
<span id="more-19"></span><br />
<strong>Variables partagées</strong></p>
<p>Pour utiliser une variable dans plusieurs fonctions en parallèle, il faut la déclarer partagée. De cette façon elle peut être modifiée de façon atomique (sans état intermédiaire) par ces fonctions. Un exemple de déclaration est:</p>
<pre>Share(&lt;this: Personne&gt;) externe
</pre>
<p>Il faut utiliser le service <code class="codecolorer text default"><span class="text">share</span></code> (voir <a href="http://blog.developpez.com/dodo/p7842/langage/dodo/la-programmation-parallele-en-dodo-parti-1">passage de message</a>) pour modifier la variable, par exemple:</p>
<pre>.share!externe = inspecteur
share!externe.Visite(site)
</pre>
<p>Il faut comprendre cela comme si le programme envoie des commandes à la variable partagée, en fait il n&rsquo;attend pas que l&rsquo;opération soit effectuée (ou cause une erreur).</p>
<p>L&rsquo;envoi de commande peut produire un ou plusieurs résultats. Ces résultats deviennent disponibles au plus tard quand la méthode correspondante termine. D&rsquo;ici là l&rsquo;accès aux résultats est une opération bloquante.</p>
<p>Si une commande fait intervenir plusieurs variables dont la valeur n&rsquo;est pas encore connue, elle commence à être évaluée seulement après que la valeur pour chacune d&rsquo;elles est renseignée (progression en tout ou rien).</p>
<p>Les attributs de la variable partagée peuvent être accédés comme une variable normale. Si la variable a plusieurs états possibles, et son état courant ne donne pas accès à l&rsquo;attribut en question, alors la tâche courante bloque en attendant que la variable change d&rsquo;état.</p>
<p>Par exemple:</p>
<pre>def Inspecteur = new Personne
{
   __state incognito =&gt;
      # On ne révèle rien ici

   __state officiel =&gt;
      Matricule matricule
}
...
.share!externe = Inspecteur()
...
Matricule m = externe.matricule
</pre>
<p>La tâche courante bloque jusqu&rsquo;à ce que l&rsquo;inspecteur sorte de son incognito et devienne officiel. Pour une variable normale, on obtiendrait immédiatement une erreur.</p>
<p>Le service <code class="codecolorer text default"><span class="text">share</span></code> garantit que les opérations qu&rsquo;il gère s&rsquo;exécutent dans l&rsquo;ordre où elles apparaissent dans le programme (ordre séquentiel) pour une tâche donnée.</p>
<p><strong>Le bloc fork</strong></p>
<p>Si l&rsquo;on veut poursuivre d&rsquo;autres tâches en attendant qu&rsquo;une variable soit renseignée, il faut mettre l&rsquo;opération bloquante dans un bloc <code class="codecolorer text default"><span class="text">sync</span></code> ou <code class="codecolorer text default"><span class="text">fork</span></code> (les instructions d&rsquo;un <code class="codecolorer text default"><span class="text">fork</span></code> sont comprises dans un block <code class="codecolorer text default"><span class="text">sync</span></code> implicite):</p>
<pre>fork
{
   Matricule m = externe.matricule
   # utilise m...
}
# reste des opérations...
</pre>
<p>Cela permet en particulier de créer des gestionnaires d&rsquo;événement, dans le cas ci-dessus pour le changement d&rsquo;état de l&rsquo;inspecteur. Notez qu&rsquo;un bloc <code class="codecolorer text default"><span class="text">fork</span></code> ne commence à s&rsquo;exécuter que lorsque toutes les variables qu&rsquo;il utilise sont renseignées. Si l&rsquo;on ne veut pas attendre d&rsquo;avoir une valeur pour une variable particulière, il faut utiliser un bloc <code class="codecolorer text default"><span class="text">fork</span></code> (ou <code class="codecolorer text default"><span class="text">sync</span></code>) imbriqué. Par exemple:</p>
<pre>def _approuvé = share!principal.Approuve("Vérification du matricule inspecteur")
fork
{
   Matricule m = externe.matricule
   case:
      registre.contains(m) =&gt;
         def data = registre[m]
         # utilise data...
      else =&gt;
         fork: # Regarder si vérif approuvée ici seulement
            case if (_approuvé)
            {
               # Pas sur le registre! Faire quelque chose...
            }
         .
      }
   .
}
</pre>
<p>On peut écrire un gestionnaire d&rsquo;événements multiples avec la forme spéciale <code class="codecolorer text default"><span class="text">fork select</span></code>, qui s&rsquo;apparente à un bloc <code class="codecolorer text default"><span class="text">case</span></code> où les instructions correspondantes s&rsquo;exécutent dans un <code class="codecolorer text default"><span class="text">fork</span></code> quand la condition (garde) devient vraie. Le bloc <code class="codecolorer text default"><span class="text">fork select</span></code> continue de s&rsquo;exécuter jusqu&rsquo;à ce que le système devienne stable, c&rsquo;est-à-dire que toutes les variables ont une valeur connue.</p>
<p>La variable qui signale la fin du programme est <code class="codecolorer text default"><span class="text">runtime.process.exit</span></code>. Si celle-ci est utilisée comme garde d&rsquo;un <code class="codecolorer text default"><span class="text">fork select</span></code>, le gestionnaire d&rsquo;événements s&rsquo;exécute jusqu&rsquo;à la fin du programme.</p>
<p><a href="/dodo/p7793/langage/dodo/la-programmation-parallele-en-dodo-parti/">Partie 1 &#8211; Présentation</a><br />
<a href="/dodo/p7842/langage/dodo/la-programmation-parallele-en-dodo-parti-1/">Partie 2 &#8211; Le passage de messages</a><br />
<a href="/dodo/p8395/langage/dodo/la-programmation-parallele-en-dodo-parti-3/">Partie 4 &#8211; Les transactions</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La programmation parallèle en dodo &#8211; Partie 4 &#8211; Les transactions</title>
		<link>https://blog.developpez.com/dodo/p8395/langage/la_programmation_parallele_en_dodo_parti_3</link>
		<comments>https://blog.developpez.com/dodo/p8395/langage/la_programmation_parallele_en_dodo_parti_3#comments</comments>
		<pubDate>Tue, 24 Nov 2009 11:24:47 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le concept de transaction est bien connu des utilisateurs de base de données, où il sert à grouper des opérations pour permettre l&#8217;accès concurrent et consistant aux données de la base. La programmation parallèle peut faire appel à la notion de transaction pour manipuler les variables partagées. Le principal intérêt de ce modèle est la simplicité d&#8217;utilisation et une efficacité meilleure que d&#8217;autres modèles comparables. Les transactions Une transaction en dodo est délimitée par un [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le concept de transaction est bien connu des utilisateurs de base de données, où il sert à grouper des opérations pour permettre l&rsquo;accès concurrent et consistant aux données de la base.</p>
<p>La programmation parallèle peut faire appel à la notion de transaction pour manipuler les variables partagées. Le principal intérêt de ce modèle est la simplicité d&rsquo;utilisation et une efficacité meilleure que d&rsquo;autres modèles comparables.</p>
<p><span id="more-20"></span></p>
<ol>
<li><strong>Les transactions</strong></p>
<p>Une transaction en dodo est délimitée par un bloc <code class="codecolorer text default"><span class="text">sync</span></code> qui contient les instructions qui font partie de la transaction. Ces instructions sont exécutées comme si il n&rsquo;y avait pas de parallélisme et nulle autre tâche n&rsquo;interfère avec son exécution.</p>
<p>En réalité ce n&rsquo;est pas tout à fait vrai, par défaut dodo triche pour éviter le rollback des transactions. En effet si le système détecte qu&rsquo;une transaction ne peut pas être complétée &laquo;&nbsp;comme si nulle autre tâche n&rsquo;interfère&nbsp;&raquo;, pour bien faire il faut annuler tout ce que la transaction a fait jusqu&rsquo;ici et recommencer du début! C&rsquo;est ce qu&rsquo;on appelle un rollback.</p>
<p>Nous verrons plus tard comment changer les options pour autoriser à nouveau les rollbacks et se conformer au principe d&rsquo;isolation. Voyons maintenant un exemple de bloc <code class="codecolorer text default"><span class="text">sync</span></code>:</p>
<pre>
sync
{
   .a = a + b
}
</pre>
<p>Pourquoi veut-on créer une transaction juste pour ajouter deux variables?</p>
<p> Eh bien si on y pense, il se pourrait qu&rsquo;une autre tâche intervienne entre le moment où les variables sont lues et le moment où <code class="codecolorer text default"><span class="text">a</span></code> est mise à jour, ce qui fait que la valeur finale ne sera pas vraiment <code class="codecolorer text default"><span class="text">a + b</span></code>. L&rsquo;utilisation d&rsquo;une transaction permet de protéger le bloc de code des influences extérieures.
</p>
<p>Pour prendre en compte la possibilité de rollback, il convient d&rsquo;indiquer à dodo comment annuler les changements déjà faits. Si par exemple f(a) cause un rollback on peut écrire:</p>
<pre>
sync
{
   .a = a + b ...&gt; __undo .a = a - b
   f(a)
}
</pre>
<p><em>Note:</em> Les instructions précédées de <code class="codecolorer text default"><span class="text">__undo</span></code> sont aussi exécutées en cas d&rsquo;exception, sauf si le gestionnaire d&rsquo;événements convertit l&rsquo;exception en <code class="codecolorer text default"><span class="text">return</span></code>. Un bloc <code class="codecolorer text default"><span class="text">sync</span></code> définit son propre gestionnaire d&rsquo;événements.</p>
</li>
<li><strong>Les variables versionnées</strong>
<p>Les variables partagées ordinaires ne sont pas de grande utilité dans le cadre des transactions, car leurs modifications sont généralement problématiques à annuler en cas de rollback. C&rsquo;est pourquoi on fait appel aux variables versionnées. Les modifications d&rsquo;une variable versionnée sont automatiquement annulées en cas de rollback.</p>
<p>Une variable versionnée a une partie commune, partagée entre toutes les tâches, et une partie locale qui est utilisée dans le cadre d&rsquo;une transaction. Quand la variable est lue dans une transaction, la partie partagée est copiée dans la partie locale ainsi que son numéro de version. C&rsquo;est ce qui permet à sa valeur de rester consistante tout au long de la transaction, même si une autre tâche intervient.</p>
<p>Quand la transaction a copié la valeur partagée de la variable dans sa partie locale, la variable est dans l&rsquo;état <code class="codecolorer text default"><span class="text">synchronized</span></code>.</p>
</li>
<li><strong>Les options de synchronisation</strong>
<p>Par défaut, dodo garantit que la transaction a une vue cohérente des données: il existe un moment dans le temps où toutes les variables de la transaction ont la valeur que la transaction a lue. C&rsquo;est la seule garantie des options par défaut (<code class="codecolorer text default"><span class="text">use: newest</span></code>). Pour l&rsquo;exemple précédent, si <code class="codecolorer text default"><span class="text">a</span></code> vaut <code class="codecolorer text default"><span class="text">0</span></code> et <code class="codecolorer text default"><span class="text">b</span></code> vaut <code class="codecolorer text default"><span class="text">3</span></code> au départ, et il y a trois tâches qui exécutent la transaction en parallèle, la valeur finale de <code class="codecolorer text default"><span class="text">a</span></code> peut être <code class="codecolorer text default"><span class="text">9, 6</span></code> ou bien <code class="codecolorer text default"><span class="text">3</span></code>. Il se peut même qu&rsquo;elle aille de <code class="codecolorer text default"><span class="text">6</span></code> à <code class="codecolorer text default"><span class="text">3</span></code> (inversion temporelle).</p>
<blockquote><p>Exemples d&rsquo;exécution<br />
<em>Valeur lue par la troisième tâche en <ins>vert</ins>, valeur écrite par la troisième tâche en <strong>gras</strong><br />
</em><br />
temps &#8212;&#8211;&gt;<br />
<strong>a</strong>: 0 , 3 , <ins>6</ins> , <strong>9</strong><br />
temps &#8212;&#8211;&gt;<br />
<strong>a</strong>: 0 , <ins>3 </ins>, 6 , <strong>6</strong><br />
temps &#8212;&#8211;&gt;<br />
<strong>a</strong>: <ins>0</ins> , 3 , 6 , <strong>3</strong>
</p></blockquote>
<p>Si l&rsquo;on veut assurer la consistence temporelle, et s&rsquo;assurer que la variable a des valeurs qui se suivent de façon logique dans le temps, on peut choisir l&rsquo;option suivante:</p>
<pre>
__handle (use: first)
</pre>
<p>Cela indique à dodo que la valeur ne devrait pas être remplacée si la version utilisée par la transaction n&rsquo;est plus celle que contient la variable partagée. Une fois encore, cette option ne cause pas de rollbacks.</p>
<p>Cependant, avec ceci il se peut qu&rsquo;une variable soit mise à jour alors qu&rsquo;une autre ne l&rsquo;est pas &#8212; la transaction n&rsquo;assure pas vraiment la cohérence des données mises à jour. C&rsquo;est pourquoi dodo ne garantit pas une vue cohérente des données avec cette option.</p>
<blockquote><p>
<em>Effet de l&rsquo;option </em>use: first<em> sur les conflits de version avec une transaction parallèle (en <ins>vert</ins>)</em></p>
<pre>
sync
{
   .a *= b
   ++.b
}

Val. lue/écrite     a  b  |  a  b  |  a  b
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -
Début transaction   3  2  |  3  2  |  3  2  
Fin transaction     <ins>5</ins>  2  |  3  <ins>4</ins>  |  3  2
Valeur locale       <ins>6</ins>  3  |  6  <ins>3</ins>  |  6  3
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -
<strong>Valeur partagée     5  3  |  6  4  |  6  3</strong>
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -
</pre>
</blockquote>
<p>Pour obtenir davantage de garanties il faut autoriser les rollbacks. Le premier exemple de transaction avec rollback est avec les options:</p>
<pre>
__handle (use: newest, action: fail)
</pre>
<p>Ces options sont similaires aux options par défaut, mais si dodo détecte une inversion temporelle les opérations sont annulées et la transaction s&rsquo;exécute à nouveau. Dans les exemples d&rsquo;exécution précédents le dernier ne serait pas possible.</p>
<p>Finalement, ces options apportent toutes les garanties que l&rsquo;on peut attendre d&rsquo;une transaction:</p>
<pre>
__handle (use: first, action: fail)
</pre>
<p>Cela indique à dodo que la transaction doit être réexécutée si la version utilisée par la transaction n&rsquo;est plus celle que contient la variable partagée quand elle est mise à jour. De plus ces options assurent une vue cohérente des données. Dès lors la seule exécution possible est:</p>
<blockquote><p><strong>a</strong>: 0 3 <ins>6</ins> <strong>9</strong></p></blockquote>
<p>Les options de synchronisation peuvent s&rsquo;appliquer à une variable particulière avec la notation <code class="codecolorer text default"><span class="text">__handle variable</span></code>.</p>
</li>
<li><strong>Bloc <code class="codecolorer text default"><span class="text">sync</span></code> conditionnel</strong>
<p>Le bloc <code class="codecolorer text default"><span class="text">sync</span></code> conditionnel s&rsquo;écrit:</p>
<pre>
sync select
{
   condition1 =&gt;
      ...transaction1...
   condition2 =&gt;
      ...transaction2...
   ...
}
</pre>
<p>Les variables utilisées dans la condition font partie de la transaction. Si les conditions sont réunies mais par la suite, la transaction sélectionnée fait un rollback, alors dodo teste les conditions de la transaction suivante. Si nulle transaction n&rsquo;a de succès, alors le bloc <code class="codecolorer text default"><span class="text">sync</span></code> entier fait un rollback. Une erreur est signalée si aucune transaction n&rsquo;a été tentée dans un bloc <code class="codecolorer text default"><span class="text">sync</span></code> conditionnel.</p>
<p>La condition spéciale <code class="codecolorer text default"><span class="text">default</span></code> indique qu&rsquo;aucune autre condition n&rsquo;est remplie; de fait, la condition <code class="codecolorer text default"><span class="text">default</span></code> n&rsquo;est pas remplie si l&rsquo;exécution d&rsquo;une autre transaction a été tentée mais s&rsquo;est soldée par un rollback. L&rsquo;utilisation de <code class="codecolorer text default"><span class="text">default</span></code> permet d&rsquo;assurer qu&rsquo;au moins une transaction est tentée.</p>
</li>
<li><strong>Transaction à l&rsquo;intérieur d&rsquo;une transaction</strong>
<p>Si le bloc <code class="codecolorer text default"><span class="text">sync</span></code> se trouve à l&rsquo;intérieur d&rsquo;un autre bloc <code class="codecolorer text default"><span class="text">sync</span></code>, cela définit une sous-transaction. Les changements faits dans la sous-transaction ne sont effectifs que quand la transaction englobante termine avec succès. En cas de rollback de la sous-transaction, la transaction englobante fait aussi l&rsquo;objet d&rsquo;un rollback. Le reste dépend des options de synchronisation.</p>
<p>Avec les options de synchronisation par défaut (<code class="codecolorer text default"><span class="text">use: newest</span></code>), dodo assure une vue cohérente des données de la sous-transaction à un moment dans le temps. Mais celle-ci peut différer de la vue de la transaction englobante.</p>
<p>Avec l&rsquo;option de consistance temporelle (<code class="codecolorer text default"><span class="text">use: first</span></code>), la vue de la transaction englobante est réutilisée.</p>
<p>Si les rollbacks sont autorisés en cas d&rsquo;inversion temporelle (<code class="codecolorer text default"><span class="text">use: first, action: fail</span></code>), l&rsquo;inversion temporelle est détectée quand une variable est lue ou mise à jour dans la sous-transaction.</p>
<p>Finalement avec toutes les garanties en place (<code class="codecolorer text default"><span class="text">use: first, action: fail</span></code>), la vue de la transaction englobante est réutilisée. La version des variables de la sous-transaction est testée quand elles sont mises à jour.</p>
<p><em>Note:</em> Une variable versionnée est synchronisée avant d&rsquo;être passée en paramètre à une fonction contenant potentiellement une transaction.</p>
</li>
</ol>
<p>Les blocs <code class="codecolorer text default"><span class="text">sync</span></code> conditionnels et emboîtés permettent la composition de transactions.</p>
<p><a href="/dodo/p7793/langage/dodo/la-programmation-parallele-en-dodo-parti/">Partie 1 &#8211; Présentation</a><br />
<a href="/dodo/p7842/langage/dodo/la-programmation-parallele-en-dodo-parti-1/">Partie 2 &#8211; Le passage de messages</a><br />
<a href="/dodo/p8238/langage/dodo/la-programmation-parallele-en-dodo-parti-2/">Partie 3 &#8211; Les tâches et les variables partagées</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monsieur Curry</title>
		<link>https://blog.developpez.com/dodo/p9340/technique/monsieur_curry</link>
		<comments>https://blog.developpez.com/dodo/p9340/technique/monsieur_curry#comments</comments>
		<pubDate>Fri, 01 Oct 2010 22:45:19 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Technique]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Mr Haskell Curry est un logicien qui a donné son nom à une technique utilisée en programmation fonctionnelle, le currying. Celle-ci a pour origine les travaux de Gottlob Frege et Moses Schönfinkel, ce qui a poussé Christopher Strachey à suggérer le nom de schönfikelisation en tant qu&#8217;alternative. Ne nous attardons pas plus longtemps sur les détails triviaux. Voyons ce que le terme signifie en informatique. Le currying transforme une fonction qui s&#8217;applique à une liste [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Mr Haskell Curry est un logicien qui a donné son nom à une technique utilisée en programmation fonctionnelle, le <em>currying</em>. Celle-ci a pour origine les travaux de Gottlob Frege et Moses Schönfinkel, ce qui a poussé Christopher Strachey à suggérer le nom de <em>schönfikelisation</em> en tant qu&rsquo;alternative.</p>
<p>Ne nous attardons pas plus longtemps sur les détails triviaux. Voyons ce que le terme signifie en informatique.<br />
<span id="more-26"></span><br />
Le currying transforme une fonction qui s&rsquo;applique à une liste de paramètres:</p>
<pre>f(x, y, z)
</pre>
<p>en une fonction qui s&rsquo;applique à un seul paramètre, qui retourne une autre fonction à un paramètre, etc jusqu&rsquo;à consommer tous les paramètres.</p>
<pre>f(x) -> f'(y) -> f''(z)
</pre>
<p>En dodo cette transformation se fait en remplaçant les paramètres de la fonction avec des caractères de soulignement _.</p>
<pre>def g = f(_, _, _)
</pre>
<p>On peut appeler cette fonction avec trois paramètres de la façon suivante:</p>
<pre>g(1)(3)(n) 	# = f(1, 3, n)
</pre>
<p>Quel est l&rsquo;avantage de faire cela? Et bien cela permet d&rsquo;appeler <code class="codecolorer text default"><span class="text">g</span></code> avec un seul ou deux paramètres, et réutiliser la fonction résultante comme une fonction ordinaire. Dans un langage qui n&rsquo;utilise que les fonctions curriées cela donne des propriétés intéressantes.</p>
<p>Dodo n&rsquo;est pas un tel langage mais l&rsquo;option est là.<br />
Une autre utilisation du caractère de soulignement est d&rsquo;appeler une fonction avec des paramètres renseignés à l&rsquo;avance, par exemple:</p>
<pre>def normalise = min(_, 100)
.x = normalise(x)	# contraint x à être inférieur ou égal à 100
</pre>
<p>Cela peut aussi servir à composer des fonctions:</p>
<pre>def positive_sinus = abs(_) &#038; sin(_)
positive_sinus(-0.5)	# = sin(abs(-0.5))
</pre>
<p>Ici &laquo;&nbsp;<code class="codecolorer text default"><span class="text">&amp;</span></code>&nbsp;&raquo; sert à combiner les deux fonctions en une nouvelle fonction, qui les applique dans l&rsquo;ordre à l&rsquo;argument. Cela ne marche pas avec les fonctions ordinaires, il faut utiliser _.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>La programmation parallèle en dodo &#8211; Partie 1 &#8211; Présentation</title>
		<link>https://blog.developpez.com/dodo/p7793/langage/la_programmation_parallele_en_dodo_parti</link>
		<comments>https://blog.developpez.com/dodo/p7793/langage/la_programmation_parallele_en_dodo_parti#comments</comments>
		<pubDate>Thu, 25 Jun 2009 00:17:09 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour être reconnu aujourd’hui, un nouveau langage se doit d’apporter des nouveautés dans le domaine de la programmation. Certains se distinguent en visant la facilité d’utilisation, ou en étant spécialisé pour une application précise. Mais ce à quoi tout le monde s’intéresse, c’est le parallélisme. En effet, les ordinateurs de bureau ont maintenant en général deux processeurs à leur coeur, voire plus. Pour bénéficier au maximum des avantages de ces processeurs il faut recourir à [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour être reconnu aujourd’hui, un nouveau langage se doit d’apporter des nouveautés dans le domaine de la programmation. Certains se distinguent en visant la facilité d’utilisation, ou en étant spécialisé pour une application précise. Mais ce à quoi tout le monde s’intéresse, c’est le parallélisme.<br />
<span id="more-16"></span><br />
En effet, les ordinateurs de bureau ont maintenant en général deux processeurs à leur coeur, voire plus. Pour bénéficier au maximum des avantages de ces processeurs il faut recourir à la programmation parallèle.</p>
<p>Les langages généralistes les plus répandus comme C, C++, Java, Visual Basic ou C# utilisent le modèle des tâches d’exécution (threads) avec mémoire partagée comme base du parallélisme. Ce modèle est en bonne adéquation avec le fonctionnement des processeurs. De plus, ces langages proposent (sous forme de bibliothèque) des outils pour le passage de messages entre processus. Cela peut aussi être utilisé pour la communication entre tâches à l’intérieur d’un même processus.</p>
<p>Le problème de la mémoire partagée c’est qu’elle induit des difficultés pratiquement insolubles aux programmeurs qui veulent l’exploiter. Il y a de bonnes chances de créer des situations ou la performance chute, ou bien deux tâches s’attendent indéfiniment l’une l’autre à cause de verrous mis en place pour protéger l’intégrité de la mémoire partagée. Pour y remédier on a inventé des mécanismes sans verrou, qui ont leurs propres problèmes et ne peuvent être utilisés partout.</p>
<p>Pour dodo j’ai préféré privilégier un autre modèle, celui du passage de messages. Il est toujours possible d’avoir deux tâches qui s’attendent indéfiniment (deadlock) mais ce modèle a la réputation d’être plus facile à utiliser et de causer moins de soucis aux programmeurs.</p>
<p>J’ai aussi prévu d’intégrer un modèle de mémoire partagée qui a l’avantage de détecter les situations de blocage, celui proposé par le projet Athapascan du <a href="http://www-id.imag.fr/">laboratoire ID-Imag</a>. Chaque modèle a ses avantages et je pense que dodo peut bénéficier de la combinaison de ces deux approches.</p>
<p>Je parlerai aussi des variables versionnées et des transactions, des concepts importants pour les applications concurrentes.</p>
<p><a href="/dodo/p7842/langage/dodo/la-programmation-parallele-en-dodo-parti-1/">Partie 2 &#8211; Le passage de messages</a><br />
<a href="/dodo/p8238/langage/dodo/la-programmation-parallele-en-dodo-parti-2/">Partie 3 &#8211; Les tâches et les variables partagées</a><br />
<a href="/dodo/p8395/langage/dodo/la-programmation-parallele-en-dodo-parti-3/">Partie 4 &#8211; Les transactions</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>D&#8217;une valeur de vérité considérée comme un ensemble</title>
		<link>https://blog.developpez.com/dodo/p9271/theorie/d_une_valeur_de_verite_consideree_comme</link>
		<comments>https://blog.developpez.com/dodo/p9271/theorie/d_une_valeur_de_verite_consideree_comme#comments</comments>
		<pubDate>Thu, 09 Sep 2010 21:17:47 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Une valeur de vérité (booléen) peut prendre deux valeurs en logique, soit vrai soit faux. En fait la logique s&#8217;étend à des ensembles de valeurs plus grand mais on ne s&#8217;intéresse qu&#8217;à ces deux-là ici. Dès lors, on peut considérer une valeur de vérité comme un ensemble de taille maximale un. L&#8217;ensemble vide [] signifie faux et l&#8217;ensemble avec un élément [v] signifie vrai. Il est aisé de relier les opérations sur les ensembles aux [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Une valeur de vérité (booléen) peut prendre deux valeurs en logique, soit vrai soit faux. En fait la logique s&rsquo;étend à des ensembles de valeurs plus grand mais on ne s&rsquo;intéresse qu&rsquo;à ces deux-là ici.</p>
<p>Dès lors, on peut considérer une valeur de vérité comme un ensemble de taille maximale un.<br />
<span id="more-12"></span><br />
L&rsquo;ensemble vide [] signifie faux et l&rsquo;ensemble avec un élément [v] signifie vrai. Il est aisé de relier les opérations sur les ensembles aux opérations booléennes:</p>
<p><strong>Union</strong> (conjonction <strong>OU</strong>)</p>
<p><em>quel que soit E:</em> E <em>union</em> E = E<br />
[] <em>union</em> [v] = [v]<br />
[v] <em>union</em> [] = [v]</p>
<p>Table de vérité:</p>
<pre> a   b | a <em>OU</em> b
_______|_____
 0   0 |  0
 0   1 |  1
 1   0 |  1
 1   1 |  1
</pre>
<p><strong>Intersection</strong> (disjonction <strong>ET</strong>)</p>
<p><em>quel que soit E:</em> E <em>intersection</em> E = E<br />
[] <em>intersection</em> [v] = []<br />
[v] <em>intersection</em> [] = []</p>
<p>Table de vérité:</p>
<pre> a   b | a <em>ET</em> b
_______|_____
 0   0 |  0
 0   1 |  0
 1   0 |  0
 1   1 |  1
</pre>
<p><strong>Complément</strong> (négation <strong>NON</strong>)</p>
<p><em>complément</em> [] = [v]<br />
<em>complément</em> [v] = []</p>
<p>Table de vérité:</p>
<pre> a | <em>NON</em> a
___|_____
 0 |  1
 1 |  0
</pre>
<p><strong>Différence symétrique</strong> (disjonction exclusive <strong>XOR</strong>)</p>
<p><em>quel que soit E:</em> E <em>différence symétrique</em> E = []<br />
[] <em>différence symétrique</em> [v] = [v]<br />
[v] <em>différence symétrique</em> [] = [v]</p>
<p>Table de vérité:</p>
<pre> a   b | a <em>XOR</em> b
_______|_____
 0   0 |  0
 0   1 |  1
 1   0 |  1
 1   1 |  0
</pre>
<p>On voit que les relations sont les mêmes pour les valeurs ensemblistes [], [v] et les valeurs de vérité 0, 1.</p>
<p>Dans dodo, <code class="codecolorer text default"><span class="text">qualifier Logic</span></code> apporte les opérations <code class="codecolorer text default"><span class="text">||</span></code> (OU/union), <code class="codecolorer text default"><span class="text">&amp;&amp;</span></code> (ET/intersection), <code class="codecolorer text default"><span class="text">!</span></code> (NON/complément) et <code class="codecolorer text default"><span class="text">^^</span></code> (XOR/différence symétrique). Il s&rsquo;applique à la fois aux booléens, aux intervalles et aux ensembles.</p>
<p>Une représentation efficace d&rsquo;un ensemble dont l&rsquo;ensemble d&rsquo;éléments possibles est limité est un entier. Chaque bit de l&rsquo;entier correspond à un élément possible. Si le bit vaut 1 l&rsquo;élément est présent mais s&rsquo;il vaut 0 l&rsquo;élément est absent.</p>
<p>Dans le cas du booléen considéré comme un ensemble décrit ci-dessus, l&rsquo;ensemble des éléments possibles se limite à un seul: v. Il suffit donc d&rsquo;un bit pour représenter le booléen.</p>
<p>En utilisant le bit le moins significatif, on obtient la représentation suivante:</p>
<p>[] = 0x0000 = 0<br />
[v] = 0x0001 = 1</p>
<p>Si bien que faux vaut <strong>0</strong>, et vrai vaut <strong>1</strong>! Si vous êtes familier avec C ou un autre langage qui a repris la même convention cela ne devrait pas vous surprendre. De fait c&rsquo;est une notation largement acceptée en logique.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Langage minimal pour dodo</title>
		<link>https://blog.developpez.com/dodo/p7976/langage/langage_minimal_pour_dodo</link>
		<comments>https://blog.developpez.com/dodo/p7976/langage/langage_minimal_pour_dodo#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:57:28 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si je voulais choisir une liste d&#8217;éléments du langage, de façon à pouvoir définir le reste du langage en ses termes, que devrais-je inclure dedans? Que serait un langage minimal pour dodo? Comme dodo est un langage à prototypes, il nous faut l&#8217;opérateur new qui crée une nouvelle instance d&#8217;un objet basée sur un prototype. Puisque dodo est basé sur les continuations, il est évident que ce serait une première chose à inclure dans dodo [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Si je voulais choisir une liste d&rsquo;éléments du langage, de façon à pouvoir définir le reste du langage en ses termes, que devrais-je inclure dedans? Que serait un langage minimal pour dodo?<br />
<span id="more-18"></span><br />
Comme dodo est un langage à prototypes, il nous faut l&rsquo;opérateur <code class="codecolorer text default"><span class="text">new</span></code> qui crée une nouvelle instance d&rsquo;un objet basée sur un prototype.</p>
<p>Puisque dodo est basé sur les continuations, il est évident que ce serait une première chose à inclure dans dodo minimal.</p>
<p>Pour rappel, une continuation est un point du programme que l&rsquo;ordinateur peut exécuter, en lui passant les données appropriées. Une continuation n&rsquo;a pas de notion de &laquo;&nbsp;retour&nbsp;&raquo; ce qui la différencie d&rsquo;une fonction. Mais si l&rsquo;une des données passées est elle-même une continuation qui représente le reste du programme, on peut l&rsquo;utiliser comme une fonction. C&rsquo;est le principe de base de dodo.</p>
<p>Puisqu&rsquo;il suffit d&rsquo;avoir la définition d&rsquo;une continuation dans le langage pour ouvrir la porte aux fonctions le dodo minimal devrait la posséder. Comme je l&rsquo;ai discuté par ailleurs, cela ne sera pas accessible dans le langage dodo normal.</p>
<p>Voici comment cela pourrait apparaître dans dodo minimal:</p>
<pre>
(-> x, return
return(x))
</pre>
<p>Le code ci-dessus définit une continuation qui prend une valeur, x, et une continuation return. Elle est l&rsquo;équivalent d&rsquo;une fonction qui retourne simplement x (fonction identité).</p>
<p>L&rsquo;utilisation d&rsquo;une continuation est déjà décrite dans la <a href="http://dodo.sourceforge.net">documentation du langage</a> et fait appel aux opérateurs <code class="codecolorer text default"><span class="text">-&gt;</span></code> et <code class="codecolorer text default"><span class="text">|</span></code>.</p>
<p>Un autre élément indispensable est celui qui permet le branchement, c&rsquo;est-à-dire le choix des instructions à exécuter en fonction d&rsquo;une condition. C&rsquo;est l&rsquo;opérateur <code class="codecolorer text default"><span class="text">match</span></code> de dodo.</p>
<p>Pour permettre l&rsquo;extension du langage, il faudra aussi <code class="codecolorer text default"><span class="text">&lt;wrap&gt;</span></code> et <code class="codecolorer text default"><span class="text">template</span></code> comme décrit dans un <a href="http://blog.developpez.com/dodo/p7459/langage/introduction-de-macros-avancees/">précédent article</a>.</p>
<p>Cela ne serait pas suffisant pour définir le langage dodo complet; en particulier, il faudrait ajouter le chargement des classes, les constructeurs, les références (opérateur <code class="codecolorer text default"><span class="text">.</span></code>) pour la partie objet impérative, et d&rsquo;autres opérateurs pour la partie programmation parallèle.</p>
<p>Mais ces simples éléments pourraient déjà servir de base à une large partie de dodo.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction de macros avancées</title>
		<link>https://blog.developpez.com/dodo/p7459/langage/introduction_de_macros_avancees</link>
		<comments>https://blog.developpez.com/dodo/p7459/langage/introduction_de_macros_avancees#comments</comments>
		<pubDate>Tue, 07 Apr 2009 20:17:31 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je me demandais à quoi pourrait ressembler un système de macro avancé pour dodo. Il se trouve que dodo a déjà deux mécanismes qui pourraient être réutilisés: les intercepteurs d&#8217;appel (wrap) et les templates. Voici un exemple de ce que l&#8217;on pourrait faire avec s&#8217;ils étaient utilisés pour les macros. Le but de cet exemple est de transformer une forme impérative (boucle while) en une forme à continuations. Par exemple, je veux transformer: loop while [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Je me demandais à quoi pourrait ressembler un système de macro avancé pour dodo.</p>
<p>Il se trouve que dodo a déjà deux mécanismes qui pourraient être réutilisés: les intercepteurs d&rsquo;appel (wrap) et les templates. Voici un exemple de ce que l&rsquo;on pourrait faire avec s&rsquo;ils étaient utilisés pour les macros.<br />
<span id="more-1"></span><br />
Le but de cet exemple est de transformer une forme impérative (boucle while) en une forme à continuations.</p>
<p>Par exemple, je veux transformer:</p>
<pre>loop while (x > 2.0)
{
   .x = (x + e) * k
}</pre>
<p>en:</p>
<pre>fun: x -> ret(double)
   if (x > 2.0)
      (x + e) * k -> x
      $loop1(x)
   else
      ret(x)
.
-> loop1
loop1(x)
</pre>
<p>Ce code est l&rsquo;équivalent de la boucle while en CPS.</p>
<p>Ma proposition utilise <code class="codecolorer text default"><span class="text">wrap</span></code> pour définir la syntaxe de la boucle while et les actions associées, et <code class="codecolorer text default"><span class="text">template</span></code> pour transformer la syntaxe.</p>
<p>Commençons notre exemple. D&rsquo;abord on va définir une expression régulière qui correspond à la syntaxe de la boucle while:</p>
<pre>/loop while
\(\n $cond\n \)(
{\n $body\n } | :\n $body\n \.[ \n])/
</pre>
<p>Dans l&rsquo;expression régulière, j&rsquo;utilise un espace pour dénoter que l&rsquo;on peut mettre des espaces ou tabulations, et un saut de ligne ou \n pour indiquer que l&rsquo;on peut mettre des espaces, tabulations ou sauts de lignes. Soit <code class="codecolorer text default"><span class="text">[ \t]*</span></code> et <code class="codecolorer text default"><span class="text">[ \t\n\r]*</span></code> respectivement.</p>
<p>Les syntaxes acceptées sont<br />
<code class="codecolorer text default"><span class="text">loop while (cond) {body}</span></code><br />
et<br />
<code class="codecolorer text default"><span class="text">loop while (cond): body.</span></code></p>
<p>Quand le compilateur rencontre cette syntaxe, les variables <code class="codecolorer text default"><span class="text">cond</span></code> et <code class="codecolorer text default"><span class="text">body</span></code> prennent une valeur et une action est exécutée. Je définis un template <code class="codecolorer text default"><span class="text">loop_while</span></code> qui est l&rsquo;action utilisée pour transformer la syntaxe. Son invocation sera:</p>
<pre>   loop_while(
      use (body.inVars + cond.inVars) * body.outVars,
      set body.outVars,
      while cond,
      do body)
</pre>
<p>Les paramètres de <code class="codecolorer text default"><span class="text">loop_while</span></code> sont:</p>
<ul>
<li><code class="codecolorer text default"><span class="text">use</span></code> les variables d&rsquo;entrée de la boucle. Ce sont les variables utilisées par le corps et les variables utilisées par la condition qui sont aussi modifiées par le corps de la boucle.</li>
<li><code class="codecolorer text default"><span class="text">set</span></code> les variables de sortie de la boucle. Ce sont les variables modifiées par le corps de la boucle.</li>
<li><code class="codecolorer text default"><span class="text">while</span></code> la condition.</li>
<li><code class="codecolorer text default"><span class="text">do</span></code> le corps de la boucle</li>
</ul>
<p>Voici le code complet.</p>
<pre><wrap>
/loop while
\(\n $cond\n \)(
{\n $body\n } | :\n $body\n \.[ \n])/
{
   loop_while(
      use (body.inVars + cond.inVars) * body.outVars,
      set body.outVars,
      while cond,
      do body)
}
</wrap>

def template loop_while(use $inVars, set $outVars, while $cond, do $body) =
   fun: inVars -> ret(outVars.types)
      if (cond)
          body -> outVars
          $loop1(inVars)
      else
          ret(outVars)
   .
   -> loop1
   loop1(inVars)
</pre>
<p>Voici comment fonctionne le code dans la forme à continuations.</p>
<pre>  fun: inVars -> ret(outVars.types) 
</pre>
<p>Définit une fonction lambda qui prend en paramètre <code class="codecolorer text default"><span class="text">inVars</span></code> et retourne <code class="codecolorer text default"><span class="text">outVars</span></code>.</p>
<pre>    if (cond) 
      body -> outVars
      $loop1(inVars) 
</pre>
<p>Si la condition est vraie, exécute le corps de la boucle puis fait un appel récursif à la fonction lambda avec <code class="codecolorer text default"><span class="text">inVars</span></code> comme arguments.</p>
<pre>    else 
      ret(outVars) 
  .
</pre>
<p>Sinon, retourne <code class="codecolorer text default"><span class="text">outVars</span></code>.</p>
<pre>  -> loop1 
  loop1(inVars)
</pre>
<p>Enfin, met la fonction lambda dans une variable <code class="codecolorer text default"><span class="text">loop1</span></code> puis appelle la fonction avec <code class="codecolorer text default"><span class="text">inVars</span></code> comme arguments.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Le modèle objet de dodo &#8211; Partie 2</title>
		<link>https://blog.developpez.com/dodo/p6427/intro/le_modele_objet_de_dodo_partie_2</link>
		<comments>https://blog.developpez.com/dodo/p6427/intro/le_modele_objet_de_dodo_partie_2#comments</comments>
		<pubDate>Wed, 24 Sep 2008 21:53:25 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Théorie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le modèle objet de dodo repose sur le prototype, comme nous avons vu dans la première partie. Nous allons maintenant voir comment dodo interprète la notion de classe, un classique de programmation orientée objet, en terme de prototypes. Classe Une classe définit un modèle auquel tous les objets instance de la classe répondent. En pratique, une classe dodo définit des attributs et fonctions membres de la classe ainsi qu&#8217;un prototype. Les objets instance de la [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le modèle objet de dodo repose sur le prototype, comme nous avons vu dans la première partie. </p>
<p>Nous allons maintenant voir comment dodo interprète la notion de classe, un classique de programmation orientée objet, en terme de prototypes.<br />
<span id="more-14"></span><br />
<strong>Classe</strong></p>
<p>Une <em>classe</em> définit un modèle auquel tous les <em>objets instance</em> de la classe répondent. En pratique, une classe dodo définit des attributs et fonctions membres de la classe ainsi qu&rsquo;un prototype. Les objets instance de la classe dérivent de ce prototype.</p>
<p>Le nom d&rsquo;une classe commence toujours avec une lettre majuscule.</p>
<p>Un exemple de classe serait <code class="codecolorer text default"><span class="text">Maison</span></code>, dont <code class="codecolorer text default"><span class="text">maisonDesDupont</span></code> serait une instance. Le prototype sur lequel est basé <code class="codecolorer text default"><span class="text">maisonDesDupont</span></code> est <code class="codecolorer text default"><span class="text">Maison.instance</span></code>, comme les autres objets instance de la classe.</p>
<p>La classe est elle-même un objet qui peut avoir des attributs et fonctions membres. Par exemple, <code class="codecolorer text default"><span class="text">instance</span></code> est un attribut standard d&rsquo;une classe.</p>
<p>Une classe possède également des constructeurs et des fonctions fabrique d&rsquo;objet.</p>
<p><strong>Constructeur</strong></p>
<p>Un <em>constructeur</em> initialise un objet instance de la classe. Si l&rsquo;attribut <code class="codecolorer text default"><span class="text">instance</span></code> de la classe n&rsquo;est pas défini et qu&rsquo;il existe un constructeur sans paramètre, dodo utilise ce constructeur pour créer l&rsquo;attribut <code class="codecolorer text default"><span class="text">instance</span></code> de la classe lorsque celle-ci est chargée en mémoire. Par exemple:</p>
<pre>class Maison
{
   Fenetre[] fenetres
   Couleur couleurMur, couleurToit
   make Maison()
   {
      .fenetres = [Fenetre()]
      .couleurMur = blanc
      .couleurToit = rouge
   }
}</pre>
<p>Quand la classe <code class="codecolorer text default"><span class="text">Maison</span></code> est chargée en mémoire, son attribut instance est initialisé en appelant le constructeur <code class="codecolorer text default"><span class="text">Maison()</span></code> qui l&rsquo;initialise avec une fenêtre, des murs blancs et un toit rouge.</p>
<p><strong>Fonction fabrique</strong></p>
<p>Une <em>fonction fabrique</em> d&rsquo;objet est une fonction de classe qui renvoie un objet instance de cette classe en fonction de certains paramètres. Par convention, le nom d&rsquo;une fonction fabrique d&rsquo;objet commence avec <code class="codecolorer text default"><span class="text">new</span></code>. Par exemple on pourrait définir une fonction <code class="codecolorer text default"><span class="text">Maison.newAvecMurEtToit(Couleur,Couleur)</span></code>.</p>
<p><strong>Héritage</strong></p>
<p>Une classe est elle-même un objet, qui utilise le modèle à base de prototype comme tout objet dodo. Une classe <em>hérite</em> d&rsquo;une <em>superclasse</em> quand elle utilise cette superclasse comme prototype. La superclasse peut être une autre classe ou bien le type d&rsquo;un objet.</p>
<p>La classe hérite des attributs, fonctions membres et autres propriétés de la superclasse. Le prototype des objets instance de la classe dérive du prototype utilisé (la superclasse est un objet) ou de l&rsquo;attribut <code class="codecolorer text default"><span class="text">instance</span></code> de la superclasse (la superclasse est une classe).</p>
<p>Une classe ne peut avoir qu&rsquo;une seule superclasse, mais on peut lui appliquer plusieurs <em>traits</em>.</p>
<p><strong>Trait</strong></p>
<p>En plus de la notion de prototype et de classe, dodo a celle de <em>trait</em> (<em>feature</em>). Un trait s&rsquo;applique à un objet ou à une classe pour lui définir des propriétés supplémentaires. Par exemple un nombre entier possède le trait <code class="codecolorer text default"><span class="text">Arithmetic</span></code> qui lui apporte l&rsquo;addition, la multiplication etc. ainsi que le trait <code class="codecolorer text default"><span class="text">Ordered</span></code> (ordonné).</p>
<p>Un trait se définit de la même façon qu&rsquo;une classe, mais il n&rsquo;y a pas d&rsquo;instance, de constructeur ou de fonction fabrique d&rsquo;objet dans un trait.</p>
<p><strong>Polymorphisme</strong></p>
<p>Le <em>polymorphisme</em> permet de faire abstraction du type exact d&rsquo;un objet pour n&rsquo;en retenir que les propriétés générales. Un exemple typique de polymorphisme est une fonction qui attend un paramètre de type FormeGeometrique, où le paramètre peut être tour à tour un carré, un cercle, un trapèze&#8230;</p>
<p>Pour bénéficier du polymorphisme, le type de l&rsquo;objet doit hériter de <code class="codecolorer text default"><span class="text">class</span></code> ou de <code class="codecolorer text default"><span class="text">Object</span></code> ou bien répondre au trait <code class="codecolorer text default"><span class="text">Polymorphic</span></code>.</p>
<p><strong>Conclusion</strong></p>
<p>Pour un rapport complet du modèle objet de dodo il faudrait également évoquer les patrons (templates), les fonctions de conversion, les états abstraits et d&rsquo;autres apports.<br />
En l&rsquo;état, on peut déjà voir toutes les possibilités qui s&rsquo;ouvrent au programmeur sur la base d&rsquo;un concept simple (le prototype) que le langage reprend sous diverses formes pour donner les outils familiers de la programmation orientée objet.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
