<?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; Flânerie</title>
	<atom:link href="https://blog.developpez.com/dodo/pcategory/flanerie/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>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>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>Dernières nouvelles</title>
		<link>https://blog.developpez.com/dodo/p10249/intro/dernieres_nouvelles</link>
		<comments>https://blog.developpez.com/dodo/p10249/intro/dernieres_nouvelles#comments</comments>
		<pubDate>Sun, 04 Sep 2011 00:48:13 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Intro]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Quoi de neuf dans l&#8217;univers de dodo? Malgré les apparences, je ne suis pas resté complètement oisif. Documentation Pour une part j&#8217;ai commencé à mettre à jour la documentation du langage. Dites-moi ce que vous en pensez! Dodo &#8211; Introduction (anglais) Implémentation J&#8217;ai aussi fait des tentatives d&#8217;implémentation de dodo en d&#8217;autres langages. Je reparlerai de la version C une autre fois. Pour le moment, je vous invite à regarder cette adaptation du modèle objet [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Quoi de neuf dans l&rsquo;univers de dodo?</p>
<p>Malgré les apparences, je ne suis pas resté complètement oisif.</p>
<p><strong>Documentation</strong><br />
Pour une part j&rsquo;ai commencé à mettre à jour la documentation du langage. Dites-moi ce que vous en pensez!</p>
<p><a href="http://dodo.sourceforge.net/doc/Dodo-Introduction.html">Dodo &#8211; Introduction</a> (anglais)</p>
<p><strong>Implémentation</strong><br />
J&rsquo;ai aussi fait des tentatives d&rsquo;implémentation de dodo en d&rsquo;autres langages. Je reparlerai de la version C une autre fois. Pour le moment, je vous invite à regarder cette adaptation du modèle objet de dodo à Javascript (incomplet):<br />
<span id="more-27"></span><br />
<a href="https://gist.github.com/1170337">Source de la page</a></p>
<p>Si vous regardez tout en bas du source, vous verrez un petit programme d&rsquo;exemple qui fait appel à ce modèle objet adapté de dodo.</p>
<p>Je donne ici les correspondances de terme:</p>
<pre>
             Dodo                |            Javascript
_________________________________|________________________________
                                 |
 struct                          | struct
                                 |
 self                            | this
                                 |
 new var0(x: 1) {def z = 36}     | copy(var0, 'x', 1, {z: 36})
                                 |
 ^fonc                           | $fonc
                                 |
 class A {def coul="bleu"}       | var A = new Class({coul: "bleu"});
                                 |
 class B {B(n) {print(n)}}       | var B = new Class({}, {1: function(n)
                                 |         {print(n);}});
                                 |
                                 |   NOTE: "1" est le nombre d'arguments
                                 |   du constructeur
                                 |
 def C = new A {def p = 0}       | var C = new A.constructor({p: 0});
                                 |
 B(1000)                         | new B(1000)
                                 |
