<?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 blog de SpiceGuid &#187; Programmation fonctionnelle</title>
	<atom:link href="https://blog.developpez.com/damien-guichard/pcategory/programmation-fonctionnelle/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/damien-guichard</link>
	<description></description>
	<lastBuildDate>Mon, 28 May 2012 16:08:44 +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>Types Abstraits généralisés</title>
		<link>https://blog.developpez.com/damien-guichard/p8967/programmation-fonctionnelle/types_abstraits_generalises</link>
		<comments>https://blog.developpez.com/damien-guichard/p8967/programmation-fonctionnelle/types_abstraits_generalises#comments</comments>
		<pubDate>Wed, 02 Jun 2010 15:59:13 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si vous ne l&#8217;avez pas déjà fait dépêchez-vous de visionner ou de télécharger la vidéo conférence de Heinrich Apfelmus sur les GADTs (Generalized Algebraic Data Types).]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://haskell.org/" target="_blank"><img src="http://haskell.org/sitewiki/images/a/a8/Haskell-logo-60.png"/></a></center></p>
<p>Si vous ne l&rsquo;avez pas déjà fait dépêchez-vous de visionner ou de télécharger<br />
<a href="http://www.archive.org/details/ExplanationOfGeneralizedAlgebraicDataTypesgadts" target="_blank">la vidéo conférence</a> de <a href="http://apfelmus.nfshost.com/" target="_blank">Heinrich Apfelmus</a> sur les GADTs (Generalized Algebraic Data Types).</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Méditation sur une calculatrice</title>
		<link>https://blog.developpez.com/damien-guichard/p8966/programmation-fonctionnelle/meditation_sur_une_calculatrice</link>
		<comments>https://blog.developpez.com/damien-guichard/p8966/programmation-fonctionnelle/meditation_sur_une_calculatrice#comments</comments>
		<pubDate>Wed, 02 Jun 2010 13:53:42 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Objective Caml]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Un exercice simple pour débutant en ocaml c&#8217;est d&#8217;écrire un interpréteur pour un petit langage simple comme par exemple une calculatrice : type arithmetic = &#124; Cst of int &#124; Neg of arithmetic &#124; Add of binary &#124; Sub of binary &#124; Mul of binary &#124; Div of binary and binary = arithmetic * arithmetic Mais cet exercice anodin change complètement de nature quand on passe à un langage fortement normalisant, dans ce cas vous [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a></center></p>
<p>Un exercice simple pour débutant en ocaml c&rsquo;est d&rsquo;écrire un interpréteur pour un petit langage simple comme par exemple une calculatrice :</p>
<pre>
type arithmetic =
   | Cst of int
   | Neg of arithmetic
   | Add of binary
   | Sub of binary
   | Mul of binary
   | Div of binary
and binary =
   arithmetic * arithmetic
</pre>
<p>Mais cet exercice anodin change complètement de nature quand on passe à un langage fortement normalisant, dans ce cas vous devez aussi prouver que le programme se termine toujours et sans accident, quelles que soient les circonstances.    </p>
<p><span id="more-28"></span></p>
<p>Cette preuve ce fait en deux étapes :</p>
<ul>
<li>d&rsquo;abord il changer d&rsquo;algèbre initiale</li>
<li>ensuite il faut établir une égalité entre les deux types algébriques</li>
</ul>
<p>Le changement d&rsquo;algèbre initiale se fait en paraphrasant la déclaration du type, en remplaçant chaque occurrence de <em>arithmetic</em> par une occurrence de <em>fold f</em> :</p>
<pre>
let rec fold f = function
   | Cst n -> f#cst n 
   | Neg a -> f#neg (fold f a)
   | Add (a,b) -> f#add (fold f a) (fold f b)
   | Sub (a,b) -> f#sub (fold f a) (fold f b)
   | Mul (a,b) -> f#mul (fold f a) (fold f b)
   | Div (a,b) -> f#div (fold f a) (fold f b)
</pre>
<p>Le paramètre <em>f</em> est une égalité entre les deux types algébriques :       </p>
<pre>
let id x = x   
   
let eval =
   fold (
      object
         method cst = id
         method neg = (~-)
         method add = ( + )
         method sub = ( - ) 
         method mul = ( * ) 
         method div = ( / )
      end )
</pre>
<p>À cette étape on est à l&rsquo;abri des boucles infinies.<br />
Mais on n&rsquo;est pas à l&rsquo;abri des interruptions intempestives, par exemple lors d&rsquo;une division par zéro.    </p>
<pre>
# eval (Div(Cst 1,Cst 0));;
Exception: Division_by_zero.
</pre>
<p>Dans les langages fortements normalisants les exceptions n&rsquo;existent pas.<br />
Pour simuler les exceptions on utilise la monade <em>result</em> pour propager le diagnostic d&rsquo;erreur.</p>
<pre>
type ('a,'b) result =
   | Ok of 'a
   | Error of 'b 

let ok1 f v =
   match v with
   | Ok x -> Ok (f x)
   | Error _ -> v

let ok2 f v1 v2 =
   match v1,v2 with
   | Ok x1,Ok x2 -> Ok (f x1 x2) 
   | Error _, _ -> v1
   | _, Error _ -> v2

let result2 f v1 v2 =
   match v1,v2 with
   | Ok x1,Ok x2 -> f x1 x2 
   | Error _, _ -> v1
   | _, Error _ -> v2
   
let safe_division a b =  
   if b=0 then Error "Division_by_zero"
   else Ok (a/b)  
</pre>
<p>À l&rsquo;aide de cette monade <em>result</em> on peut définir une nouvelle égalité qui prend en compte les possibilités d&rsquo;erreur :  </p>
<pre>
let ok n = Ok n   
      
let eval =
   fold (
      object
         method cst = ok
         method neg = ok1 (~-)
         method add = ok2 ( + )
         method sub = ok2 ( - ) 
         method mul = ok2 ( * ) 
         method div = result2 safe_division
      end )
