<?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</title>
	<atom:link href="https://blog.developpez.com/dodo/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>L&#8217;appartenance des variables (Borrow)</title>
		<link>https://blog.developpez.com/dodo/p13210/langage/lappartenance-des-variables-borrow</link>
		<comments>https://blog.developpez.com/dodo/p13210/langage/lappartenance-des-variables-borrow#comments</comments>
		<pubDate>Sat, 19 Oct 2024 00:17:52 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Langage]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/dodo/?p=130</guid>
		<description><![CDATA[Une notion importante de programmation, du moins si vous vous intéressez à comment ça marche, est celle de référence. Pour l&#8217;ordinateur une variable a deux attributs: sa valeur (on peut y attacher une taille, un type&#8230;) et son adresse en mémoire. Pourquoi l&#8217;adresse en mémoire? Eh bien, c&#8217;est simplement l&#8217;information qu&#8217;il lui faut pour accéder à la variable quand elle est en mémoire vive. Du coup, un programme tend à manipuler deux types de données. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Une notion importante de programmation, du moins si vous vous intéressez à comment ça marche, est celle de référence.</p>
<p>Pour l&rsquo;ordinateur une variable a deux attributs: sa valeur (on peut y attacher une taille, un type&#8230;) et son adresse en mémoire. Pourquoi l&rsquo;adresse en mémoire? Eh bien, c&rsquo;est simplement l&rsquo;information qu&rsquo;il lui faut pour accéder à la variable quand elle est en mémoire vive.</p>
<p>Du coup, un programme tend à manipuler deux types de données. Il y a les variables qui représentent des valeurs comme des caractères ou des nombres, et les variables qui contiennent&#8230; l&rsquo;adresse d&rsquo;une autre variable. Nous appelons ces dernières des &laquo;&nbsp;pointeurs&nbsp;&raquo; ou des &laquo;&nbsp;références&nbsp;&raquo;, des termes qui ne sont pas historiquement équivalents mais en pratique ils désignent le même objet.</p>
<p>Cette longue introduction a pour but de vous familiariser avec la notion de référence. Je voudrais maintenant passer au sujet principal: l&rsquo;appartenance.</p>
<p><strong>Le language Rust</strong></p>
<p><span id="more-130"></span></p>
<p>Si vous suivez les fils d&rsquo;information sur la programmation vous avez certainement, à un moment ou à un autre, entendu parler de Rust. En effet cette création de la fondation Mozilla a une profonde influence sur les derniers développements de systèmes d&rsquo;exploitation et de certains logiciels, avec Microsoft et Linux qui s&rsquo;y investissent.</p>
<p>La nouveauté de ce language est qu&rsquo;il parvient à gérer la mémoire de façon sûre sans compromettre la performance. Et cela tient à son utilisation du concept d&rsquo;appartenance pour les références.</p>
<p>Pour Rust, toute référence a une appartenance: une fonction ou un bout de code qui gère la variable pointée par la référence, comment et quand elle peut être modifiée ou désallouée. Le compilateur fait appel au fameux Borrow Checker (contrôleur d&rsquo;appartenance) pour s&rsquo;assurer que le code suit bien les règles définies par le language.</p>
<p>Je ne vais pas m&rsquo;étendre ici sur ces règles, si ce n&rsquo;est qu&rsquo;elles inspirent directement la suite.</p>
<p><strong>Références en dodo</strong></p>
<p>Le language dodo a deux types de références, qui sont complètement différents (à la surface).</p>
<p>Il y a les références simples qui apparaissent dans les paramètres des méthodes comme dans cet exemple:</p>
<blockquote><p>
method Mixe(&amp;Fruit[], Vitesse?)
</p></blockquote>
<p>La liste de fruits est passée par référence (marque <strong>&amp;</strong>) pour pouvoir être modifiée à l&rsquo;intérieur de la méthode. En effet connaître l&rsquo;adresse d&rsquo;une variable permet de la modifier de façon visible à l&rsquo;extérieur. En contraste, la vitesse n&rsquo;est pas une référence donc la méthode n&rsquo;a accès qu&rsquo;à sa valeur.</p>
<p>Mais c&rsquo;est bien la limitation de ce type de référence: elle ne peut être utilisée que dans les paramètres d&rsquo;une méthode ou d&rsquo;un constructeur, pas dans les paramètres d&rsquo;une fonction ou comme type d&rsquo;un champ dans un objet.</p>
<p>Le deuxième type de référence est appelé Link (lien). Il s&rsquo;apparente peut-être plus au pointeur traditionnel.</p>
<p>A la différence de la référence simple, Link peut être passé comme argument d&rsquo;une fonction et stocké dans un objet. Cela le rend plus versatile mais aussi plus compliqué en terme de gestion sûre de la mémoire.</p>
<p><strong>Gestion sûre de la mémoire avec Link</strong></p>
<p>A sa création une variable Link pointe vers une adresse mémoire invalide (le fameux pointeur <em>null</em> que vous avez peut-être déjà rencontré). Il n&rsquo;y a donc pas de variable à modifier ou désallouer à cette adresse. Son état à ce point est <strong>null</strong> (vide).</p>
<p>Quand on lui donne une valeur deux choses se passent:</p>
<ul>
<li>une variable est allouée en mémoire vive pour stocker la valeur</li>
<li>la référence Link pointe vers cette variable et prend l&rsquo;état <strong>owned</strong> (variable lui appartenant)</li>
</ul>
<p>La variable appartient effectivement au code qui l&rsquo;a créée en mémoire. Il n&rsquo;y a pas d&rsquo;autre code qui a accès à la variable.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def Age = new Link(with: Number) &nbsp;# type<br />
*Age _âge &nbsp; # lien initialisé avec null<br />
*_âge = 20 &nbsp;# variable allouée</div></div>
<p>A ce point la variable peut simplement être désallouée si le code s&rsquo;arrête ici, ou recevoir une nouvelle valeur. Il n&rsquo;y a pas vraiment de différence avec une variable ordinaire.</p>
<p>Elle peut aussi être passée à une autre fonction.</p>
<p>Il y a quatre façons de passer la variable à une autre fonction:</p>
<ul>
<li>de façon définitive: l&rsquo;appartenance de la variable change, la fonction appelée en prend possession</li>
<li>comme un lien passif, pour observation seulement</li>
<li>temporaire, la variable peut être modifiée par l&rsquo;appel mais l&rsquo;appelant en retient l&rsquo;appartenance</li>
<li>finalement comme une référence simple si c&rsquo;est une méthode ou un constructeur</li>
</ul>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def _gère(Personne, **Age) → ()</div></div>
<p>Dans le premier cas l&rsquo;appelant n&rsquo;a plus rien à voir avec la variable et le lien reprend l&rsquo;état <strong>null</strong> quand l&rsquo;appel finit. Il n&rsquo;y a pas de complication par rapport à l&rsquo;utilisation de la mémoire puisque l&rsquo;appelé en est responsable.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def assignation(RendezVous[], Age) → Personne</div></div>
<p>Dans le deuxième cas, l&rsquo;état du lien passif reçu par la fonction est <strong>listener</strong> (variable suivie). L&rsquo;appelé peut simplement consulter la variable sans la modifier.</p>
<p>La variable reprend son état initial quand l&rsquo;appel finit.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">def changeDate(Personne, DateVisite, *Age) → RendezVous</div></div>
<p>Dans le troisième cas l&rsquo;état du lien reçu par la fonction appelée est <strong>borrowed</strong> (variable prêtée). La fonction a la permission de modifier la variable. Elle peut aussi consulter la valeur de la variable ou la prêter à une autre fonction. Mais ça s&rsquo;arrête ici.</p>
<p>En particulier, la fonction appelée ne peut pas <em>désallouer</em> la variable. Comme avant, la variable reprend son état initial quand l&rsquo;appel finit.</p>
<blockquote><p>
method Remplace(&amp;*Age)
</p></blockquote>
<p>Avec une référence simple le lien lui-même peut changer, alors qu&rsquo;avec le prêt c&rsquo;est juste la variable.</p>
<ul>
<li>Si le lien est actif, l&rsquo;appartenance de la variable revient à l&rsquo;appelant mais la variable originelle peut être désallouée par la méthode.</li>
<li>Si le lien est passif le lien sortant doit avoir au moins la même durée de vie que le lien entrant (voir la prochaine section).</li>
</ul>
<p><strong>Référence Link comme attribut d&rsquo;objet</strong></p>
<p>Jusqu&rsquo;ici nous n&rsquo;avons vu que des références <strong>locales</strong>, ce qui signifie que la référence Link ne s&rsquo;échappe pas du bloc d&rsquo;instructions courant (fonction, méthode&#8230;)</p>
<p>A partir d&rsquo;ici nous allons parler de références en état de partage (<strong>shared</strong>).</p>
<p>Si le lien est stocké comme un lien <strong>actif</strong> dans l&rsquo;attribut d&rsquo;un objet, cet objet devient le propriétaire de la variable (<em>owned</em>). Elle peut être consultée ou prêtée tant que l&rsquo;objet est défini. Mais elle ne peut changer de propriétaire que quand l&rsquo;objet est désalloué, donc en valeur de retour à la sortie de la fonction. Cela est similaire à une variable prêtée (<em>borrowed</em>).</p>
<p>Si le lien est stocké comme un lien <strong>passif</strong> dans l&rsquo;attribut de l&rsquo;objet le propriétaire de la variable ne change pas. Il faut donc prendre garde que la durée de vie de l&rsquo;objet n&rsquo;excède pas celle du propriétaire. La variable ne peut pas changer de propriétaire tant que l&rsquo;objet est défini, car le nouveau propriétaire pourrait la désallouer alors qu&rsquo;il y a toujours une référence. C&rsquo;est une <em>variable partagée</em>.</p>
<p>Pour retourner un tel objet depuis une fonction il faut définir une exigence sur sa durée de vie à travers l&rsquo;attribut <em>lifetime</em> de son type, comme dans l&rsquo;exemple ci-dessous:</p>
<blockquote><p>
template (param: $A, retour: $S) [where A = Age(lifetime: $l) &amp;&amp; S = Suivi(lifetime: $l)]<br />
def suivi(Personne, A) → S
</p></blockquote>
<p>Cela indique que la durée de vie de l&rsquo;objet retourné doit correspondre à la durée de vie du paramètre de type Age. Si l&rsquo;âge passé en paramètre est stocké dans la valeur de retour de la fonction, le compilateur ne va pas produire d&rsquo;erreur car il y a une garantie que l&rsquo;âge sera défini pour toute la durée de vie de l&rsquo;objet.</p>
<p>Une durée de vie peut avoir une valeur <strong>static</strong>. Cela indique qu&rsquo;elle est de durée indéfinie et signifie que l&rsquo;objet va occuper de la mémoire jusqu&rsquo;à la fin du programme.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Le numéro de l&#8217;enum</title>
		<link>https://blog.developpez.com/dodo/p12021/intro/le-numero-de-lenum</link>
		<comments>https://blog.developpez.com/dodo/p12021/intro/le-numero-de-lenum#comments</comments>
		<pubDate>Wed, 05 Jun 2013 19:32:24 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[ensemble]]></category>
		<category><![CDATA[enum]]></category>
		<category><![CDATA[enumeration]]></category>
		<category><![CDATA[identifiant]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[syntaxe]]></category>
		<category><![CDATA[table]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/dodo/?p=85</guid>
		<description><![CDATA[En langage C, la déclaration d&#8217;un enum énumère une liste d&#8217;identifiants associés avec cet enum (d&#8217;où son nom) et affecte une valeur numérique unique pour chacun d&#8217;entre eux. En Java, l&#8217;idée est la même mais les identifiants appartiennent au namespace de l&#8217;Enum et les valeurs peuvent être non-numériques. Exemple d&#8217;enum en C: &#40;C&#41; enum style &#123; plan, relief, creux, cadre &#125;; Le type enum de dodo est différent. En fait, il correspond au type des [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>En langage C, la déclaration d&rsquo;un enum énumère une liste d&rsquo;identifiants associés avec cet enum (d&rsquo;où son nom) et affecte une valeur numérique unique pour chacun d&rsquo;entre eux. En Java, l&rsquo;idée est la même mais les identifiants appartiennent au namespace de l&rsquo;Enum et les valeurs peuvent être non-numériques.</p>
<p>Exemple d&rsquo;enum en C:</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"><span style="color: #009900;">&#40;</span>C<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">enum</span> style <span style="color: #009900;">&#123;</span> plan<span style="color: #339933;">,</span> relief<span style="color: #339933;">,</span> creux<span style="color: #339933;">,</span> cadre <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></div>
<p>Le type enum de dodo est différent. En fait, il correspond au type des identifiants tels que &laquo;&nbsp;plan&nbsp;&raquo;; la différence est qu&rsquo;il n&rsquo;y a pas de liste d&rsquo;identifiants définie. Donc dodo permet de faire:</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"><span style="color: #000000; font-weight: bold;">enum</span> jour <span style="color: #339933;">=</span> creux &nbsp;<span style="color: #339933;"># euh, c'est un jour de la semaine ça?</span></div></div>
<p>Heureusement il y a moyen de définir quels enums peuvent être affectés à une variable.</p>
<p>Cela se fait à l&rsquo;aide d&rsquo;une variable d&rsquo;ensemble ou de table associative. Par 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"><span style="color: #000000; font-weight: bold;">enum</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#93;</span> style <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #339933;">:</span>plan<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>relief<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>creux<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>cadre<span style="color: #009900;">&#93;</span></div></div>
<p>Dans cet exemple, style est un ensemble qui a quatre éléments. Un élément de cet ensemble est de type style.member, qui de par la déclaration est un enum&#8230; Mais dodo s&rsquo;assure que l&rsquo;élément est bien listé dans l&rsquo;ensemble!</p>
<p>On peut donc déclarer une variable comme un enum appartenant à l&rsquo;ensemble &laquo;&nbsp;style&nbsp;&raquo;:</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">style.<span style="color: #202020;">member</span> s <span style="color: #339933;">=</span> creux &nbsp;<span style="color: #339933;"># ok, creux est un enum appartenant à l'ensemble</span></div></div>
<p>C&rsquo;est un concept puissant qui peut s&rsquo;appliquer à d&rsquo;autres types qu&rsquo;enum, par exemple si l&rsquo;on veut limiter la valeur d&rsquo;une chaîne de caractères à un ensemble de chaînes bien défini.</p>
<p>Pour associer une valeur numérique à chaque identifiant, il faut utiliser une table associative plutôt qu&rsquo;un ensemble:</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"><span style="color: #993333;">int</span><span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">enum</span> label<span style="color: #009900;">&#93;</span> jours <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>lundi<span style="color: #339933;">:</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> mardi<span style="color: #339933;">:</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> mercredi<span style="color: #339933;">:</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> jeudi<span style="color: #339933;">:</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">,</span> vendredi<span style="color: #339933;">:</span> <span style="color: #0000dd;">5</span><span style="color: #009900;">&#93;</span><br />
jours.<span style="color: #202020;">label</span> jour <span style="color: #339933;">=</span> mardi &nbsp;<span style="color: #339933;"># ok, mardi est associé avec l'entier 2 dans la table</span></div></div>
<p>Un enum qui appartient à deux ensembles peut être utilisé pour les deux. Mais un type d&rsquo;enum n&rsquo;est compatible que si l&rsquo;ensemble est inclus dans l&rsquo;autre. On pourrait faire:</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"><span style="color: #000000; font-weight: bold;">enum</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#93;</span> semaine <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #339933;">:</span>lundi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>mardi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>mercredi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>jeudi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>vendredi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>samedi<span style="color: #339933;">,</span> <span style="color: #339933;">:</span>dimanche<span style="color: #009900;">&#93;</span><br />
semaine.<span style="color: #202020;">member</span> m <span style="color: #339933;">=</span> jour.<span style="color: #202020;">value</span> &nbsp;<span style="color: #339933;"># ok, l'ensemble de jours.label est inclus dans semaine</span></div></div>
<p>Dodo associe une valeur interne à chaque enum qu&rsquo;il rencontre pour pouvoir comparer les enums entre eux. Mais deux programmes dodo n&rsquo;utilisent pas la même valeur interne pour le même enum. Par exemple, &laquo;&nbsp;plan&nbsp;&raquo; dans un programme peut être associé avec la même valeur que &laquo;&nbsp;creux&nbsp;&raquo; dans l&rsquo;autre. Cela pose problème si ces programmes veulent échanger des données.</p>
<p>Pour pallier à cela, dodo demande que les enums échangés fassent toujours partie d&rsquo;un ensemble (on peut utiliser style.member mais pas directement enum), et les deux programmes s&rsquo;échangent la position d&rsquo;un élément dans l&rsquo;ensemble plutôt que sa valeur interne. De cette façon &laquo;&nbsp;plan&nbsp;&raquo; reste &laquo;&nbsp;plan&nbsp;&raquo; et ne se transfome pas en &laquo;&nbsp;creux&nbsp;&raquo; quand il est envoyé par message.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Langage à prototypes</title>
		<link>https://blog.developpez.com/dodo/p11940/langage/langage-a-prototypes</link>
		<comments>https://blog.developpez.com/dodo/p11940/langage/langage-a-prototypes#comments</comments>
		<pubDate>Fri, 26 Apr 2013 14:21:49 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Langage]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/dodo/?p=62</guid>
		<description><![CDATA[Une particularité intéressante de dodo est qu&#8217;il s&#8217;agit d&#8217;un langage prototypes, à l&#8217;instar de Javascript, qui est aussi fortement typé. Comment résoudre cet antagonisme? Nous y avons déjà touché dans l&#8217;article Le Modèle Objet de Dodo. En dodo, l&#8217;appartenance à un type implique que la variable dérive d&#8217;un prototype donné, et l&#8217;interface du type permet d&#8217;accéder ou manipuler la variable sur cette base. Dans cet épisode nous allons nous intéresser particulièrement aux prototypes. La façon [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Une particularité intéressante de dodo est qu&rsquo;il s&rsquo;agit d&rsquo;un langage prototypes, à l&rsquo;instar de Javascript, qui est aussi fortement typé. Comment résoudre cet antagonisme?</p>
<p>Nous y avons déjà touché dans l&rsquo;article <a href="http://blog.developpez.com/dodo/p6433/langage/le_modele_objet_de_dodo_partie_1" title="Le modèle objet de dodo – Partie 1">Le Modèle Objet de Dodo</a>. En dodo, l&rsquo;appartenance à un type implique que la variable dérive d&rsquo;un prototype donné, et l&rsquo;interface du type permet d&rsquo;accéder ou manipuler la variable sur cette base.</p>
<p>Dans cet épisode nous allons nous intéresser particulièrement aux prototypes.</p>
<p>La façon la plus directe d&rsquo;ajouter des fonctionnalités à une variable est d&rsquo;étendre son prototype.</p>
<p>Par 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">def point <span style="color: #339933;">=</span> new <span style="color: #993333;">struct</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">double</span> x<span style="color: #339933;">,</span> y<br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Nous allons décomposer cela.</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 point</div></div>
<p>Cela commence une déclaration de variable. Tous les noms de type commencent avec une majuscule, ce qui n&rsquo;est pas le cas de <em>point</em> donc il s&rsquo;agit d&rsquo;un nom de variable. Le mot <em>def</em> indique l&rsquo;inférence de type (ou plutôt de prototype) locale, comme &laquo;&nbsp;auto&nbsp;&raquo; en C++11. On s&rsquo;attend donc à une valeur d&rsquo;initialisation.</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"><span style="color: #339933;">=</span> new <span style="color: #993333;">struct</span></div></div>
<p>Comme attendu, voici l&rsquo;initialisation de la variable introduite par &laquo;&nbsp;=&nbsp;&raquo;. Le mot-clef <em>new</em> veut dire que l&rsquo;expression étend un prototype, dans ce cas <em>struct</em>. Toute variable ou constante peut être utilisée comme prototype.</p>
<p>La variable <em>struct</em> est juste une structure vide, elle occupe zéro octet de mémoire et n&rsquo;a aucun attribut membre. Je vais noter sa valeur <strong>{}</strong> à la façon de Javascript.</p>
<p>Vu la nature de <em>struct</em>, il n&rsquo;y a pas vraiment d&rsquo;utilité à l&rsquo;utiliser comme prototype si l&rsquo;on n&rsquo;ajoute aucun membre. On s&rsquo;attend donc à ce qu&rsquo;un bloc de déclaration suive.</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"><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">double</span> x<span style="color: #339933;">,</span> y<br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Voici le bloc de déclaration comme prévu. Celui-ci étend le prototype <em>struct</em> et par cela ajoute les attributs <em>x</em> et <em>y</em> en tant que membres de la variable <em>point</em>.</p>
<p>La variable <em>double</em> est utilisée comme prototype de <em>x</em> et <em>y</em>, qui prennent sa valeur (normalement <strong>0.0</strong>) puisque ils n&rsquo;ont pas de valeur d&rsquo;initialisation. C&rsquo;est l&rsquo;équivalent de <em>&laquo;&nbsp;def x = double; def y = double&nbsp;&raquo;</em>. L&rsquo;effet et la syntaxe sont les mêmes qu&rsquo;une déclaration de variable en C++ avec une valeur par défaut.</p>
<p>Quand un prototype est étendu avec de nouveaux attributs membres, l&rsquo;espace mémoire alloué est la somme de la taille du prototype et la taille des nouveaux attributs. Le prototype est copié au début de l&rsquo;espace mémoire, suivi par les attributs.</p>
<p>Dans le cas de <em>point</em> la valeur d&rsquo;initialisation est donc:</p>
<blockquote><p>{ {}, 0.0, 0.0 }</p></blockquote>
<p>Ceci occupe l&rsquo;espace de deux double puisque <em>struct</em> n&rsquo;occupe aucun espace mémoire.</p>
<p>Cette représentation en mémoire sert de guide à ce que l&rsquo;on peut faire avec la variable <em>point</em>. Par exemple, on peut lui assigner une nouvelle valeur comme <strong>(2.0, -1.33)</strong> puisque c&rsquo;est la notation de dodo pour une structure avec deux valeurs de (proto)type <em>double</em>, donc la représentation en mémoire est la même:</p>
<blockquote><p>{ {}, 2.0, -1.33 }</p></blockquote>
<p>Une propriété intéressante d&rsquo;avoir le prototype en tête de la structure est qu&rsquo;une variable ainsi structurée est compatible avec son prototype, et le prototype de son prototype, etc&#8230; Il suffit de se limiter aux premiers octets de la structure.</p>
<p>Par exemple, si l&rsquo;on étend le prototype <em>double</em> avec de nouveaux attributs membres pour une variable, cette variable peut être utilisée partout où un <em>double</em> est attendu. Cependant les attributs supplémentaires peuvent être perdus dans l&rsquo;opération.</p>
<p>Par exemple si l&rsquo;on fait:</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"><span style="color: #993333;">struct</span> struct_p <span style="color: #339933;">=</span> point</div></div>
<p>La variable <em>struct_p</em> n&rsquo;a pas d&rsquo;attributs <em>x</em> et <em>y</em> car son (proto)type est <em>struct</em> qui ne les a pas définis.</p>
<p>Ce qui est aussi intéressant de voir est quel est le type de retour d&rsquo;un fonction retournant plusieurs valeurs. En programmation classique, une fonction ne retourne qu&rsquo;une valeur:</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 droite_1<span style="color: #009900;">&#40;</span>point p<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span> <span style="color: #b1b100;">return</span> point<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> new p<span style="color: #009900;">&#40;</span>x<span style="color: #339933;">:</span> p.<span style="color: #202020;">x</span> <span style="color: #339933;">+</span> <span style="color:#800080;">1.0</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Ici la valeur retournée par <em>droite_1(point)</em> est représentée en mémoire par:</p>
<blockquote><p>{ {}, 1.0, 0.0 }</p></blockquote>
<p>Mais dodo permet aussi de retourner plus d&rsquo;une valeur. Cette notation révèle une autre caractéristique du langage dodo, le passage de continuations, qui n&rsquo;a pas de limitation:</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 pos_droite_1<span style="color: #009900;">&#40;</span>point p<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">double</span><span style="color: #339933;">,</span> <span style="color: #993333;">double</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span>p.<span style="color: #202020;">x</span> <span style="color: #339933;">+</span> <span style="color:#800080;">1.0</span><span style="color: #339933;">,</span> p.<span style="color: #202020;">y</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>La représentation en mémoire de ce que retourne <em>pos_droite_1(point)</em> est:</p>
<blockquote><p>{ 1.0, 0.0 }
</p></blockquote>
<p>D&rsquo;après ce que l&rsquo;on a vu auparavant, le premier élément de la structure est le prototype. Ici c&rsquo;est un <em>double</em>, donc on peut assigner la valeur de retour à une variable de (proto)type <em>double</em> de par la compatibilité avec le prototype:</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"><span style="color: #993333;">double</span> x1 <span style="color: #339933;">=</span> pos_droite_1<span style="color: #009900;">&#40;</span>point<span style="color: #009900;">&#41;</span></div></div>
<p>Mais dodo est aussi prêt à convertir la valeur de retour en <em>struct</em> étendue où toutes les valeurs retournées sont attributs membres, comme <em>x</em> et <em>y</em> dans <em>point</em>. On peut donc faire:</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">point point1 <span style="color: #339933;">=</span> pos_droite_1<span style="color: #009900;">&#40;</span>point<span style="color: #009900;">&#41;</span></div></div>
<p>Où la représentation en mémoire de <em>point1</em> est la même que pour <em>droite_1(point)</em>:</p>
<blockquote><p>{ {}, 1.0, 0.0 }
</p></blockquote>
<p><!--next page--><br />
Il y a aussi des variables dont la représentation en mémoire dépend de l&rsquo;état d&rsquo;un ou plusieurs attributs membres. C&rsquo;est le cas en particulier de <em>class</em>, le prototype des objets, qui a pour seul attribut une lien vers l&rsquo;interface de l&rsquo;objet:</p>
<blockquote><p>{ Object }</p></blockquote>
<p>L&rsquo;interface de <em>class</em> est <em>Object</em>.</p>
<p>Toute classe d&rsquo;objets qui étend ce prototype a un lien vers sa propre interface, ce qui permet à dodo de connaître sa représentation en mémoire.</p>
<p>Par 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 Figure<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; point centre<br />
<span style="color: #009900;">&#125;</span></div></div>
<p>L&rsquo;instance par défaut de cette classe, l&rsquo;objet <em>Figure.instance</em>, est représenté en mémoire par:</p>
<blockquote><p>{ Figure, { {}, 0.0, 0.0 } }</p></blockquote>
<p>On peut définir la classe d&rsquo;objets <em>Cercle</em> qui étend <em>Figure</em>:</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 Cercle <span style="color: #339933;">=</span> new Figure<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">double</span> rayon <span style="color: #339933;">=</span> <span style="color:#800080;">1.0</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Comme auparavant, le prototype est le premier membre de la structure pour <em>Cercle.instance</em>:</p>
<blockquote><p>{ { Cercle, { {}, 0.0, 0.0 } }, 1.0 }</p></blockquote>
<p>Mais si on assigne ceci à une variable de (proto)type <em>Figure.instance</em>, la valeur du lien (attribut dont dépend la représentation en mémoire) doit être changé en <em>Figure</em>:</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">Figure.<span style="color: #202020;">instance</span> figure <span style="color: #339933;">=</span> Cercle.<span style="color: #202020;">instance</span></div></div>
<p>Si ce n&rsquo;était pas le cas la variable figure mentirait sur son état, ce qui cause des problèmes. Dodo utilise la relation entre <em>Cercle</em> et <em>Figure</em> pour déterminer la valeur à utiliser pour le lien. En fin de compte la variable est représentée par:</p>
<blockquote><p>{ Figure, { {}, 0.0, 0.0 } }
</p></blockquote>
<p>Cela illustre bien que les prototypes ne se prêtent pas bien au polymorphisme. Si l&rsquo;on veut préserver la nature de <em>Cercle</em> de l&rsquo;objet, il faut utiliser le nom de la classe plutôt que son instance comme type:</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">Figure figure_cercle <span style="color: #339933;">=</span> Cercle.<span style="color: #202020;">instance</span></div></div>
<p>Cette fois-ci, la représentation en mémoire de l&rsquo;objet <em>figure_cercle</em> reste inchangée car il n&rsquo;y a pas de contrainte sur la façon dont il est représenté:</p>
<blockquote><p>{ { Cercle, { {}, 0.0, 0.0 } }, 1.0 }
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Faire dodo en C &#8211; Partie 3</title>
		<link>https://blog.developpez.com/dodo/p11806/technique/faire-dodo-en-c-partie-3</link>
		<comments>https://blog.developpez.com/dodo/p11806/technique/faire-dodo-en-c-partie-3#comments</comments>
		<pubDate>Tue, 26 Feb 2013 10:01:47 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/dodo/?p=33</guid>
		<description><![CDATA[Pour le troisième volet de cet article je vais discuter la fonction auxiliaire à laquelle je faisais allusion dans la première partie. Nous allons premièrement voir quel est le problème qu&#8217;il s&#8217;agit de résoudre. Le problème des appels de fonction Revenons au programme fzero que l&#8217;on avait traduit en C dans le volet précédent de cet article: int choix = 0; while (1) switch (choix) { case 0: if (n == 0) choix = 1; [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour le troisième volet de cet article je vais discuter la fonction auxiliaire à laquelle je faisais allusion dans la première partie. Nous allons premièrement voir quel est le problème qu&rsquo;il s&rsquo;agit de résoudre.<br />
<span id="more-33"></span></p>
<h2>Le problème des appels de fonction</h2>
<p>Revenons au programme <strong>fzero</strong> que l&rsquo;on avait traduit en C dans le volet précédent de cet article:</p>
<pre>   int choix = 0;
   while (1) switch (choix)
   {
      case 0:
         if (n == 0) choix = 1;
         else choix = 2;
         break;
      case 1:
         return c_return;
      case 2:
         n = n - 1;
         choix = 0;
         break;
      default:
         c_throw-&gt;event.message = "Erreur de branchement!";
         return c_throw;
   }</pre>
<p>Ce qui est notable c&rsquo;est qu&rsquo;il s&rsquo;agit d&rsquo;une fonction très simple. En particulier, cette fonction ne fait pas appel à d&rsquo;autres fonctions dodo: le test <em>if</em>, les opérations <em>n == 0</em> et <em>n = n &#8211; 1</em> sont directement écrits en C ici.</p>
<p>Mais si elle contient un appel de fonction, d&rsquo;après la logique du language dodo <strong>fzero</strong> devrait lui fournir une continuation à invoquer quand la fonction veut retourner à l&rsquo;appelant.</p>
<p>Si l&rsquo;on s&rsquo;en tient à la convention d&rsquo;une fonction C par fonction dodo, cela signifie que l&rsquo;on devrait pouvoir sauter au milieu de la boucle <em>while</em> avec une branche (valeur de <em>choix</em>) différente de zéro.</p>
<h2>Une solution</h2>
<p>Une solution simple à cela serait de passer en tant que continuation non seulement la fonction à appeler, mais aussi la branche où il faut se rendre. Mais il peut y avoir d&rsquo;autres données à inclure dans la continuation comme les paramètres de la fonction (<em>n</em> dans cet exemple). Si bien que la solution retenue utilise une structure C pour stocker l&rsquo;adresse de la fonction, la branche et les autres données.</p>
<pre>typedef void* (*continuation)(void*);

struct fzero_data
{
   continuation* function;
   int choice;
   int n;
   continuation** c_return;
   continuation** c_throw;
};</pre>
<p>Ce qui est intéressant est que cela correspond à ce à quoi l&rsquo;on s&rsquo;attend pour une closure écrite en C. Il n&rsquo;y a rien de bien étonnant à ça, comme j&rsquo;avais dit auparavant il est facile de traduire les continuations de dodo  en closures dans un language de programmation qui en dispose.</p>
<h2>Exemple pratique</h2>
<p>A ce point nous pouvons appeler une autre fonction dodo depuis la boucle while en spécifiant l&rsquo;adresse de <em>data</em> comme continuation de retour. Par exemple, nous allons appeler une fonction qui écrit un texte à l&rsquo;écran.</p>
<p>Nous pouvons donc utiliser la structure ci-dessus dans notre fonction:</p>
<pre>continuation** fzero(int n, continuation** c_return, continuation** c_throw);

continuation** fzero_switch(struct fzero_data* data)
{
   int choix = data-&gt;choix;
   while (1) switch (choix)
   {
      case 0:
         if (data-&gt;n == 0) choix = 1;
         else choix = 2;
         break;
      case 1:
         return data-&gt;c_return;
      case 2:
         data-&gt;choix = 3;
         return printHello((continuation**) data, c_throw);
      case 3:
         data-&gt;n = data-&gt;n - 1;
         choix = 0;
         break;
      default:
         ((struct event_handler*) data-&gt;c_throw)-&gt;event.message =
            "Erreur de branchement!";
         return data-&gt;c_throw;
   }
}</pre>
<p>La fonction <strong>fzero</strong> déclarée ci-dessus sera expliquée dans un prochain volet, mais nous pouvons déjà comprendre qu&rsquo;elle crée une structure <em>fzero_data</em> avec les paramètres de la fonction puis appelle la fonction auxiliaire <strong>fzero_switch</strong>.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Faire dodo en C &#8211; Partie 2</title>
		<link>https://blog.developpez.com/dodo/p11189/technique/faire_dodo_en_c_partie_2</link>
		<comments>https://blog.developpez.com/dodo/p11189/technique/faire_dodo_en_c_partie_2#comments</comments>
		<pubDate>Sat, 28 Jul 2012 20:14:01 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le langage dodo et le langage C ne sont pas trop éloignés au niveau de la syntaxe, mais leur fonctionnement est assez différent. Là où C est un langage procédural, dodo est un langage à prototypes utilisant le passage de continuations (CPS). Le défi pour moi, l&#8217;architecte du langage, est de faire correspondre les concepts de dodo à une implémentation pratique offrant une performance acceptable. Je me suis donc tourné vers C avec l&#8217;idée d&#8217;écrire [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le langage dodo et le langage C ne sont pas trop éloignés au niveau de la syntaxe, mais leur fonctionnement est assez différent. Là où C est un langage <a href="http://fr.wikipedia.org/wiki/Programmation_procédurale">procédural</a>, dodo est un <a href="http://fr.wikipedia.org/wiki/Programmation_orientée_prototype">langage à prototypes</a> utilisant le <a href="http://fr.wikipedia.org/wiki/Continuation">passage de continuations (CPS)</a>.</p>
<p>Le défi pour moi, l&rsquo;architecte du langage, est de faire correspondre les concepts de dodo à une implémentation pratique offrant une performance acceptable. Je me suis donc tourné vers C avec l&rsquo;idée d&rsquo;écrire un convertisseur automatique de programmes dodo en C.</p>
<p>Seulement voilà, comment traduire?<br />
<span id="more-11"></span><br />
<strong>La directive switch<br />
</strong><br />
Comme je l&rsquo;ai suggéré dans <a href="http://blog.developpez.com/dodo/p11170/technique/faire-dodo-en-c/">la première partie</a>, l&rsquo;appel de continuation en dodo et la directive <code class="codecolorer text default"><span class="text">switch</span></code> de C s&rsquo;apparentent tous deux à <em>GOTO</em>, alors on peut écrire quelque chose comme:</p>
<pre>
   int choix = 0;
   while (1) switch (choix)
   {
      case 0:
         if (n == 0) choix = 1;
         else choix = 2;
         break;
      case 1:
         return c_return;
      case 2:
         n = n - 1;
         choix = 0;
         break;
      default:
         c_throw-&gt;event.message = "Erreur de branchement!";
         return c_throw;
   }
</pre>
<p>Cela correspond à une fonction dodo qui prend en paramètre un nombre <em>n</em> et le décrémente jusqu&rsquo;à ce qu&rsquo;il atteigne 0, puis retourne de la fonction:</p>
<pre>
   def fzero = fun(int n) =&gt; return(), throw(Exception):
      n = 0 -&gt;
         return()
      |
         n - 1 -&gt; n
         $fzero(n)
   .
</pre>
<p><strong>La notation à continuations</strong></p>
<p>Le code dodo ci-dessus ne ressemble pas vraiment à du C vous me direz. C&rsquo;est que j&rsquo;ai utilisé la notation à continuations pour bien illustrer la correspondance avec le <code class="codecolorer text default"><span class="text">switch</span></code>. En réalité, le but est bien de pouvoir écrire la fonction <code class="codecolorer text default"><span class="text">fzero</span></code> en style C comme ceci:</p>
<pre>
   def fzero(int n)
   {
      loop
      {
         case if (n = 0)
         {
            return()
         }
         .n = n - 1
      }
   }
</pre>
<p>À quoi bon transformer une fonction de style C en une fonction à passage de continuations, pour ensuite la transformer à nouveau en fonction C vous demandez-vous?</p>
<p>Hé bien pour le moment je compte implémenter juste la notation à continuations, de façon à avoir une base solide pour le langage, et ensuite m&rsquo;attaquer à la transformation du style procédural en passage de continuations pour rendre le langage plus confortable à utiliser. Si un jour je trouve un langage avec continuations ou <em>GOTO</em> que je peux utiliser en lieu et place de C, il devrait être simple d&rsquo;implémenter le langage de base de dodo avec lui. Le reste de dodo n&rsquo;aura pas besoin d&rsquo;être réécrit.</p>
<p><strong>La boucle de continuations</strong></p>
<p>Revenons à nos moutons.</p>
<p>Nous avons vu comment utiliser <code class="codecolorer text default"><span class="text">switch</span></code> pour implémenter une fonction dodo simple qui se contente de décrémenter un compteur.</p>
<p>Pour ceux qui sont attentifs, il y a une continuation dans le <code class="codecolorer text default"><span class="text">switch</span></code> qui n&rsquo;existe pas dans la fonction dodo: celle du cas <em>default</em>. Un examen du code montre que ce cas n&rsquo;est jamais atteint, mais il est bon de prévoir une erreur du convertisseur automatique (ou dans ce cas, du convertisseur humain puisque c&rsquo;est écrit à la main!)</p>
<p>
<hr /></p>
<p>Si je parle du cas <em>default</em> c&rsquo;est que ses instructions contiennent une ligne intéressante qu&rsquo;il serait bon d&rsquo;expliquer. C&rsquo;est:</p>
<pre>
   c_throw-&gt;event.message = "Erreur de branchement!";
</pre>
<p>On y voit comment passer un paramètre à une continuation. En effet, <em>c_throw</em> est une continuation passée en paramètre à la fonction C. Il ne serait pas viable d&rsquo;utiliser la technique du <code class="codecolorer text default"><span class="text">switch</span></code> pour toutes les continuations du programme, dans une application conséquente il y aurait des centaines de milliers de cas dans le <code class="codecolorer text default"><span class="text">switch</span></code>, sans compter qu&rsquo;il faudrait trouver comment faire passer des arguments à une continuation sans mettre tout en variables globales.</p>
<p>Donc on garde la boucle de continuation décrite <a href="http://blog.developpez.com/dodo/p9236/technique/vers-une-premiere-implementation-de-dodo/">dans un article précédent</a> pour interagir avec les autres fonctions.</p>
<p>Mais la boucle de continuation utilise des fonctions qui sont appelées en boucle, comment se fait-il que l&rsquo;exemple utilise la notation <code class="codecolorer text default"><span class="text">c_throw-&amp;gt;event</span></code> qui suggère que <em>c_throw</em> est une structure pas une fonction?</p>
<p>C&rsquo;est simple, <em>c_throw</em> est effectivement une structure. Mais son premier champ est un pointeur de fonction qui est utilisé par la boucle de continuations. Dans l&rsquo;exemple donné, <em>event</em> est un autre champ de la structure. La boucle de continuations ne sait rien de <em>event</em>, ou des autres champs ajoutés à la structure.</p>
<p>Il faut que la fonction appelée par la boucle de continuations puisse lire une valeur fournie comme argument par l&rsquo;appelant de la continuation qui, lui, connaît la structure de c_throw.</p>
<p>C&rsquo;est pour cela que la boucle de continuation passe la structure en argument à la fonction. Dès lors, voici comment s&rsquo;écrit la boucle de continuations:</p>
<pre>
   continuation suivante = premiere
   while (suivante != NULL)
   {
      suivante = suivante-&gt;appel(suivante);
   }
</pre>
<p><strong>Gestion de la mémoire</strong></p>
<p>Donc <em>event</em> est un champ de la structure passée en argument à la fonction C pour la continuation <em>c_throw</em>. Côté dodo il correspond à un argument de la continuation <code class="codecolorer text default"><span class="text">throw</span></code>. Mais comment le programme alloue-t-il la mémoire pour les champs supplémentaires de la structure?</p>
<p>
<hr /></p>
<p>La boucle de continuations ne peut pas gérer cela, elle ne sait rien des champs supplémentaires et de plus elle ne saurait pas quand la mémoire n&rsquo;est plus nécessaire et peut être libérée.</p>
<p>L&rsquo;appelant pourrait utiliser <code class="codecolorer text default"><span class="text">malloc</span></code> pour allouer la mémoire nécessaire. La mémoire pourrait être libérée au retour si elle n&rsquo;est plus utilisée. C&rsquo;était de fait ma première idée.</p>
<p>Un problème est que le contrôle ne retourne pas nécessairement à l&rsquo;appelant quand la fonction termine. Un exemple courant est une fonction qui passe à une fonction appelée sa propre continuation <code class="codecolorer text default"><span class="text">return</span></code> comme continuation de retour. Quand la fonction appelée fait <code class="codecolorer text default"><span class="text">return()</span></code>, la fonction qui l&rsquo;a appelée n&rsquo;est pas informée.</p>
<p>Il faut donc intercepter cela pour libérer la mémoire allouée, avant que la continuation n&rsquo;atteigne la boucle de continuations.</p>
<p>C&rsquo;est alors qu&rsquo;une autre idée m&rsquo;est venue.</p>
<p>Plutôt que d&rsquo;essayer de libérer la mémoire quand elle n&rsquo;est plus utilisée, pourquoi n&rsquo;essaierions-nous pas de préserver la mémoire qui sera encore utilisée jusqu&rsquo;au retour de la fonction?</p>
<p>Pour cela, on dissocie la fonction dodo en deux fonctions C: l&rsquo;une qui fait le travail et contient le <code class="codecolorer text default"><span class="text">switch</span></code>, et l&rsquo;autre qui préserve la mémoire utile jusqu&rsquo;à la fin de la fonction et qui contient une boucle de continuations. La fonction au <code class="codecolorer text default"><span class="text">switch</span></code> n&rsquo;utilise la boucle de continuations que pour reprendre le contrôle quand une fonction appelée retourne ou pour terminer. La boucle de continuations continue tant que la continuation suivante appelle la fonction au <code class="codecolorer text default"><span class="text">switch</span></code> (qui n&rsquo;est donc pas terminée).</p>
<p>Il n&rsquo;y a pas besoin d&rsquo;utiliser <code class="codecolorer text default"><span class="text">malloc</span></code> avec cette solution, la mémoire peut être préservée sur la pile.</p>
<p>Par exemple, si notre fonction <em>fzero</em> voulait afficher la valeur de <em>n</em> à chaque itération on pourrait écrire les deux fonctions:</p>
<pre>
   continuation fzero(int n, continuation c_return, continuation c_throw)
   {
      struct c_fzero donnees = {
         fzero_switch, // appel
         0,            // choix
         n,
         c_return,
         c_throw
      }
      continuation suivante = (continuation) &amp;donnees;
      while (suivante-&gt;appel == fzero_switch)
      {
         suivante = suivante-&gt;appel(suivante);
      }
      return suivante;
   }

   continuation fzero_switch(continuation self)
   {
      struct c_fzero *donnees = (struct c_fzero*) self;
      int choix = donnees-&gt;choix;
      int n = donnees-&gt;n;
      while (1) switch (choix)
      {
         case 0:
            if (n == 0) choix = 1;
            else choix = 2;
            break;
         case 1:
            return donnees-&gt;c_return;
         case 2:
            donnees-&gt;choix = 3;
            donnees-&gt;n = n;
            return print_int(n, self, donnees-&gt;c_throw);
         case 3:
            n = n - 1;
            choix = 0;
            break;
         default:
            donnees-&gt;c_throw-&gt;event.message = "Erreur de branchement!";
            return donnees-&gt;c_throw;
      }
   }
</pre>
<p>On voit que si <em>print_int</em> retourne <em>self</em>, la boucle de continuation appelle à nouveau <em>fzero_switch</em> mais avec le choix 3. Par contre si elle retourne la continuation <code class="codecolorer text default"><span class="text">throw</span></code>, la boucle de continuation de <em>fzero</em> termine.</p>
<p>Je conclus ainsi la seconde partie de <strong><a href="http://blog.developpez.com/dodo/p11170/langage/faire_dodo_en_c" title="Faire dodo en C">Faire dodo en C</a></strong>.</p>
<p>Vous pouvez réagir dans les commentaires ci-dessous.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Une table associative efficace basée sur deux principes</title>
		<link>https://blog.developpez.com/dodo/p11178/technique/une_table_associative_efficace_basee_sur</link>
		<comments>https://blog.developpez.com/dodo/p11178/technique/une_table_associative_efficace_basee_sur#comments</comments>
		<pubDate>Fri, 27 Jul 2012 13:11:21 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Table de hachage La table de hachage est une structure de données qui permet d&#8217;implémenter une table associative (que l&#8217;on appelle aussi un index ou un dictionnaire). Son principe est de répartir les données de façon homogène à l&#8217;aide d&#8217;une fonction de hachage appliquée aux clés de la table. La plupart des langages de programmation offrent une table de hachage comme structure de données standard, avec peut-être l&#8217;exception notable du langage C (noter que le [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><strong>Table de hachage</strong></p>
<p>La <em><a href="http://fr.wikipedia.org/wiki/Table_de_hachage">table de hachage</a></em> est une structure de données qui permet d&rsquo;implémenter une <a href="http://fr.wikipedia.org/wiki/Tableau_associatif">table associative</a> (que l&rsquo;on appelle aussi un <em>index</em> ou un <em>dictionnaire</em>). Son principe est de répartir les données de façon homogène à l&rsquo;aide d&rsquo;une <em><a href="http://fr.wikipedia.org/wiki/Fonction_de_hachage">fonction de hachage</a></em> appliquée aux clés de la table.</p>
<p>La plupart des langages de programmation offrent une table de hachage comme structure de données standard, avec peut-être l&rsquo;exception notable du langage C (noter que le C++ comble cette lacune).</p>
<p>Mais est-il possible de faire mieux que la table de hachage proposée par défaut?<br />
<span id="more-10"></span><br />
<strong>Mesure du mieux</strong></p>
<p>Il y a différentes mesures qui déterminent la qualité d&rsquo;une table de hachage.</p>
<p>L&rsquo;une d&rsquo;elle est le<em> taux de remplissage</em> &#8211; est-ce que la table accommode un certain nombre d&rsquo;éléments sans laisser trop de &laquo;&nbsp;trous&nbsp;&raquo;?</p>
<p>Une autre est l&rsquo;efficacité de consultation, et l&rsquo;efficacité d&rsquo;insertion. Je ne parlerai pas de l&rsquo;efficacité d&rsquo;enlever un élément.</p>
<p>Un facteur clé pour améliorer le taux de remplissage est une bonne fonction de hachage. Par exemple, si la fonction de hachage ne retourne jamais que des nombres entre <em>0</em> et <em>100</em>, il est inévitable que plusieurs clés aient la même valeur de hachage après une centaine d&rsquo;insertions. Même si la table de hachage se redimensionne pour accommoder plus d&rsquo;éléments, ce sera en vain car tous les éléments vont se retrouver aux emplacements correspondants aux nombres de 0 à 100, en fait c&rsquo;est contre-productif puisque le taux de remplissage se détériore!</p>
<p>La solution proposée dans cet article ne permet pas de compenser une mauvaise fonction de hachage. En fait elle est plus exigeante que les solutions traditionnelles car elle fait appel à plusieurs fonctions de hachage pour chaque clé.</p>
<p><strong>Le principe de la seconde chance</strong></p>
<p>Utiliser deux (ou davantage) fonctions de hachage est la base de la première astuce qui va nous permettre d&rsquo;écrire une table de hachage super efficace, le <em>principe de la seconde chance</em>.</p>
<p>Etant donné une fonction de hachage <em>h1</em> et une clé <em>k</em>, comment décider où placer l&rsquo;élément dans la table de hachage? Une table de hachage fait généralement appel à un tableau de taille fixe (<em>N</em>) pour stocker les données, donc il s&rsquo;agit de faire correspondre le numéro retourné par <code class="codecolorer text default"><span class="text">h1(k)</span></code> avec un numéro d&rsquo;index dans ce tableau. </p>
<p>Cela se fait souvent avec l&rsquo;opération <em>modulo</em>, c&rsquo;est-à-dire le reste de la division <code class="codecolorer text default"><span class="text">h1(k) / N</span></code>. Le modulo donne un nombre entre <em>0</em> et<em> N-1</em> qui est utilisée comme valeur d&rsquo;index.</p>
<p>Si je rappelle tout cela, c&rsquo;est pour mettre en exergue le fait qu&rsquo;une tâche de la table de hachage est de gérer les <em>collisions</em>. En effet, il y a plusieurs valeurs telles que, par exemple, <code class="codecolorer text default"><span class="text">x modulo 100</span></code> est égal à 13. Si la valeur de hachage est 13, 113, 213, 313 etc il faut lui trouver une place même s&rsquo;il y a déjà un élément à l&rsquo;emplacement prévu.</p>
<p>Une solution est de rechercher un autre emplacement possible pour l&rsquo;élément. Le principe de la seconde change utilise une différente fonction de hachage, disons <em>h2</em>, pour déterminer cet autre emplacement. Il est important que <em>h1</em> et <em>h2</em> soient indépendants, autrement il y a des chances que les deux fonctions retournent les mêmes deux résultats pour différentes clés.</p>
<p>Donc l&rsquo;algorithme est:</p>
<pre>p1 = h1(k) modulo N
si libre(p1)
  alors table[p1] = paire(k, élément)
sinon
  p2 = h2(k) modulo N
  si libre(p2)
    alors table[p2] = paire(k, élément)
</pre>
<p>Il est possible d&rsquo;utiliser davantage de fonctions de hachage de la même façon que h2.</p>
<p>Pour retrouver un élément, on regarde aux différents emplacements possible pour voir s&rsquo;ils contiennent la clé recherchée.</p>
<p>Si tous les emplacements sont déjà pris, il peut être nécessaire de redimensionner le tableau — ce qui donne un nouvel <em>N</em> et permet, on l&rsquo;espère, de placer l&rsquo;élément.</p>
<p>Il n&rsquo;est pas très satisfaisant de devoir compter sur un <em>N</em> qui a exactement la bonne valeur pour pouvoir placer un élément, d&rsquo;autant plus qu&rsquo;il est coûteux de redimensionner la table de hachage car tous les éléments prennent un nouvel emplacement. L&rsquo;efficacité de consultation est très bonne mais utilisé seul, le principe de seconde chance donne un taux de remplissage avoisinant les 50%.</p>
<p><strong>Le principe du coucou</strong></p>
<p>Pour améliorer cela, on utilise une autre astuce: <em>le principe du <a href="http://en.wikipedia.org/wiki/Cuckoo_hashing">coucou</a></em>. Le bébé coucou, il est bien connu, est né dans le nid d&rsquo;autres oiseaux et se fait de la place en jetant les oeufs du nid par-dessus bord. Pour une table de hachage, l&rsquo;idée est de faire de la place en déplaçant l&rsquo;élément existant <em>autre part</em>.</p>
<p>Certains utilisent les fonctions de hachage pour trouver un nouvel emplacement à l&rsquo;élément existant dans la table de hachage. S&rsquo;il n&rsquo;y a pas d&rsquo;emplacement libre, il peut y avoir des déplacements en cascade. Mais <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.185.2655&#038;rep=rep1&#038;type=pdf">une étude a montré</a> qu&rsquo;un seul déplacement par insertion est nécessaire pour une bonne efficacité.</p>
<p>Ma solution, de son côté, utilise une <em>réserve</em> pour les éléments existants déplacés. Dans mes tests, en utilisant une table de hachage de 50 à 100 éléments comme réserve, le taux de remplissage excède facilement 90% pour l&rsquo;insertion de 250 à 10000 éléments jusqu&rsquo;à saturation.</p>
<p>C&rsquo;est tout bonnement excellent pour une solution aussi simple et économe en espace mémoire.</p>
<p>L&rsquo;algorithme combinant <em>le principe de seconde chance</em> avec deux fonctions de hachage, <em>le principe du coucou</em> et une réserve est:</p>
<pre>p1 = h1(k) modulo N
si libre(p1)
  alors table[p1] = paire(k, élément)
sinon
  p2 = h2(k) modulo N
  si libre(p2)
    alors table[p2] = paire(k, élément)
  sinon
    p = choix(p1 ou p2)
    ajoute(réserve, table[p])
    table[p] = paire(k, élément)
</pre>
<p>Si la réserve est pleine on a le choix de redimensionner le tableau ou la réserve. Je pense que l&rsquo;idéal est d&rsquo;augmenter les deux jusqu&rsquo;à ce que la taille de la réserve soit trop grande pour être stockée dans une ligne de cache ou une page de mémoire, puis n&rsquo;augmenter que la taille du tableau. Mes tests montrent qu&rsquo;il n&rsquo;y a pas d&rsquo;avantage à avoir une très grande réserve.</p>
<p>Pour la réserve on peut utiliser une table de hachage comme je l&rsquo;ai fait ou on peut utiliser une liste ordonnée par valeur de hachage, dont l&rsquo;ordre peut être maintenu de façon efficace pour un nombre d&rsquo;éléments restreint (<code class="codecolorer text default"><span class="text">O(log N)</span></code> pour la consultation et pour l&rsquo;insertion). L&rsquo;avantage est que la liste ordonnée peut accepter des éléments dont toutes les valeurs de hachage sont identiques.</p>
<p><strong>Problème: je n&rsquo;ai qu&rsquo;une seule fonction de hachage!</strong></p>
<p>Souvent en standard on n&rsquo;a qu&rsquo;une seule fonction de hachage à disposition, par exemple en Java il y a <code class="codecolorer text default"><span class="text">x.hashCode()</span></code>. Dans le cas d&rsquo;un objet composé de plusieurs attributs, on peut simplement prendre les attributs uniques à l&rsquo;objet et utiliser leurs fonctions de hachage.</p>
<p>Il y a un autre moyen. Puisque l&rsquo;index dans le tableau est calculé à l&rsquo;aide de <code class="codecolorer text default"><span class="text">h1(k) modulo N</span></code>, le résultat non fractionnaire de la division n&rsquo;entre pas en compte. Par exemple si:</p>
<pre>
N = 100
h1(k)=1113
</pre>
<p>alors l&rsquo;index est 13. On n&rsquo;utilise pas les deux premiers chiffres 11.</p>
<p>Donc on peut utiliser la partie entière de la division <code class="codecolorer text default"><span class="text">h1(k) / N</span></code> comme seconde valeur de hachage.</p>
<p><strong><em>Et maintenant, à vos claviers!</em></strong></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Faire dodo en C</title>
		<link>https://blog.developpez.com/dodo/p11170/langage/faire_dodo_en_c</link>
		<comments>https://blog.developpez.com/dodo/p11170/langage/faire_dodo_en_c#comments</comments>
		<pubDate>Fri, 20 Jul 2012 19:50:00 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Langage]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le langage C est réputé proche de la machine. Comme le langage dodo utilise des techniques très bas niveau, on pourrait penser que C serait une plate-forme idéale pour une implémentation efficace. La réalité n&#8217;est pas si simple. Il y a une fondamentale différence entre la façon dont dodo structure le code et C structure le code. C est un langage procédural, l&#8217;unité d&#8217;organisation du code est la fonction. De son côté dodo se base [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le langage C est réputé proche de la machine. Comme le langage dodo utilise des techniques très bas niveau, on pourrait penser que C serait une plate-forme idéale pour une implémentation efficace. </p>
<p>La réalité n&rsquo;est pas si simple.<br />
 <span id="more-9"></span><br />
Il y a une fondamentale différence entre la façon dont dodo structure le code et C structure le code. C est un langage procédural, l&rsquo;unité d&rsquo;organisation du code est la fonction. De son côté dodo se base sur les continuations. </p>
<p>Nous l&rsquo;avons vu dans un article précédent, il est possible de simuler les continuations avec des fonctions à l&rsquo;aide de <a href="http://blog.developpez.com/dodo/p9236/technique/vers-une-premiere-implementation-de-dodo/">la boucle de continuations</a>. </p>
<p>Mais C y met un autre obstacle: il n&rsquo;offre pas de closures. Le rôle des closures est de capturer les variables qui doivent être encore utilisées par la suite. Les fonctions de Clojure font office de closures, ce qui m&rsquo;a permis d&rsquo;<a href="http://blog.developpez.com/dodo/p9400/langage/dodo/venez-jouer-1/">écrire une première implémentation</a> (dodo0). En C il faut mettre en place un autre mécanisme pour préserver les données qui doivent être réutilisées dans d&rsquo;autres continuations. </p>
<p>Mon idée est de faire correspondre une fonction dodo à une fonction C. Puisque les variables d&rsquo;une fonction sont généralement utilisées tout au long de son exécution, on peut les préserver au niveau d&rsquo;une fonction. </p>
<p>Une continuation est l&rsquo;équivalent d&rsquo;un GOTO, et en C la directive switch est aussi équivalente à GOTO. Alors chaque fonction a une boucle avec un switch pour aller d&rsquo;une continuation à l&rsquo;autre.</p>
<p>Mais il faut aussi pouvoir appeler d&rsquo;autres fonctions dodo, qui s&rsquo;attendent à une continuation de retour. Pour cela chaque fonction C a une fonction auxiliaire qui se charge de sauter directement à la continuation désignée lors de son appel.</p>
<p>J&rsquo;ai trouvé que dans certaines circonstances il était possible de faire tout cela sans allocation de mémoire, uniquement sur la pile! C&rsquo;est une bonne nouvelle.</p>
<p>Dans un prochain épisode, je donnerai plus de détails et des exemples de code. A bientôt!</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gestion des chaînes de caractères</title>
		<link>https://blog.developpez.com/dodo/p11127/langage/gestion_des_chaines_de_caracteres</link>
		<comments>https://blog.developpez.com/dodo/p11127/langage/gestion_des_chaines_de_caracteres#comments</comments>
		<pubDate>Mon, 02 Jul 2012 01:44:13 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Intro]]></category>
		<category><![CDATA[Langage]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Représentation Une chaîne de caractères en dodo peut simplement s&#8217;écrire entre double guillemets. "Bonjour" Par défaut, le programme utilise le même encodage de caractères que le fichier source. Le compilateur détermine l&#8217;encodage du fichier à sa lecture. Cependant la détection d&#8217;encodage de fichier n&#8217;est pas une science exacte et dépend souvent de la configuration du système. Le compilateur doit permettre de fournir le nom d&#8217;un encodage de caractères au moment de la compilation. Pour choisir [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><strong>Représentation</strong></p>
<p>Une chaîne de caractères en dodo peut simplement s&rsquo;écrire entre double guillemets.</p>
<pre>   "Bonjour"
</pre>
<p>Par défaut, le programme utilise le même encodage de caractères que le fichier source. Le compilateur détermine l&rsquo;encodage du fichier à sa lecture. Cependant la détection d&rsquo;encodage de fichier n&rsquo;est pas une science exacte et dépend souvent de la configuration du système. Le compilateur doit permettre de fournir le nom d&rsquo;un encodage de caractères au moment de la compilation.</p>
<p>Pour choisir l&rsquo;encodage des caractères d&rsquo;une chaîne pour le programme il est possible de précéder les guillemets ouvrants avec un code. Par exemple, &laquo;&nbsp;x&nbsp;&raquo; est le code qui indique un encodage de caractères en UTF-16.<br />
Le compilateur traduit de l&rsquo;encodage du fichier en celui spécifié pour la chaîne de caractères.</p>
<p><strong>Contenu</strong></p>
<p>En fonction de l&rsquo;encodage sélectionné, les caractères qui composent la chaîne peuvent occuper un octet ou plus. Par exemple en BIG5 les caractères chinois occupent deux octets et les caractères latins n&rsquo;en occupent qu&rsquo;un.<br />
En Unicode il est même possible d&rsquo;utiliser plusieurs caractères &#8211; ou codepoints &#8211; pour écrire une lettre, par exemple un accent aigu et &laquo;&nbsp;e&nbsp;&raquo; font un &laquo;&nbsp;é&nbsp;&raquo;.</p>
<p><span id="more-22"></span></p>
<p>Au vu de ces considérations, on ne peut pas toujours faire correspondre une position absolue dans la chaîne avec un caractère. Cela signifie que pour obtenir, par exemple, le cinquième caractère de la chaîne il faut soit partir du premier caractère et avancer caractère par caractère, ou il faut utiliser une représentation interne différente pour les caractères.</p>
<p>Dodo considère que le choix d&rsquo;encodage du programmeur prend précédence, et n&rsquo;impose pas sa propre représentation interne des chaînes de caractères.<br />
En cela dodo est différent de Java et autres langages qui sont standardisés avec UTF-16 ou un autre encodage de caractères. Pour les opérations telles qu&rsquo;obtenir le cinquième caractère, une chaîne de caractères peut être convertie en un tableau de caractères de façon efficace.</p>
<p><strong>Caractères spéciaux</strong></p>
<p>En dodo il n&rsquo;y a pas de caractère d&rsquo;échappement prédéfini. Donc les caractères spéciaux peuvent simplement être insérés dans la chaîne, sans les précéder d&rsquo;un caractère d&rsquo;échappement. Cela implique aussi qu&rsquo;une chaîne de caractères ne peut pas contenir de double guillemet.</p>
<pre>
   "antislash: \, dollar: $, apostrophe: ', pourcent: %"</pre>
<p>Pour exprimer le double guillemet, les caractères de contrôle et les caractères qui ne peuvent pas être représentés à l&rsquo;aide de l&rsquo;encodage de caractères courant, dodo a une syntaxe pour un seul caractère:</p>
<pre>
   \"
   \n
   \u2030</pre>
<p>Un tel caractère peut être ajouté à une chaîne de caractères par concaténation. De plus, rien n&rsquo;empêche les fonctions comme sprintf() d&rsquo;interpréter certaines séquences de caractères comme des caractères échappés.</p>
<p><strong>Texte multi-ligne</strong></p>
<p>Dodo aide le programmeur à se rappeler de fermer une chaîne de caractères en rejetant une ligne qui a des guillemets ouvrants mais pas de guillemets fermants. A moins que la ligne suivante commence avec des guillemets.<br />
Si la ligne suivante commence avec des guillemets alors la chaîne de caractères continue à la ligne suivante, et ainsi de suite jusqu&rsquo;à une ligne qui contient des guillemets fermants.</p>
<pre>
   "ligne 1
   "ligne 2"</pre>
<p>L&rsquo;inconvénient est que cela fait un nombre impair de double-guillemets sur une ligne, ce qui ne plaît pas aux éditeurs de texte. Pour pallier à cela, on peut utiliser trois double-guillemets pour indiquer que la chaîne continue sur la ligne suivante.</p>
<pre>
   "ligne 1"""
   "ligne 2"</pre>
<p>
Cette syntaxe a aussi l&rsquo;avantage de révéler s&rsquo;il y a des espaces en fin de ligne.</p>
<p><strong>Conclusion</strong></p>
<p>En attribuant un encodage à chaque chaîne de caractères et en convertissant automatiquement de l&rsquo;encodage système vers l&rsquo;encodage spécifié, dodo permet un grand contrôle sur la représentation des chaînes de caractères dans le programme.</p>
<p>La gestion des chaînes de caractères dans dodo s&rsquo;efforce d&rsquo;apporter des réponses aux problèmes courants. Par exemple, les opérations sur les caractères et les opérations sur les codes sont clairement séparées.</p>
<p>
Si certains choix de syntaxe peuvent porter à débat (notamment l&rsquo;absence de caractère d&rsquo;échappement) ils ont leurs avantages et ne sont pas difficiles à s&rsquo;habituer.</p>
<p>A propos de la syntaxe, je vais refermer ce chapitre avec une proposition de syntaxe pour la concaténation de chaînes de caractères.<br />
Si une expression est une chaîne de caractères entre double guillemets, elle peut être suivie d&rsquo;une expression entre parenthèses et du reste de la chaîne de caractères. Il n&rsquo;est pas nécessaire de spécifier l&rsquo;encodage pour le reste de la chaîne.</p>
<pre>
   x"Utilisateur = "(\")(nom)(\")(\n)"Age = "(age)(\n)</pre>
<p>Qu&rsquo;en dites-vous?</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>
	</channel>
</rss>