</pre>
<p>J&rsquo;ai bien tenté de rendre les variables construites par ce modèle non éditables comme en dodo mais celà fait appel au nouveau standard ECMAScript et mes connaissances de Javascript sont limitées.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</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>Venez jouer!</title>
		<link>https://blog.developpez.com/dodo/p9400/flanerie/venez_jouer_1</link>
		<comments>https://blog.developpez.com/dodo/p9400/flanerie/venez_jouer_1#comments</comments>
		<pubDate>Sat, 16 Oct 2010 16:01:18 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Flânerie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le jour est venu, dodo a maintenant un interpréteur qui permet d&#8217;écrire de petits programmes et les exécuter! Certes il est limité à un petit nombre d&#8217;éléments du langage mais on peut déjà faire des choses intéressantes. Assurez-vous de lire Readme.txt et les exemples. Page du projet: http://sourceforge.net/projects/dodo Autres liens: http://blog.developpez.com/dodo/p7976/langage/dodo/langage-minimal-pour-dodo http://blog.developpez.com/dodo/p9236/technique/vers-une-premiere-implementation-de-dodo]]></description>
				<content:encoded><![CDATA[<p>Le jour est venu, dodo a maintenant un interpréteur qui permet d&rsquo;écrire de petits programmes et les exécuter!</p>
<p>Certes il est limité à un petit nombre d&rsquo;éléments du langage mais on peut déjà faire des choses intéressantes. Assurez-vous de lire Readme.txt et les exemples. Page du projet:</p>
<p>http://sourceforge.net/projects/dodo</p>
<p>Autres liens:</p>
<p>http://blog.developpez.com/dodo/p7976/langage/dodo/langage-minimal-pour-dodo</p>
<p>http://blog.developpez.com/dodo/p9236/technique/vers-une-premiere-implementation-de-dodo</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>À propos du passage de messages</title>
		<link>https://blog.developpez.com/dodo/p7898/technique/a_propos_du_passage_de_messages</link>
		<comments>https://blog.developpez.com/dodo/p7898/technique/a_propos_du_passage_de_messages#comments</comments>
		<pubDate>Fri, 24 Jul 2009 14:45:47 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans le dernier ticket, j&#8217;ai parlé du modèle client-serveur avec passage de message pour la programmation parallèle en dodo. Cela semble une bonne idée en théorie, mais comment cela marche en pratique? À mon idée, les services peuvent tourner dans la même tâche, une autre tâche (le plus courant), un autre processus ou même sur une autre machine. La communication par message entre un client et un serveur doit être efficace, contrôlée et sure. Il [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Dans le dernier ticket, j&rsquo;ai parlé du modèle client-serveur avec passage de message pour la programmation parallèle en dodo.</p>
<p>Cela semble une bonne idée en théorie, mais comment cela marche en pratique?<br />
<span id="more-25"></span><br />
À mon idée, les services peuvent tourner dans la même tâche, une autre tâche (le plus courant), un autre processus ou même sur une autre machine. La communication par message entre un client et un serveur doit être efficace, contrôlée et sure.</p>
<p>Il faut donc s&rsquo;attendre à un système de messages assez complexe.</p>
<p>Je vais essayer de décrire ce qui peut se passer quand un client envoie une requête au serveur.<br />
D&rsquo;abord, le client doit disposer d&rsquo;une <em>capability</em> qui l&rsquo;autorise à faire la requête. Le code situé dans un constructeur ou une méthode, qui peut donc avoir des effets de bord, peut généralement obtenir une <em>capability</em> sans ambages. Le reste du code peut la recevoir en paramètre.</p>
<p>La <em>capability</em> contient un code (comme un mot de passe) plus ou moins sophistiqué reconnu par le serveur. Celui-ci est utilisé pour encoder la requête.</p>
<p>Pour savoir où envoyer la requête, il faut que le serveur enregistre les services qu&rsquo;il offre auprès des clients. Alors le client peut choisir un serveur à qui envoyer la requête (ou peut-être plusieurs serveurs).</p>
<p>Puis le message qui forme la requête entre dans une file d&rsquo;attente associée avec le serveur. Les messages sortent de la file d&rsquo;attente suivant le principe du premier venu, premier servi (par défaut) ou suivant un système de priorité mis en place par le programmeur.</p>
<p>Je pense que chaque tâche maintient sa liste de files d&rsquo;attente pour les services qu&rsquo;elle utilise, et le serveur fait le tour des tâches pour trouver les files d&rsquo;attentes qui lui sont destinées. Si le serveur se trouve dans un autre processus ou sur une autre machine, il y a un serveur spécial auprès du client qui s&rsquo;occupe de récupérer les messages destinés au serveur pour les lui envoyer.</p>
<p>Une fois le message récupéré, le serveur le décode à l&rsquo;aide du code correspondant à la <em>capability</em> utilisée. Alors la méthode désignée est exécutée avec les paramètres reçus dans le message. Les paramètres doivent être validés avant d&rsquo;être passés à la méthode.</p>
<p>Si la méthode doit reporter une exception ou un résultat au client, il faut mettre à jour l&rsquo;objet retourné par la requête (message) et en informer le client. Le message retourné a plusieurs états possibles, comme &laquo;&nbsp;en attente&nbsp;&raquo;, &laquo;&nbsp;résultat partiel&nbsp;&raquo;, &laquo;&nbsp;résultat final&nbsp;&raquo;, &laquo;&nbsp;exception&nbsp;&raquo;&#8230;</p>
<p>Le client, de son côté, peut faire ce qu&rsquo;il veut en attendant le résultat. Jusqu&rsquo;à ce qu&rsquo;il demande à utiliser ce résultat, auquel cas il s&rsquo;arrête jusqu&rsquo;à obtenir le résultat final ou une exception. Il devrait être possible d&rsquo;accéder au résultat partiel à l&rsquo;aide d&rsquo;un <em>handler</em> muni d&rsquo;un timeout.</p>
<p>Le compilateur peut se charger d&rsquo;optimiser tout cela, peut-être en se passant d&rsquo;encodage et décodage dans certains cas, ou même de passage de message. La file d&rsquo;attente de messages doit être efficace et éviter de bloquer les tâches. Si le <em>handler</em> l&rsquo;autorise, on pourrait renoncer à envoyer un message plutôt que de bloquer quand la file d&rsquo;attente est trop pleine.</p>
<p>Y a-t-il des questions qui n&rsquo;ont pas été encore abordées? Des point qui ne sont pas clairs ou erronés? J&rsquo;aimerais avoir votre opinion.</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>Particularités de yield</title>
		<link>https://blog.developpez.com/dodo/p6552/technique/particularites_de_yield</link>
		<comments>https://blog.developpez.com/dodo/p6552/technique/particularites_de_yield#comments</comments>
		<pubDate>Fri, 10 Oct 2008 16:49:06 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Dodo]]></category>
		<category><![CDATA[Flânerie]]></category>
		<category><![CDATA[Technique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans une fonction qui retourne le type yield, le return n&#8217;indique pas la fin de la fonction. En effet la particularité de yield est que l&#8217;on peut retourner plusieurs valeurs l&#8217;une après l&#8217;autre. Alors que se passe-t-il si l&#8217;on met le return à l&#8217;intérieur d&#8217;un bloc try? Par exemple: yield(int) disUnNombre() { popoh() try: return 5 return 3 return 1 . hopop() } D&#8217;après la documentation, hopop() devrait être appelé juste avant que la fonction [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Dans une fonction qui retourne le type <code class="codecolorer text default"><span class="text">yield</span></code>, le <code class="codecolorer text default"><span class="text">return</span></code> n&rsquo;indique pas la fin de la fonction. En effet la particularité de <code class="codecolorer text default"><span class="text">yield</span></code> est que l&rsquo;on peut retourner plusieurs valeurs l&rsquo;une après l&rsquo;autre.</p>
<p>Alors que se passe-t-il si l&rsquo;on met le <code class="codecolorer text default"><span class="text">return</span></code> à l&rsquo;intérieur d&rsquo;un bloc <code class="codecolorer text default"><span class="text">try</span></code>?<br />
<span id="more-23"></span><br />
Par exemple:</p>
<pre>
yield(int) disUnNombre()
{
   popoh()
   try:
      return 5
      return 3
      return 1
   .
   hopop()
}
</pre>
<p>D&rsquo;après la documentation, hopop() devrait être appelé juste avant que la fonction retourne avec <code class="codecolorer text default"><span class="text">return 5</span></code>. De même pour <code class="codecolorer text default"><span class="text">return 3</span></code> et <code class="codecolorer text default"><span class="text">return 1</span></code>&#8230;</p>
<p>Or le but du bloc <code class="codecolorer text default"><span class="text">try</span></code> est d&rsquo;isoler le code qui peut générer un erreur, de façon que le code qui suit soit toujours exécuté (bloc <em>finally</em> dans d&rsquo;autres langages). Le <code class="codecolorer text default"><span class="text">yield</span></code> interfère ici avec ce but.</p>
<p>Il faut donc ajouter une règle comme quoi l&rsquo;instruction <code class="codecolorer text default"><span class="text">return</span></code> ne cause pas l&rsquo;exécution du code après le bloc <code class="codecolorer text default"><span class="text">try</span></code> dans le cas du <code class="codecolorer text default"><span class="text">yield</span></code>. L&rsquo;exécution a toujours lieu en cas d&rsquo;exception ou quand les instructions du bloc <code class="codecolorer text default"><span class="text">try</span></code> sont complétées.</p>
<p>Le compilateur s&rsquo;arrange pour que toutes les valeurs de la fonction soient retournées, donc hopop() est appelé dans tous les cas de terminaison.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bonne Année</title>
		<link>https://blog.developpez.com/dodo/p7046/flanerie/bonne_annee_2014</link>
		<comments>https://blog.developpez.com/dodo/p7046/flanerie/bonne_annee_2014#comments</comments>
		<pubDate>Wed, 07 Jan 2009 01:50:26 +0000</pubDate>
		<dc:creator><![CDATA[bredelet]]></dc:creator>
				<category><![CDATA[Flânerie]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonne année, meilleurs voeux à tous! Les vacances sont terminées et je compte reprendre la publication du Nid De Dodo. Au programme: la gestion des versions, l&#8217;encapsulation des données et probablement une discussion sur le parallélisme. Ce sont des sujets passionnants alors il faut repasser ici à l&#8217;occasion]]></description>
				<content:encoded><![CDATA[<p>Bonne année, meilleurs voeux à tous!</p>
<p>Les vacances sont terminées et je compte reprendre la publication du Nid De Dodo. Au programme: la gestion des versions, l&rsquo;encapsulation des données et probablement une discussion sur le parallélisme.</p>
<p>Ce sont des sujets passionnants alors il faut repasser ici à l&rsquo;occasion <img src="https://blog.developpez.com/dodo/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