</pre>
<p>Cette fois le programme suit son cours jusqu&rsquo;au bout, sans interruption :</p>
<pre>
# eval (Div(Cst 1,Cst 0));;
- : (int, string) result = Error "Division_by_zero"      
</pre>
<p>Bien sûr un tel raffinement de style n&rsquo;est pas forcément utile ou même désirable dans chaque code ocaml. Le langage étant multi-paradigmes par nature il vous invite à trouver le style qui vous convient le mieux.</p>
<p>Cependant, avec cette introduction courte et informelle sur les récurseurs et les monades, j&rsquo;espère avoir donné quelques encouragements à ceux qui voudraient faire le grand saut vers un assistant de preuve.</p>
<p>&#8211; damien</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Plus de logos pour Rox-Filer</title>
		<link>https://blog.developpez.com/damien-guichard/p8809/programmation-fonctionnelle/plus_de_logos_pour_rox_filer_1</link>
		<comments>https://blog.developpez.com/damien-guichard/p8809/programmation-fonctionnelle/plus_de_logos_pour_rox_filer_1#comments</comments>
		<pubDate>Sat, 10 Apr 2010 14:45:20 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Divers]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans un précédent billet je vous expliquais comment créer un MIME pour les sources dans votre langage de programmation favori. Un MIME (Multipurpose Internet Mail Extension) est une information système pour identifier les types de fichier et leur affecter certains attributs comme une commande par défaut ou une icône personnalisée. Dans ce billet je vais encore plus loin en vous proposant directement un panel d&#8217;icônes taillées sur mesure pour le gestionnaire de fichiers ROX-Filer. Bien [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Dans un <a href="http://blog.developpez.com/damien-guichard/p8578/logiciel-libre/linux/personnalisez-vos-fichiers-source/#more8578" target="_blank">précédent billet</a> je vous expliquais comment créer un MIME pour les sources dans votre langage de programmation favori. </p>
<p>Un MIME (Multipurpose Internet Mail Extension) est une information système pour identifier les types de fichier et leur affecter certains attributs comme une commande par défaut ou une icône personnalisée.  </p>
<p>Dans ce billet je vais encore plus loin en vous proposant directement un panel d&rsquo;icônes taillées sur mesure pour le gestionnaire de fichiers <a href="http://fr.wikipedia.org/wiki/ROX-Filer" target="_blank">ROX-Filer</a>.</p>
<ul>
<li><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a>
</li>
<li><a href="http://haskell.org/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_haskell.png"/></a>
</li>
<li><a href="http://coq.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_coq1.png"/></a><a href="http://coq.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_coq2.png"/></a><a href="http://coq.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_coq3.png"/></a><a href="http://coq.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_coq4.png"/></a><a href="http://coq.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_coq5.png"/></a>
</li>
<li><a href="http://www.schemers.org/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_scheme.png"/></a>
</li>
<li><a href="http://fr.wikipedia.org/wiki/Lisp" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_lisp1.png"/></a>
</li>
<li><a href="http://www.scala-lang.org/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_scala1.png"/></a>
</li>
<li><a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_Fsharp.png"/></a>
</li>
</ul>
<p>Bien sûr si vous semblez frappé d&rsquo;injustice du fait que votre langage de programmation favori ne soit pas représenté, vous pouvez me faire une proposition que j&rsquo;ajouterai pour élargir la gamme de fichiers sources personnalisables.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Raincat, le chaton craintif</title>
		<link>https://blog.developpez.com/damien-guichard/p8795/programmation-fonctionnelle/raincat_le_chaton_craintif</link>
		<comments>https://blog.developpez.com/damien-guichard/p8795/programmation-fonctionnelle/raincat_le_chaton_craintif#comments</comments>
		<pubDate>Mon, 05 Apr 2010 19:01:41 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Logiciel Libre]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Ce n&#8217;est pas la première fois que je vous parle de jeu-vidéo et de programmation fonctionnelle. Cette fois il s&#8217;agit de Raincat, un jeu SDL écrit en Haskell, pour Windows et Linux. Le jeu consiste à déposer les accessoires (dans la colonne à droite) sur le parcours du chaton afin que celui-ci atteigne la sortie du niveau malgré la pluie et diverses projections d&#8217;eau. Car le Raincat est réellement hydrophobe, la moindre goutte sur son [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://haskell.org/" target="_blank"><img src="http://haskell.org/sitewiki/images/a/a8/Haskell-logo-60.png"/></a></center></p>
<p>Ce n&rsquo;est pas la première fois que je vous parle de jeu-vidéo et de programmation fonctionnelle.<br />
Cette fois il s&rsquo;agit de <a href="http://bysusanlin.com/raincat/" target="_blank">Raincat</a>, un jeu SDL écrit en <a href="http://haskell.org/" target="_blank">Haskell</a>, pour Windows et Linux.</p>
<p><center><img src="http://damien-guichard.developpez.com/illustrations/developpez_0107.jpg"/></center></p>
<p>Le jeu consiste à déposer les accessoires (dans la colonne à droite) sur le parcours du chaton afin que celui-ci atteigne la sortie du niveau malgré la pluie et diverses projections d&rsquo;eau. Car le Raincat est réellement hydrophobe, la moindre goutte sur son pelage délicat et vous devrez recommencer le niveau.</p>
<p>À vrai dire ce petit puzzle ne m&rsquo;a pas rendu accro. Maintenir un chaton propre et toujours au sec m&rsquo;apparaît difficilement comme un enjeu ludique motivant.  </p>
<p>Ce qui est peut être plus intéressant que le jeu en lui-même c&rsquo;est le témoignage que le fossé qui séparaient les langages académiques des applications quotidiennes se comble de jours en jours.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OCaml Meeting 2010 à Paris le 16 Avril</title>
		<link>https://blog.developpez.com/damien-guichard/p8721/programmation-fonctionnelle/ocaml_meeting_2010_a_paris_le_16_avril</link>
		<comments>https://blog.developpez.com/damien-guichard/p8721/programmation-fonctionnelle/ocaml_meeting_2010_a_paris_le_16_avril#comments</comments>
		<pubDate>Fri, 12 Mar 2010 16:23:33 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Objective Caml]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Sylvain Le Gall et l&#8217;équipe organisatrice de la 3ième rencontre des programmeurs Objective-Caml vous donnent rendez-vous le 16 Avril à Paris. Malheureusement je ne pourrai pas être présent cette année. Hello, For the third time, I am proud to invite all OCaml enthusiasts to join us at OCaml Meeting 2010 in Paris. This year event takes place in Paris on Friday 16th April 2010. Subscription is opened and will be closed on Friday 2nd April [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a></center></p>
<p><strong>Sylvain Le Gall</strong> et l&rsquo;équipe organisatrice de la 3ième rencontre des programmeurs Objective-Caml vous donnent rendez-vous le 16 Avril à Paris.</p>
<p>Malheureusement je ne pourrai pas être présent cette année. </p>
<p><span id="more-27"></span></p>
<p>Hello,</p>
<p>For the third time, I am proud to invite all OCaml enthusiasts to join<br />
us at OCaml Meeting 2010 in Paris.</p>
<p>This year event takes place in Paris on Friday 16th April 2010.<br />
Subscription is opened and will be closed on Friday 2nd April 2010.</p>
<p>Presentations include:</p>
<ul>
<li>Enforcing Type-Safe Linking using Inter-Package Relationships for<br />
  OCaml Debian packages</li>
<li>The Ocamlviz visualization toolkit</li>
<li>Cluster computing in Ocaml</li>
<li>Ocaml in a web startup</li>
<li>React, functional reactive programming for OCaml</li>
<li>OASIS, a Cabal like system for OCaml</li>
<li>OPA, same web, but with types and lambda</li>
<li>OC4MC, Objective Caml for MultiCore</li>
<li>Lwt, Cooperative Light-Weight Threads</li>
<li>naclgrid: the collaborative rendering farm, a JoCaml-powered<br />
  desktop grid</li>
</ul>
<p>The meeting is sponsored by INRIA, the Caml Consortium and OCamlCore.<br />
Inscription is free but the number of participants is limited.</p>
<p>Further information and inscriptions:</p>
<p>http://wiki.cocan.org/events/europe/ocamlmeetingparis2010</p>
<p>The day after OCaml Meeting, Mehdi Dogguy from PPS helps me to organize<br />
an informal day where OCaml teams can meet to work. We will have 2<br />
classrooms, each can host 45 persons. There will be an internet access<br />
and a blackboard in each room. Inscription is free.</p>
<p>Further information and inscriptions:</p>
<p>http://wiki.cocan.org/events/europe/ocamlhackingday2010</p>
<p>Hope to see a lot of you,</p>
<p>Regards,</p>
<p><strong>Sylvain Le Gall</strong> on behalf of the OCaml Meeting organization team.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Les files de priorité (les bases)</title>
		<link>https://blog.developpez.com/damien-guichard/p8644/programmation-fonctionnelle/les_files_de_priorite_les_bases</link>
		<comments>https://blog.developpez.com/damien-guichard/p8644/programmation-fonctionnelle/les_files_de_priorite_les_bases#comments</comments>
		<pubDate>Thu, 18 Feb 2010 16:54:03 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Objective Caml]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le tas binaire est un tableau qui implémente un arbre pseudo-complet vérifiant la propriété de tas. Un tableau est de taille fixe. Par conséquent un tas binaire est borné, on ne peut y insérer qu&#8217;un nombre fixe et limité d&#8217;éléments. Bien sûr on pourrait redimensionner le tableau dynamiquement, mais cela a un impact négatif sur le coût des opérations. Qu&#8217;on prêche le style impératif ou le style fonctionnel est étrangé à l&#8217;affaire. La bonne question [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a></center></p>
<p>Le tas binaire est un tableau qui implémente un arbre pseudo-complet vérifiant la propriété de tas.<br />
Un tableau est de taille fixe. Par conséquent un tas binaire est borné, on ne peut y insérer qu&rsquo;un nombre fixe et limité d&rsquo;éléments. Bien sûr on pourrait redimensionner le tableau dynamiquement, mais cela a un impact négatif sur le coût des opérations.<br />
Qu&rsquo;on prêche le style impératif ou le style fonctionnel est étrangé à l&rsquo;affaire.<br />
La bonne question c&rsquo;est de savoir si on connait d&rsquo;avance le nombre d&rsquo;éléments à insérer ou non. </p>
<p>Si on le connait alors un tas binaire fera très bien l&rsquo;affaire.<br />
Si on ne le connait pas, alors autant opter tout de suite pour un arbre binaire, même si on veut garder un style impératif.<br />
Ça serait exactement la même problématique avec un dictionnaire. On peut faire une recherche dichotomique dans un tableau trié. Ou alors on peut faire une recherche dans un arbre ordonnée.<br />
Dans les deux cas l&rsquo;algorithme de recherche est le même, il s&rsquo;agit dune boucle qui à chaque étape découpe l&rsquo;espace de recherche en deux moitiés dont une seule peut contenir l&rsquo;élément recherché.<br />
Le paradigme a bien un impact sur le programmeur mais c&rsquo;est parce que le programmeur est trop attaché à la syntaxe.<br />
En réalité le paradigme impacte plus fortement la façon de faire que la façon de penser.<br />
L&rsquo;expérience aussi est un facteur qui impacte la façon de faire.<br />
C&rsquo;est pourquoi je préfère parler de style plutôt que de paradigme.</p>
<p><span id="more-26"></span></p>
<h3 style="text-align: left">Le tas de Braun</h3>
<p>Un petit rappel de quelques définitions :</p>
<ul>
<li><a href="http://algo.developpez.com/faq/?page=types#structure_de_tas" target="_blank">propriété de tas</a></li>
<li><a href="http://algo.developpez.com/faq/?page=arbres#arbre_binaire_complet" target="_blank">arbre complet</a></li>
<li><a href="http://algo.developpez.com/faq/?page=arbres#arbre_braun" target="_blank">arbre de Braun</a></li>
</ul>
<p>On l&rsquo;appelle tas de Braun parce que l&rsquo;insertion répétée dans l&rsquo;arbre vide produit un arbre de Braun.<br />
Un autre nom est <em>heap-ordered binary tree</em> mais c&rsquo;est moins spécifique.</p>
<pre>

<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">type 'a heap = <br />
&nbsp; | E (* 'a empty heap *) <br />
&nbsp; | N of 'a non_empty_heap <br />
and 'a non_empty_heap = <br />
&nbsp; {mutable l: 'a heap; mutable e: 'a; mutable r: 'a heap}</div></div>

</pre>
<p>Remarques :</p>
<ul>
<li>on a un type tas non-vide, il n&rsquo;y aura pas d&rsquo;exceptions dans le code, la contrainte sur l&rsquo;argument des fonctions <em>find_max</em> et <em>remove_max</em> sera exprimée par le type, la contrainte sur le résultat de <em>insert</em> également</li>
<li>les champs sont mutables, c&rsquo;est parce qu&rsquo;on va utiliser le même type pour les deux styles de programmation, les algorithmes seront les mêmes, mais dans un cas on fera de la copie, dans l&rsquo;autre on fera de la modification sur place</li>
</ul>
<p>La fonction <em>find_max</em> est triviale :</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">let find_max {e=m} = m</div></div>
<h3 style="text-align: left">Le style fonctionnel</h3>
<p>On devrait dire le style immutable.<br />
Je commence toujours par le style immutable parce que c&rsquo;est plus lisible.<br />
J&rsquo;ai choisi un tas-max plutôt qu&rsquo;un tas-min, pour un tas-min il n&rsquo;y aura qu&rsquo;à changer le signe où inverser le signe de la fonction <em>compare</em>.</p>
<pre>

<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">let rec add x = function <br />
&nbsp; | E -&gt; <br />
&nbsp; &nbsp; &nbsp; {l=E;e=x;r=E} <br />
&nbsp; | N n -&gt; &nbsp;<br />
&nbsp; &nbsp; &nbsp; if compare n.e x &gt; 0 then {l=N (add x n.r);e=n.e;r=n.l} &nbsp;<br />
&nbsp; &nbsp; &nbsp; else {l=N (add n.e n.r);e=x;r=n.l} <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
let rec remove_max = function <br />
&nbsp; | {l=E;r=t} | {r=E;l=t} -&gt; <br />
&nbsp; &nbsp; &nbsp; t <br />
&nbsp; | {l=N l;e=e;r=N r} -&gt; <br />
&nbsp; &nbsp; &nbsp; if compare l.e r.e &gt; 0 then N {l=remove_max l;e=l.e;r=N r} <br />
&nbsp; &nbsp; &nbsp; else N {l=N l;e=r.e;r=remove_max r}</div></div>

</pre>
<h3 style="text-align: left">Le style impératif</h3>
<p>On devrait dire le style mutable.<br />
Je traduis à partir de la version en style immutable.</p>
<pre>

<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">let rec insert x = function <br />
&nbsp; | E -&gt; <br />
&nbsp; &nbsp; &nbsp; {l=E;e=x;r=E} <br />
&nbsp; | N n -&gt; <br />
&nbsp; &nbsp; &nbsp; let nr = n.r in <br />
&nbsp; &nbsp; &nbsp; n.r &lt;- n.l; <br />
&nbsp; &nbsp; &nbsp; if compare n.e x &gt; 0 then n.l &lt;- N (insert x nr) <br />
&nbsp; &nbsp; &nbsp; else (n.l &lt;- N (insert n.e nr); n.e &lt;- x); <br />
&nbsp; &nbsp; &nbsp; n <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
let rec delete_max h = <br />
&nbsp; match h with &nbsp;<br />
&nbsp; | {l=E;r=t} | {r=E;l=t} -&gt; <br />
&nbsp; &nbsp; &nbsp; t <br />
&nbsp; | {l=N l;e=e;r=N r} -&gt; <br />
&nbsp; &nbsp; &nbsp; if compare l.e r.e &gt; 0 then (h.e &lt;- l.e; h.l &lt;- delete_max l) &nbsp;<br />
&nbsp; &nbsp; &nbsp; else (h.e &lt;- r.e; h.r &lt;- delete_max r); <br />
&nbsp; &nbsp; &nbsp; N h</div></div>

</pre>
<h3 style="text-align: left">Autres opérations</h3>
<p>Il faut mentionner qu&rsquo;un tas de Braun offre des tas de possibilités de variantes et d&rsquo;extensions qui seraient bien plus difficiles à implanter à l&rsquo;aide d&rsquo;un tas binaire.<br />
Je ne vais pas être exhaustif sur ce point, je vais cependant en citer deux.<br />
Il est également possible de supprimer un élément arbitraire dans un tas en le faissant percoler jusqu&rsquo;à la racine puis en invoquant <em>remove_max</em>.</p>
<h3 style="text-align: left">La fusion </h3>
<p>Il est possible de fusionner deux tas de Braun en un seul tas.</p>
<pre>

<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">let rec join ha hb = <br />
&nbsp; match ha,hb with <br />
&nbsp; | t,E | E,t -&gt; <br />
&nbsp; &nbsp; &nbsp; t <br />
&nbsp; | N a,N b -&gt; <br />
&nbsp; &nbsp; &nbsp; if compare a.e b.e &gt; 0 then N {l=join a.l a.r;e=a.e;r=hb} <br />
&nbsp; &nbsp; &nbsp; else N {l=ha;e=b.e;r=join b.l b.r}</div></div>

</pre>
<p>On peut accélérer l&rsquo;opération de fusion à l&rsquo;aide d&rsquo;une technique dite de &laquo;&nbsp;structural bootstrapping&nbsp;&raquo;.<br />
Grâce à cette technique il est possible de fusionner deux tas simplement en insérant l&rsquo;un dans l&rsquo;autre.</p>
<h3 style="text-align: left">L&rsquo;arbre tournoi</h3>
<p>On peut modifier légèrement les opérations d&rsquo;insertion et de suppression pour que le tas restitue l&rsquo;ordre d&rsquo;insertion quand on le parcourre dans l&rsquo;ordre infixe.<br />
Toutefois cette modification a un impact sur la performance, le tas n&rsquo;est plus pseudo-complet comme un arbre de Braun.  </p>
<p>Typiquement on insère les scores dans l&rsquo;arbre tournoi, le gagnant est toujours à la racine.<br />
Le parcourt infixe restitue la liste des scores dans l&rsquo;ordre d&rsquo;apparition des joueurs.</p>
<pre>

<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">let rec add x = function <br />
&nbsp; | E -&gt; <br />
&nbsp; &nbsp; &nbsp; {l=E;e=x;r=E} <br />
&nbsp; | N n -&gt; &nbsp;<br />
&nbsp; &nbsp; &nbsp; if compare n.e x &gt; 0 then {n with r=N (add x n.r)} &nbsp;<br />
&nbsp; &nbsp; &nbsp; else {l=N n;e=x;r=E} <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
let rec remove_max = function <br />
&nbsp; | {l=E;r=t} | {r=E;l=t} -&gt; <br />
&nbsp; &nbsp; &nbsp; t <br />
&nbsp; | {l=N l;e=e;r=N r} as t -&gt; <br />
&nbsp; &nbsp; &nbsp; if compare l.e r.e &gt; 0 then <br />
&nbsp; &nbsp; &nbsp; &nbsp; N{l=l.l;e=l.e;r=remove_max {t with l=l.r}} <br />
&nbsp; &nbsp; &nbsp; else <br />
&nbsp; &nbsp; &nbsp; &nbsp; N{l=remove_max {t with r=r.l};e=r.e;r=r.r}</div></div>

</pre>
<h3 style="text-align: left">Conclusion</h3>
<p>La chose à retenir c&rsquo;est que ce n&rsquo;est pas le fonctionnel qui force à changer de structure de données.<br />
Ce qui force à changer de structure de données c&rsquo;est le fait qu&rsquo;un tableau n&rsquo;est pas toujours la meilleure option. Utiliser une liste ou un arbre au lieu d&rsquo;un tableau n&rsquo;interdit pas le style mutable.<br />
Il n&rsquo;y a pas un paradigme impératif qui s&rsquo;oppose à un paradigme impératif fonctionnel, il y a juste le style mutable et le style immutable qui sont deux façons d&rsquo;implanter un même algorithme pour une même structure de données.<br />
On peut d&rsquo;ailleurs très bien adopter le style immutable avec un langage à objets si le ramasse-miettes est suffisamment efficace pour ça.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qu&#8217;est-ce qu&#8217;un langage fonctionnel ?</title>
		<link>https://blog.developpez.com/damien-guichard/p8623/programmation-fonctionnelle/qu_est_ce_que_la_programmation_fonctionn</link>
		<comments>https://blog.developpez.com/damien-guichard/p8623/programmation-fonctionnelle/qu_est_ce_que_la_programmation_fonctionn#comments</comments>
		<pubDate>Fri, 12 Feb 2010 15:34:05 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Définition C&#8217;est comme pour un langage à objets, étant un paradigme riche il y a plusieurs définitions possibles pour un langage fonctionnel. Une définition possible: c&#8217;est un langage qui offre les fermetures (une fonction liée à un environnement d&#8217;évaluation). Avantage de cette définition: elle est tolérante. Inconvénient de cette définition: elle perd de sa pertinence au fur et à mesure que la plupart des langages à objets intègrent plus ou moins cette fonctionnalité. Une autre [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a></center></p>
<h3 style="text-align: left">Définition</h3>
<p>C&rsquo;est comme pour un langage à objets, étant un paradigme riche il y a plusieurs définitions possibles pour un langage fonctionnel. </p>
<p><strong>Une définition possible:</strong> c&rsquo;est un langage qui offre les fermetures (une fonction liée à un environnement d&rsquo;évaluation).<br />
Avantage de cette définition: elle est tolérante.<br />
Inconvénient de cette définition: elle perd de sa pertinence au fur et à mesure que la plupart des langages à objets intègrent plus ou moins cette fonctionnalité.</p>
<p><strong>Une autre définition possible:</strong> c&rsquo;est un langage avec un sytème de typage riche, riche au point qu&rsquo;il devienne insupportable de ne pas être assisté par une forme d&rsquo;inférence de type.<br />
Avantage: c&rsquo;est plus représentatif de la spécificité des langages fonctionnels modernes.<br />
Inconvénient: ça exclut les assembleurs de langages (macro-langages) que sont les vénérables Lisp et Scheme.</p>
<p><span id="more-6"></span></p>
<p>Autres définitions (plus techniques et plus ou moins équivalentes entre elles) :</p>
<ul>
<li>c&rsquo;est un langage inspiré du lambda calcul</li>
<li>c&rsquo;est un langage inspiré des catégories bi-cartésiennes fermées</li>
<li>c&rsquo;est un langage où Hom(A × B, C) = Hom(A, Hom(B,C))</li>
</ul>
<h3 style="text-align: left">Utilisation</h3>
<p>Typiquement les macro-langages font des merveilles pour prototyper la conception de nouveaux paradigmes (réflection, AOP et autre POO étendue ou exotique).<br />
Typiquement les langages à inférence de type font des merveilles pour implémenter les spécification algébriques et les algorithmes avancés.</p>
<p>Historiquement les langages à inférence de type sont très liés à la preuve de programme, ce qui les rends très lisibles dès lors qu&rsquo;on est familier avec leurs concepts exotiques (du point de vue d&rsquo;un programmeur POO) et la syntaxe particulière qui va avec.<br />
Mais aujourd&rsquo;hui la programmation fonctionnelle s&rsquo;est élargie et démocratisée et on peut quasiment tout faire avec, y compris des jeux SDL, Allegro ou SFML, de la 3D OpenGL, de la programmation système, du web et bien d&rsquo;autres choses encore. </p>
<h3 style="text-align: left">Avenir académique </h3>
<p>Au niveau académique la programmation par objets n&rsquo;est plus un domaine vraiment actif, pour plusieurs raisons :</p>
<ul>
<li>la recherche sur la POO avait beaucoup exploré toutes sortes de variantes exotiques de la sémantique de l&rsquo;envoi de messages, en pratique aucune variante n&rsquo;a été assez convaincante pour éclipser le fait que le modèle d&rsquo;exécution de C++ est le plus performant</li>
<li>il est plus fructueux d&rsquo;associer une extension objets à un langage fonctionnel que le contraire</li>
<li>même si en lui-même le paradigme fonctionnel n&rsquo;apporte pas la solution à la question du parallélisme, au moins il repose sur un modèle théorique plus simple qui permet de se concentrer sur le coeur de la difficulté</li>
<li>le modèle du lambda-calcul est tellement simple qu&rsquo;il se prête à d&rsquo;infinies variantes / extensions, potentiellement porteuses de nouveaux paradigmes (voir <a href="http://bondi.it.uts.edu.au/">Bondi</a> par exemple), éventuellement ces expérimentations connaîtront le même sort que les expérimentations sur l&rsquo;envoi de message mais il est trop tôt pour l&rsquo;affirmer aujourd&rsquo;hui</li>
</ul>
<h3 style="text-align: left">Avenir industriel</h3>
<p>La programmation fonctionnelle a déjà réussi dans le sens où la plupart des langages à objets sont dotés (ou envisagent de se doter) d&rsquo;une extension offrant les fermetures. Cependant l&rsquo;influence de la programmation fonctionnelle va déjà bien au delà et les nouveaux langages à objets (Scala,F#,Clojure,Groovy,Go) sont ouvertement influencés par les langages fonctionnels. L&rsquo;industrie a plébiscité l&rsquo;objet et continuera de le faire mais d&rsquo;une façon moins dogmatique qui ouvre la voie aux approches mixtes objet / fonctionnel.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Personnalisez vos fichiers source</title>
		<link>https://blog.developpez.com/damien-guichard/p8578/programmation-fonctionnelle/objective-caml/personnalisez_vos_fichiers_source</link>
		<comments>https://blog.developpez.com/damien-guichard/p8578/programmation-fonctionnelle/objective-caml/personnalisez_vos_fichiers_source#comments</comments>
		<pubDate>Sat, 30 Jan 2010 15:56:10 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Objective Caml]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Un MIME (Multipurpose Internet Mail Extension) est une information système pour identifier les types de fichier et leur affecter certains attributs comme une commande par défaut ou une icône personnalisée. Ce billet vous propose d&#8217;agrémenter votre station de développement Objective-Caml à l&#8217;aide d&#8217;un MIME pour vos fichiers source. Bien sûr ça n&#8217;est qu&#8217;un exemple que vous pourrez adapter à votre application ou à votre langage de programmation favori. D&#8217;abord un avertissement : l&#8217;ajout de MIMEs [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://damien-guichard.developpez.com/logos/logo_caml.png"/></a></center></p>
<p>Un MIME (Multipurpose Internet Mail Extension) est une information système pour identifier les types de fichier et leur affecter certains attributs comme une commande par défaut ou une icône personnalisée.  </p>
<p>Ce billet vous propose d&rsquo;agrémenter votre station de développement <a href="http://caml.inria.fr/" target="_blank">Objective-Caml</a> à l&rsquo;aide d&rsquo;un MIME pour vos fichiers source.<br />
Bien sûr ça n&rsquo;est qu&rsquo;un exemple que vous pourrez adapter à votre application ou à votre langage de programmation favori.</p>
<p><span id="more-12"></span></p>
<p>D&rsquo;abord un <strong>avertissement</strong> :</p>
<ul>
<li> l&rsquo;ajout de MIMEs est une opération potentiellement dangereuse, en effet si vous perdez tous vos MIMEs vous ne pourrez plus monter un volume en cliquant sur son icône et vous devrez retourner à la console pour réaliser la plupart des opérations mêmes les plus élémentaires</li>
<li> tapez la commande <ins>update-mime-database /usr/share/mime</ins> dans une console </li>
<li> si cette commande n&rsquo;est pas reconnue alors votre système ne gère pas la mise à jour des MIMEs et vous devrez opérer à la main, à condition de savoir ce que vous faites </li>
</ul>
<p>Sinon créez un fichier <ins>/usr/share/mime/packages/ocaml.xml</ins> et éditez-le avec ce contenu :</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">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt; <br />
&lt;mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'&gt; <br />
&nbsp; &lt;mime-type type=&quot;text/ocaml-source&quot;&gt; <br />
&nbsp; &nbsp; &lt;comment&gt;Objective-Caml source&lt;/comment&gt; <br />
&nbsp; &nbsp; &lt;glob pattern=&quot;*.ml&quot;/&gt; <br />
&nbsp; &lt;/mime-type&gt; <br />
&nbsp; &lt;mime-type type=&quot;text/ocaml-interface&quot;&gt; <br />
&nbsp; &nbsp; &lt;comment&gt;Objective-Caml interface&lt;/comment&gt; <br />
&nbsp; &nbsp; &lt;glob pattern=&quot;*.mli&quot;/&gt; <br />
&nbsp; &lt;/mime-type&gt; <br />
&lt;/mime-info&gt;</div></div>
<p>Puis exécutez la commande <ins>update-mime-database /usr/share/mime</ins>.</p>
<p>Vous pouvez alors définir tous les paramètres liés à un MIME comme une icône personnalisée et une action par défaut pour votre gestionnaire de fichiers.</p>
<p>Par exemple définir une icône personnalisée pour <strong>ROX-filer</strong> :</p>
<ul>
<li> sauvez le fichier image en tête de cet article </li>
<li> sélectionnez le menu <ins>File/Set Icon&#8230;</ins> sur un fichier <strong>*.ml</strong> </li>
<li> cochez la case <ins>Pour tous les fichiers de type &lsquo;text/ocaml-source</ins> </li>
<li> lâchez l&rsquo;image sur la zone réservée à cet effet</li>
</ul>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qualification à l&#8217;intérieur des modules</title>
		<link>https://blog.developpez.com/damien-guichard/p8514/programmation-fonctionnelle/qualification_a_l_interieur_des_modules_1</link>
		<comments>https://blog.developpez.com/damien-guichard/p8514/programmation-fonctionnelle/qualification_a_l_interieur_des_modules_1#comments</comments>
		<pubDate>Tue, 12 Jan 2010 19:28:44 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Objective Caml]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le billet d&#8217;aujourd&#8217;hui a pour but de faire toute la lumière sur la qualification à l&#8217;intérieur des modules Objective-Caml. Un module paramétré est un module-fonction, c&#8217;est-à-dire une fonction d&#8217;un module-type vers un module-type qui accepte un module-valeur pour argument réel. La définition d&#8217;un module paramétré conduit fréquemment à ce genre de code où Graphics est l&#8217;argument formel du module-fonction Draw. module type Graphics = sig type color = Black &#124; White type point = {x:int;y:int} [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><center><a href="http://caml.inria.fr/" target="_blank"><img src="http://caml.inria.fr//pub/logos/caml-inria-fr.128x58.gif"/></a></center></p>
<p>Le billet d&rsquo;aujourd&rsquo;hui a pour but de faire toute la lumière sur la qualification à l&rsquo;intérieur des modules Objective-Caml.</p>
<p><span id="more-25"></span></p>
<p>Un module paramétré est un module-fonction, c&rsquo;est-à-dire une fonction d&rsquo;un module-type vers un module-type qui accepte un module-valeur pour argument réel.</p>
<p>La définition d&rsquo;un module paramétré conduit fréquemment à ce genre de code où Graphics est l&rsquo;argument formel du module-fonction Draw. </p>
<pre>
module type Graphics
  =
  sig
    type color = Black | White
    type point = {x:int;y:int}
    val draw_line : int -> int -> int -> int -> unit
  end

module Draw (G: Graphics)
  =
  struct
    let pen = Black
    let background = White
    let connect a b = G.draw_line a.x a.y b.x b.y 
  end
</pre>
<p>Au premier abord il est surprenant qu&rsquo;OCaml n&rsquo;accepte pas ce code.<br />
Il ne l&rsquo;accepte pas pour deux raisons similaires :  </p>
<ul>
<li>les couleurs Black et White ne sont pas définies dans le module Draw</li>
<li>les champs x et y ne sont pas définis dans le module Draw</li>
</ul>
<p>Le contournement évident consiste à tout qualifier par le module G.</p>
<pre>
module Draw (G: Graphics)
  =
  struct
    let pen = G.Black
    let background = G.White
    let connect a b = G.draw_line a.G.x a.G.y b.G.x b.G.y 
  end
</pre>
<p>Une fois tout qualifié par le module G ocaml accepte le code.<br />
Mais cette solution peut vite devenir assez lourde.<br />
Il y a d&rsquo;autres moyens pour soulager la notation.</p>
<p>Un moyen classique consiste à ouvrir le module G de façon à accéder à ses définitions sans avoir à qualifier systématiquement.</p>
<pre>
module Draw (G: Graphics)
  =
  struct
    open G
    let pen = Black
    let background = White
    let connect a b = draw_line a.x a.y b.x b.y 
  end
</pre>
<p>Toutefois un reproche que l&rsquo;on peut faire à l&rsquo;ouverture de module c&rsquo;est qu&rsquo;on ouvre tout ou rien. Il n&rsquo;est pas possible, à l&rsquo;aide d&rsquo;<strong>open</strong>, d&rsquo;ouvrir le type <em>G.point</em> parce que les champs <em>G.x</em> et <em>G.y</em> impactent beaucoup la lisibilité mais de laisser le type <em>G.color</em> fermé parce que <em>G.Black</em> et <em>G.White</em> ne sont pas très gênants.<br />
Ça n&rsquo;est pas possible à l&rsquo;aide d&rsquo;<strong>open</strong> mais ça l&rsquo;est à l&rsquo;aide d&rsquo;une égalité de types.<br />
L&rsquo;idée c&rsquo;est de déclarer un type <em>point</em> équivalent au type <em>G.point</em>.<br />
Ce type local agira comme un alias pour le type <em>G.point</em>.<br />
De cette façon le module G reste fermé mais on peut accéder directement aux composantes x et y sans les qualifier.</p>
<pre>
module Draw (G: Graphics)
  =
  struct
    type point = G.point = {x:int;y:int}
    let pen = G.Black
    let background = G.White
    let connect a b = G.draw_line a.x a.y b.x b.y 
  end
</pre>
<p>En allant jusqu&rsquo;au bout de cette logique on peut carrément inclure le module G, dans ce cas le module Draw contient une copie complète du module G et il n&rsquo;y a plus rien à qualifier.</p>
<pre>
module Draw (G: Graphics)
  =
  struct
    include G
    let pen = Black
    let background = White
    let connect a b = draw_line a.x a.y b.x b.y 
  end
</pre>
<p>Attention toutefois à ne pas abuser du <strong>include</strong> là où un <strong>open</strong> ferait très bien l&rsquo;affaire.<br />
Le <strong>include</strong> ajoute tout le module à l&rsquo;interface du module en cours.<br />
Il a donc un effet à l&rsquo;extérieur du module alors que l&rsquo;effet de <strong>open</strong> est limité à l&rsquo;intérieur.<br />
N&rsquo;utilisez <strong>include</strong> que si c&rsquo;est nécessaire pour implanter l&rsquo;interface voulue, si vous n&rsquo;avez que besoin d&rsquo;alléger la qualification dans l&rsquo;implantation alors c&rsquo;est <strong>open</strong> qu&rsquo;il vous faut.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello Developpez ! avec LibGlade/XML</title>
		<link>https://blog.developpez.com/damien-guichard/p7748/programmation-fonctionnelle/hello_developpez_avec_libglade_xml_1</link>
		<comments>https://blog.developpez.com/damien-guichard/p7748/programmation-fonctionnelle/hello_developpez_avec_libglade_xml_1#comments</comments>
		<pubDate>Mon, 15 Jun 2009 14:49:50 +0000</pubDate>
		<dc:creator><![CDATA[SpiceGuid]]></dc:creator>
				<category><![CDATA[Logiciel Libre]]></category>
		<category><![CDATA[Objective Caml]]></category>
		<category><![CDATA[Programmation fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Hier, afin d&#8217;illustrer l&#8217;usage de LablGtk2, le binding GTK+ pour le langage Objective-Caml j&#8217;ai posté le code de ce Hello Developpez tout ce qu&#8217;il y a de plus basique : Toutefois, une comparaison ligne à ligne avec la version Gtk2Hs pour Haskell, grâcieusement postée par Alp, n&#8217;était pas possible puisque mon code n&#8217;utilisait pas libglade. On pourrait se demander pour quelle raison utiliser libglade car OCaml est un langage statiquement typé particulièrement sûr comparé à [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://caml.inria.fr/" target="_blank"><img src="http://caml.inria.fr//pub/logos/caml-inria-fr.128x58.gif"/></a></p>
<p>Hier, afin d&rsquo;illustrer l&rsquo;usage de <a href="http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/lablgtk.html" target="_blank">LablGtk2, le binding GTK+</a> pour le <a href="http://caml.inria.fr/" target="_blank">langage Objective-Caml</a> j&rsquo;ai posté le code de ce Hello Developpez tout ce qu&rsquo;il y a de plus basique :</p>
<p><img src="http://damien-guichard.developpez.com/illustrations/developpez_0077.jpg"/></p>
<p>Toutefois, une comparaison ligne à ligne avec <a href="http://blog.developpez.com/alp/p7737/programmation-fonctionnelle/hello-gtk2hs/#more7737" target="_blank">la version Gtk2Hs pour Haskell</a>, grâcieusement postée par <strong>Alp</strong>, n&rsquo;était pas possible puisque mon code n&rsquo;utilisait pas <em>libglade</em>. </p>
<p><span id="more-11"></span></p>
<p>On pourrait se demander pour quelle raison utiliser libglade car OCaml est un langage statiquement typé particulièrement sûr comparé à un fichier XML chargé dynamiquement et qui pourrait être modifié sans contrôle à tout moment. On pourrait argumenter qu&rsquo;il est bon de séparer le visuel de l&rsquo;interface et sa logique interne mais là encore le système de modules de OCaml est particulièrement bien adapté pour le <em>separation of concerns</em>.<br />
L&rsquo;intérêt indiscutable c&rsquo;est la flexibilité, en particulier l&rsquo;internationalisation est bien plus facile à réaliser que si elle était codée en dur. Et puis après tout la question n&rsquo;est pas là, c&rsquo;est à la mode, on peut le faire en Haskell, on peut le faire en OCaml, c&rsquo;est facile à faire et ça justifie bien un nouveau billet blog. </p>
<p>Mon fichier XML est en tous points identique à celui de <strong>Alp</strong> :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;?xml version=&quot;1.0&quot;?&gt; <br />
&lt;glade-interface&gt; &nbsp;<br />
&nbsp; &lt;!-- interface-requires gtk+ 2.16 --&gt; &nbsp;<br />
&nbsp; &lt;!-- interface-naming-policy project-wide --&gt; &nbsp;<br />
&nbsp; &lt;widget class=&quot;GtkWindow&quot; id=&quot;window1&quot;&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Hello, Developpez !&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;default_width&quot;&gt;400&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;default_height&quot;&gt;400&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;child&gt; &nbsp;<br />
&nbsp; &lt;widget class=&quot;GtkButton&quot; id=&quot;yo&quot;&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;label&quot; translatable=&quot;yes&quot;&gt;Bonjour Developpez, comment vas-tu ? &nbsp;<br />
&nbsp;<br />
Je suis un programme OCaml qui utilise <br />
LablGtk2, le binding GTK+ pour OCaml. <br />
&nbsp;<br />
Clique pour fermer.&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;visible&quot;&gt;True&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;can_focus&quot;&gt;True&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;property name=&quot;receives_default&quot;&gt;True&lt;/property&gt; &nbsp;<br />
&nbsp; &lt;/widget&gt; &nbsp;<br />
&nbsp; &lt;/child&gt; &nbsp;<br />
&nbsp; &lt;/widget&gt; &nbsp;<br />
&lt;/glade-interface&gt;</div></div>
<p>Faites attention à ce que la balise <strong>?xml</strong> soit bien sur la toute 1ière ligne du fichier sinon OCaml génèrera un avertissement et/ou une exception.</p>
<p>Le code source OCaml pour charger le XML et quitter quand l&rsquo;utilisateur clique sur le bouton : </p>
<pre>
let xml =
   Glade.create ~file:"hello.glade" ()
in let window = new GWindow.window
   (GtkWindow.Window.cast(Glade.get_widget xml "window1"))
in let button = new GButton.button
   (GtkButton.Button.cast(Glade.get_widget xml "yo")
in button#connect#clicked ~callback:
   (fun () -> print_endline "Bye"; window#destroy (); GMain.Main.quit ());
   window#show ();
   GMain.Main.main ()
</pre>
<p>La différence principale avec <strong>Gtk2Hs</strong>, hormis l&rsquo;absence de la <strong>do</strong>-notation, se situe au niveau du chargement et de la conversion.<br />
C&rsquo;est légèrement plus tortueux qu&rsquo;en Gtk2Hs, ça se fait en 3 étapes. C&rsquo;est dû à la couche orienté-objet de LablGtk.</p>
<ol>
<li> on charge le gadget à l&rsquo;aide de <em>Glade.get_widget</em>, on obtient un <em>Gtk.widget Gtk.obj</em></li>
<li> on converti ce <em>Gtk.widget Gtk.obj</em> en <em>Gtk.window Gtk.obj</em> à l&rsquo;aide de <em>GtkWindow.Window.cast</em> </li>
<li> ça ne s&rsquo;arrête pas là, il n&rsquo;est toujours pas possible d&rsquo;utiliser cette fenêtre avec les méthodes de LablGtk parce qu&rsquo;un <em>Gtk.window Gtk.obj</em> est une valeur mais pas un objet. il faut une deuxième conversion en un objet <em>GWindow.window</em>, en fait une instanciation réalisée par <strong>new GWindow.window</strong></li>
</ol>
<p>Voilà, ça n&rsquo;était pas sorcier mais comme il faut naviguer dans une doc hyper-texte touffue et avare en explication, la première fois c&rsquo;est toujours un peu déroutant.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
