<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-17133288</id><updated>2011-12-28T16:47:01.099+01:00</updated><category term='libertés'/><category term='conf'/><category term='yacc'/><category term='flash'/><category term='hack'/><category term='radio'/><category term='english'/><category term='web'/><category term='inférence'/><category term='liquidsoap'/><category term='anarchie'/><category term='caml'/><category term='informatique'/><category term='geek'/><category term='bd'/><category term='wtf'/><category term='general'/><category term='electronique'/><category term='musique'/><category term='types'/><category term='voyage'/><category term='rien'/><category term='mylife'/><category term='velo'/><category term='audio'/><category term='jeu'/><category term='logique'/><category term='these'/><category term='réalité'/><category term='programmation'/><category term='internet'/><category term='design'/><category term='ocaml'/><category term='code'/><category term='savonet'/><category term='philo'/><category term='open-source'/><category term='hardware'/><category term='science'/><title type='text'>Blogue à tabac</title><subtitle type='html'>Journal d'un pingouin à côté de la plaque comme il se doit, thésard en info, geekesque de l'avis de tous, abracadabrant selon certains, etc.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default?start-index=101&amp;max-results=100'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>181</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17133288.post-4176747826471623224</id><published>2011-05-10T20:36:00.005+02:00</published><updated>2011-05-10T20:40:27.486+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wtf'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Le web et la sémantique</title><content type='html'>Amis familiers des grands laboratoires d'informatique, cherchez l'erreur...&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-QCccoPLHOy0/TcmGG9xvAxI/AAAAAAAAAC4/EMd0rckc1ks/s1600/web_semantique.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="236" width="400" src="http://2.bp.blogspot.com/-QCccoPLHOy0/TcmGG9xvAxI/AAAAAAAAAC4/EMd0rckc1ks/s400/web_semantique.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4176747826471623224?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4176747826471623224/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4176747826471623224' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4176747826471623224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4176747826471623224'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2011/05/le-web-semantique.html' title='Le web et la sémantique'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-QCccoPLHOy0/TcmGG9xvAxI/AAAAAAAAAC4/EMd0rckc1ks/s72-c/web_semantique.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-1328446157947472531</id><published>2011-01-17T22:55:00.011+01:00</published><updated>2011-01-18T13:59:22.440+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Gestion de code</title><content type='html'>De lecture en lecture sur le web, je me suis récemment débloqué sur une question relative à l'organisation du développement logiciel...&lt;br /&gt;&lt;br /&gt;Quand on élabore du code, on a des contraintes contradictoires:&lt;ul&gt;&lt;li&gt;&lt;b&gt;Commiter souvent&lt;/b&gt; pour ne pas perdre du code qui marche, ainsi que pour communiquer et faire tester du code en cours d'élaboration.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Avoir une base de code propre&lt;/b&gt; pour que les gens puissent récupérer une version récente mais stable du code, et pour que l'historique soit propre.&lt;/li&gt;&lt;/ul&gt;&lt;small&gt;On pourrait rajouter une dernière contrainte: coder au lieu de procrastiner sur des questions d'organisation de code...&lt;/small&gt;&lt;br /&gt;Pour reformuler le second point, il s'agit d'assurer d'une part la qualité du code à un instant donné (ce qui nécessite une distinction entre code expérimental et code stable validé) et d'autre part d'assurer la tracabilité et le suivi du code dans le temps, c'est à dire la lisibilité de l'historique des modifications (principalement pour le code stable). L'objectif est que ce qui constitue moralement une seule modification ne soit pas explosé sur plusieurs commits. En particulier, on ne veut pas des corrections suivant trop souvent un commit hâtif. Avoir un historique propre simplifie la tâche quand on cherche à comprendre un bout de code (voir d'où vient telle partie du code) ou quand on liste les modifications avant de releaser une nouvelle version. Cela simplifie aussi la vie de ceux qui surveillent les modifications du code -- c'est la raison principale de mon obsession pour ce problème car je m'attache à suivre les commits effectués sur liquidsoap, en tout cas ceux qui touchent des modules critiques ou dans lesquels je suis impliqué. En fait, avec un historique propre on a des chances d'avoir plus de personnes qui suivent de près l'évolution du code et sont susceptibles de détecter des problèmes.&lt;br /&gt;&lt;br /&gt;Bien sûr, une partie de la réponse est apportée par la notion de branche. Mais cela n'aide pas du tout pour ce qui est de la gestion de l'historique. Sur ce point, on peut essayer de concevoir un système avec plusieurs dépôts: le dépôt expérimental dont le code n'est pas testé et l'historique est fragmenté, et le dépôt stable où le code est propre et les modifications sont regroupées pour avoir un historique clair. Mais cela fonctionne très mal: pour le transport des modifications vers le dépôt stable, il faut développer un nouvel outil; pour le transport dans l'autre sens, il faut faire face à tout un tas de problèmes. En bref, cette solution est nulle car elle nous prive de l'aide des outils de gestion de code actuels.&lt;br /&gt;&lt;br /&gt;Au fond il n'y a qu'une solution pour maintenir un historique propre: l'édition d'historique. Comme le nom l'indique, il s'agit de modifier l'historique des modifications après coup: on fait quelques commits, on attend du feedback, on trouve un bug, et quand tout a l'air propre on réduit tout ça en un seul commit bien clair.&lt;br /&gt;&lt;br /&gt;Le gros problème c'est que l'édition d'historique peut interférer assez mal avec la gestion de code distribuée: si on a deux copies d'un dépôt, et qu'on change l'historique dans l'un, il devient difficile de suivre certaines modifications relatives à l'ancien historique dans l'autre. J'illustre ceci sur un exemple plus bas, mais l'idée générale est qu'on ne devrait modifier que des parties de l'historique dont personne ne dépendra jamais plus. Cela exclut de travailler avec une branche expérimentale dont on manipule l'historique avant le report des modifications dans la branche stable, car cela désynchroniserait les différents dépôts où l'on continue de travailler dans la branche. Même avec une branche expérimentale par développeur, le développeur ne pourrait plus continuer de travailler dans sa branche après l'édition d'historique. Il n'y a que deux situations où l'édition d'historique est utilisable: soit on parle d'une suite de modifications qui n'ont jamais été publiées, soit on parle d'une suite de modifications publiées mais qui n'auront plus de descendants.&lt;br /&gt;&lt;br /&gt;J'étais bloqué à ce stade depuis un moment. J'avais découvert mercurial, l'édition d'historique, la gestion facilitée des branches, les commits locaux, etc. Mais je ne trouvais pas de solution à mon problème. Jusqu'à ce que je lise &lt;a href="http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html"&gt;A Git Workflow for Agile teams&lt;/a&gt; qui fait pile ce que je veux. La clé est de vraiment faire PLEIN de branches: une par feature ou bug. Quand on a fini de préparer la modification, au moment d'intégrer les modifications dans la branche principale, on peut éditer l'historique et personne ne touche plus à la branche. Pour penser à ça, il faut vraiment oublier les SCM comme SVN, où gérer une branche est pénible, et être habitué à un SCM distribué, où c'est censé être tout naturel.&lt;br /&gt;&lt;br /&gt;Je vous refais la recette, en français et en mercurial... Vous pouvez quand même lire l'&lt;a href="http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html"&gt;article original&lt;/a&gt;, qui dit quelques choses en plus, notamment la correspondance entre branches et tickets/issues.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Un exemple&lt;/h3&gt;&lt;br /&gt;On a Alice et Bob qui bossent sur le même projet. Ils ont tous les deux contribué dans la branche &lt;code&gt;123-new-feature&lt;/code&gt;, chacun un commit. L'historique ressemble à ça:&lt;br /&gt;&lt;pre&gt;@  changeset:   3:f3a6c5394605&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  parent:      0:11575ff21a29&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:34:05 2011 +0100&lt;br /&gt;|  summary:     Dummy&lt;br /&gt;|&lt;br /&gt;| o  changeset:   2:c6dc5c92d631&lt;br /&gt;| |  branch:      123-new-feature&lt;br /&gt;| |  user:        Bob &lt;b@o.b&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;| |  summary:     Plus expressif!&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   1:fafdcd7dccf5&lt;br /&gt;|/   branch:      123-new-feature&lt;br /&gt;|    user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|    date:        Tue Jan 11 15:11:40 2011 +0100&lt;br /&gt;|    summary:     Nicer.&lt;br /&gt;|&lt;br /&gt;o  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Alice et Bob sont satisfaits de leur code, Alice va donc fusionner les deux commits et les passer dans &lt;code&gt;default&lt;/code&gt;. On utilise l'option &lt;code&gt;--keep&lt;/code&gt; pour ne pas détruire tout de suite la branche. En gros on prend le noeud 1 et ses ancetres, on fusionne, et on recolle la modification résultante sur le noeud 3.&lt;br /&gt;&lt;pre&gt;$ hg rebase --collapse --keep --source 1 --dest 3&lt;br /&gt;&lt;br /&gt;@  changeset:   4:2bf346072a24&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;|  summary:     Plus joli et plus expressif!&lt;br /&gt;|&lt;br /&gt;o  changeset:   3:f3a6c5394605&lt;br /&gt;|  parent:      0:11575ff21a29&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:34:05 2011 +0100&lt;br /&gt;|  summary:     Dummy&lt;br /&gt;|&lt;br /&gt;| o  changeset:   2:c6dc5c92d631&lt;br /&gt;| |  branch:      123-new-feature&lt;br /&gt;| |  user:        Bob &lt;b@o.b&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;| |  summary:     Plus expressif!&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   1:fafdcd7dccf5&lt;br /&gt;|/   branch:      123-new-feature&lt;br /&gt;|    user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|    date:        Tue Jan 11 15:11:40 2011 +0100&lt;br /&gt;|    summary:     Nicer.&lt;br /&gt;|&lt;br /&gt;o  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A ce stade on peut même carrément virer la branche du dépôt. Les données correspondantes seront alors perdues pour toujours.&lt;br /&gt;&lt;pre&gt;$ hg strip 1&lt;br /&gt;&lt;br /&gt;@  changeset:   2:2bf346072a24&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;|  summary:     Plus joli et plus expressif!&lt;br /&gt;|&lt;br /&gt;o  changeset:   1:f3a6c5394605&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:34:05 2011 +0100&lt;br /&gt;|  summary:     Dummy&lt;br /&gt;|&lt;br /&gt;o  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;C'est tout beau! Mais si Alice a détruit sa branche, cela ne se propagera pas chez Bob. Au contraire, si Alice se synchronise avec Bobe elle récupérerait la branche, qui apparait en fait comme étant nouvelle pour son dépôt qui en a perdu toute trace.&lt;br /&gt;&lt;br /&gt;Si on pousse les modifications d'Alice chez Bob (éventuellement vai un dépôt central) la modification numéro 2 va être transmise. La branche &lt;code&gt;123-new-feature&lt;/code&gt; reste dans les autres dépôts  -- en d'autres termes l'historique n'est pas lui même versionné. Bob pourrait donc faire d'autres modifications dans la branche, ce qui n'est bien sûr pas trop souhaitable...&lt;br /&gt;&lt;pre&gt;# Bob fait une modif (#3) et la commite&lt;br /&gt;&lt;br /&gt;o  changeset:   5:2bf346072a24&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;|  summary:     Plus joli et plus expressif!&lt;br /&gt;|&lt;br /&gt;o  changeset:   4:f3a6c5394605&lt;br /&gt;|  parent:      0:11575ff21a29&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:34:05 2011 +0100&lt;br /&gt;|  summary:     Dummy&lt;br /&gt;|&lt;br /&gt;| @  changeset:   3:b37a07ad9982&lt;br /&gt;| |  branch:      123-new-feature&lt;br /&gt;| |  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:39:38 2011 +0100&lt;br /&gt;| |  summary:     Never enough of that.&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   2:c6dc5c92d631&lt;br /&gt;| |  branch:      123-new-feature&lt;br /&gt;| |  user:        Bob &lt;b@o.b&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;| |  summary:     Plus expressif!&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   1:fafdcd7dccf5&lt;br /&gt;|/   branch:      123-new-feature&lt;br /&gt;|    user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|    date:        Tue Jan 11 15:11:40 2011 +0100&lt;br /&gt;|    summary:     Nicer.&lt;br /&gt;|&lt;br /&gt;o  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si maintenant on pousse les modifications de Bob à Alice, on a la situation suivante, où les modifications individuelles de la "vieille" branche sont suivies d'une nouvelle modification...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;o  changeset:   5:b37a07ad9982&lt;br /&gt;|  branch:      123-new-feature&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:39:38 2011 +0100&lt;br /&gt;|  summary:     Never enough of that.&lt;br /&gt;|&lt;br /&gt;o  changeset:   4:c6dc5c92d631&lt;br /&gt;|  branch:      123-new-feature&lt;br /&gt;|  user:        Bob &lt;b@o.b&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;|  summary:     Plus expressif!&lt;br /&gt;|&lt;br /&gt;o  changeset:   3:fafdcd7dccf5&lt;br /&gt;|  branch:      123-new-feature&lt;br /&gt;|  parent:      0:11575ff21a29&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:11:40 2011 +0100&lt;br /&gt;|  summary:     Nicer.&lt;br /&gt;|&lt;br /&gt;| o  changeset:   2:2bf346072a24&lt;br /&gt;| |  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:15:26 2011 +0100&lt;br /&gt;| |  summary:     Plus joli et plus expressif!&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   1:f3a6c5394605&lt;br /&gt;|/   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|    date:        Tue Jan 11 15:34:05 2011 +0100&lt;br /&gt;|    summary:     Dummy&lt;br /&gt;|&lt;br /&gt;@  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pour réparer cela, il faudrait reporter uniquement la modification 5 sur 2. Mais le but est que cela n'arrive pas, si les développeurs sont bien organisés. Par exemple, plutôt que de détruire la branche, il vaut mieux la garder, et utiliser la possibilité de &lt;em&gt;fermer&lt;/em&gt; une branche dans mercurial (&lt;code&gt;hg commit --close-branch&lt;/code&gt;). On peut imaginer que les très branches sont effacées périodiquement de tous les dépôts, quand il n'y a plus de souci possible.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Rebase sur un ancêtre&lt;/h3&gt;&lt;br /&gt;De façon pas très uniforme, le rebase de mercurial ne permet pas que la cible soit un ancetre de la source. C'est à dire que si on commence une branche alternative, et qu'on ne fait pas de modification dans la branche principale, on ne peut pas faire de rebase de la nouvelle branche dans la principale. Faire un simple merge ne nous permet pas de fusionner les différentes modifications. Il faut donc utiliser une routine un peu différente.&lt;br /&gt;&lt;br /&gt;D'abord on se place dans la branche principale: &lt;code&gt;hg update default&lt;/code&gt;. Ensuite, sans changer notre position dans l'historique, on applique sur nos fichiers les modifs appliquées dans l'autre branche: &lt;code&gt;hg revert -r tip --all&lt;/code&gt;. Enfin, on commit ces modifications en une fois: &lt;code&gt;hg ci -m "Combined."&lt;/code&gt;. Voila, 1 et 2 sont devenus 3:&lt;br /&gt;&lt;pre&gt;@  changeset:   3:b29ddaf6c31c&lt;br /&gt;|  tag:         tip&lt;br /&gt;|  parent:      0:11575ff21a29&lt;br /&gt;|  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|  date:        Tue Jan 11 15:57:58 2011 +0100&lt;br /&gt;|  summary:     Combined.&lt;br /&gt;|&lt;br /&gt;| o  changeset:   2:c0aa9c6feb0a&lt;br /&gt;| |  branch:      123-new&lt;br /&gt;| |  user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;| |  date:        Tue Jan 11 15:47:36 2011 +0100&lt;br /&gt;| |  summary:     Two.&lt;br /&gt;| |&lt;br /&gt;| o  changeset:   1:23e96c98b90e&lt;br /&gt;|/   branch:      123-new&lt;br /&gt;|    user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;|    date:        Tue Jan 11 15:47:29 2011 +0100&lt;br /&gt;|    summary:     One.&lt;br /&gt;|&lt;br /&gt;o  changeset:   0:11575ff21a29&lt;br /&gt;   user:        Alice &lt;a@li.ce&gt;&lt;br /&gt;   date:        Tue Jan 11 15:08:58 2011 +0100&lt;br /&gt;   summary:     Initial commit.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Comme avant on peut se débarasser de la vieille branche avec &lt;code&gt;hg strip 1&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;La morale&lt;/h3&gt;&lt;br /&gt;Je ne sais pas comment tout cela fonctionne dans la durée et à grande échelle. J'imagine que parfois c'est plus compliqué que sur ce petit exemple, mais cela me semble valoir le coup d'essayer. Et ça a l'air de marcher pour des gens.&lt;br /&gt;&lt;br /&gt;La question restante est donc surtout: quand et comment se jeter à l'eau avec savonet?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-1328446157947472531?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/1328446157947472531/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=1328446157947472531' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1328446157947472531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1328446157947472531'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2011/01/gestion-de-code.html' title='Gestion de code'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5351820351588925931</id><published>2010-12-17T15:16:00.002+01:00</published><updated>2010-12-17T15:19:06.828+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Design III: Liquidsoap tomorrow?</title><content type='html'>In the previous post we've seen the problems with the current source at the core of liquidsoap. The point of doing so was to highlight the interest of a more principled design.&lt;br /&gt;&lt;br /&gt;We could start with a mathematical notion of stream, but we haven't reached that point yet. As I've illustrated before, sources are inherently interactive objects, which is hard to account for.&lt;br /&gt;&lt;br /&gt;Instead, I'll keep the same practical notion of source but do one simplification: we'll work sample by sample. We'll have a &lt;code&gt;#is_ready&lt;/code&gt; method that tells whether the source can produce a sample for the current instant. A source is always ready when it is in the middle of a track. And we have the &lt;code&gt;#get&lt;/code&gt; method which returns at most one sample, none when the current track ends, and should never be called unless the source &lt;code&gt;#is_ready&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;As before, a source is passive by default (it doesn't produce data when not asked to) and caching mechanisms ensure that a source gives consistent answers to several observers. Depending on how/when it is used, a source will generate a stream, possibly undefined at some instants, but otherwise containing samples, metadata and end of track markers. Note that we need more precision than just time to denote a point in such a stream, in order to be able to tell the position relative to end of tracks -- it is possible to have several consecutive end of tracks exactly at the same point in time.&lt;br /&gt;&lt;br /&gt;Let us detail caching, which isn't totally trivial. What do we cache: a number N of end of tracks, corresponding to partial &lt;code&gt;#get&lt;/code&gt;, possibly followed by a sample. How do we use that cache: for an operator which already had M end of tracks and performs a &lt;code&gt;#get&lt;/code&gt;, we return an end of track if M&amp;lt;N, the sample otherwise.&lt;br /&gt;&lt;br /&gt;In the current liquidsoap, this M is passed as part of the frame, but there is no way to track which source has produced which end of track. Hence it is possible that M&amp;gt;N, for example in case of a switch which has seen many empty tracks before switching to that source. Even when M&amp;lt;N, it makes it unclear how many end of tracks we should add. I'm not sure whether it is crucial that we keep precise track of who produces which end of track.&lt;br /&gt;&lt;br /&gt;What matters is (1) if you listen continuously to a stream, you get exactly all its content and (2) we don't have the first problem with sharing. This is because various operators of a source can only get data at one instant. If I pump it, the source will generate (or find in its cache) an end of track or a sample. It's as simple as this, there's no bad side-effect here. We don't even need to worry about sharing detection, because we can perform caching all the time without changing the stream content -- efficiency isn't an issue for now. (At some point I was worried that sub-instantaneous data is in the cache, i.e. end of tracks, could lead to the same problem as before, but it does not make sense because this data can't be refered to without first generating it: you can't pump a source "after" it has generated end of tracks, you can only pump it, ignore end of tracks, and pump it again.)&lt;br /&gt;&lt;br /&gt;For our second problem, we would simply cache the result of &lt;code&gt;#is_ready&lt;/code&gt; (rather, rely on the same cache). As with &lt;code&gt;#get&lt;/code&gt;, we need to know the number of end of tracks already obtained by the observer to tell him if the source is ready at that precise point.&lt;br /&gt;&lt;br /&gt;Some minor remarks:&lt;ul&gt;&lt;li&gt;We can't distinguish a source that is in the middle or just before the beginning of a track. If you don't listen to a source for a while, and the source is ready when you come back to it, there's no way to know if it is about to start something new or if you missed the beginning of the current track. It's never been a problem, I'll assume we can keep living with it.&lt;/li&gt;&lt;li&gt;The  implementation of end-of-track notification is still a "partial" &lt;code&gt;#get&lt;/code&gt; which may be too ad-hoc. The alternative is to attach an end-of-track tag to the last sample. Looks like a meaningless choice to me.&lt;/li&gt;&lt;li&gt;Note that metadata and end-of-tracks are treated very differently: we never issue a partial &lt;code&gt;#get&lt;/code&gt; because of metadata. It corresponds to a view where, end of tracks are "after" the last sample, while metadata is "before" or maybe "inside" samples. We should try to generalize this into a nice notion of event, some being interruptions, some not.&lt;/li&gt;&lt;li&gt;With Samuel, we have explored other design choices. What I present here isn't his favorite, but it's the most convincing to me. It also has the advantage of being fully defined (at least in my mind).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This new model is not revolutionary. But we gained more than it seems. For example, we can now write an operator that takes two sources and sums them, only producing data when both of them are ready, and not pumping any of them when none is ready. The reason is that in the old frame-based design, we can only get data until either the end of a frame or the end of a track. But if one source ends a track, the other will still fill a frame.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lifting to frames&lt;/h3&gt;&lt;br /&gt;The real challenge now is to derive an efficient frame-based model that faithfully reflects the simply sample-based model.&lt;br /&gt;&lt;br /&gt;I'll start with the biggest problem: sharing. We can't approximate it anymore, or we'll obtain the same problem. Hence I'm going to propose a two-phase pumping: In a first abstract phase we do a dry run of the pumping methods to know who pumps who at what instant. Then we have a precise picture of the sharing and we can do a real run, computing the actual stream content.&lt;br /&gt;&lt;br /&gt;This method forbids some source behaviors: for example if a source acts differently based on the actual values of its input samples, it cannot meaningfully take part to the first phase. That would be a problem with a blank detection source. I believe we can relax this enough to get what liquidsoap currently does. The key is to declare some values as "sparse" or "slow", allowing the change of the value (and hence the reaction of the source) to only take place at the end of the frame. For example blank detection would set a flag that only takes effect for the next frame.&lt;br /&gt;&lt;br /&gt;For most sources I want to automatically generate the &lt;code&gt;#simulated_get&lt;/code&gt; method from a simple &lt;code&gt;#get&lt;/code&gt;. This is why compilation is needed now.&lt;br /&gt;&lt;br /&gt;Now, I believe I can run that simulation thing. The nice thing is that once I bite the bullet and decide we need this, there's no question about being more modest in other places. In particular, the new &lt;code&gt;#is_ready&lt;/code&gt; will be asked not only if a source is ready at a particular point but for how long. This enables a nice frame-based implementation of the precise sum operator described above. Of course, it goes with a &lt;code&gt;#get&lt;/code&gt; that takes not only a start but also a stop position.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Plans&lt;/h3&gt;&lt;br /&gt;There are several things we can do now:&lt;ol&gt;&lt;li&gt;Compile frame-level sources from sample-level sources written in OCaml.  This is only about analysing the source, and it does not need be  user-friendly. There are a couple tricky analysis to run. For example, a sine source will have a counter decremented at each sample and reset after an end of track, and we'll have to turn this into the natural code for the frame-level sine.&lt;/li&gt;&lt;li&gt;Extend liquidsoap scripts with a notation for sources and compile it down to OCaml objects. We'll have to ensure that the user never sees a type error coming from OCaml, but only errors from us, which should be more readable. The main extra challenge is to run liquidsoap code fast. Some of it can be compiled directly to OCaml but function calls won't match exactly. We'll have to inline or leave some interpreter calls.&lt;/li&gt;&lt;li&gt;Do cross-source optimizations on top of the previous work. If the user writes a sum of sine sources, inline it into a source that computes directly the sums.&lt;/li&gt;&lt;li&gt;Compile to C or even lower level code.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;I gave a rather precise proposal of what Step 1 could look like. Still we can discuss some points, try to generalize a few things. My proposition doesn't look as clean as I would like in some places, but it has one great advantage: I'm sure we can program liquidsoap sources with that model, and even do some things currently impossible.&lt;br /&gt;&lt;br /&gt;Step 2 presents even more design choices: should users write sources in an OO style like we do? should they work with an explicit notion of time? should time be discrete or continuous?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5351820351588925931?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5351820351588925931/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5351820351588925931' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5351820351588925931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5351820351588925931'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/12/design-iii-liquidsoap-tomorrow.html' title='Design III: Liquidsoap tomorrow?'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2204047876510308880</id><published>2010-12-10T15:11:00.003+01:00</published><updated>2010-12-10T15:37:16.881+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Design II: Liquidsoap today</title><content type='html'>In this post, I will give a high level picture of the current internals of liquidsoap, show a few problems with them. The interested reader can read further details on the design of liquidsoap in &lt;a href="http://savonet.sourceforge.net/publications.html"&gt;our papers&lt;/a&gt;. In the next post, I'll finally describe a better future for liquidsoap.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The source protocol&lt;/h3&gt;&lt;br /&gt;In order to get a minimum understanding of liquidsoap's streaming model, let us consider the following example:&lt;br /&gt;&lt;pre&gt;output(fallback([queue,playlist]))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What we want here is to produce a stream either from the playlist or the queue of requests, and output it somehow. The &lt;code&gt;fallback&lt;/code&gt; between our two sources only switches from one to the other for new tracks. For example, if the &lt;code&gt;queue&lt;/code&gt; becomes available while we are in the middle of a &lt;code&gt;playlist&lt;/code&gt; track, we'll keep playing the &lt;code&gt;playlist&lt;/code&gt; track, and only switch to the &lt;code&gt;queue&lt;/code&gt; for the next track. In order to obtain the expected behavior this means that (when possible) unused sources are (almost) frozen in time: the &lt;code&gt;queue&lt;/code&gt; doesn't start playing its request until the &lt;code&gt;fallback&lt;/code&gt; asks it to do so. The stream of a source isn't defined in itself, but computed in interaction with the source's environment. Simply put, it's on-demand streaming.&lt;br /&gt;&lt;br /&gt;Now what happens concretely. Streaming is clocked, and at each cycle of the clock we produce a frame, which is simply a buffer of samples (audio, video or MIDI) of fixed size/duration. The filling of the frame starts from the outputs: Our output passes the frame to the fallback, which passes it to the source that is currently playing a track, the frame is filled, passed back to fallback, which passes it back to output, which outputs the frame to the world.&lt;br /&gt;&lt;br /&gt;Sometimes, it'll be a little different: When the child source of fallback ends its track, it won't completely fill the frame, which gives the opportunity for the fallback to select another source. The newly selected source isn't used right away. Instead, the partial frame is returned to the above operator, in our case the output, which passes it back because all it wants is a complete frame -- the story would be different with nested fallbacks. When the partial frame comes back, its filling is completed by the newly selected source.&lt;br /&gt;&lt;br /&gt;We perform that kind of computation by having sources communicate with each other using just a few methods: we mainly have &lt;code&gt;#get&lt;/code&gt; for filling a frame and &lt;code&gt;#is_ready&lt;/code&gt; for knowing if a source has a ready track (ongoing or not).&lt;br /&gt;&lt;br /&gt;All this works smoothly when sources are organized along a tree, &lt;em&gt;i.e.,&lt;/em&gt; when there is no sharing. But we really want sharing, as seen in the following example:&lt;br /&gt;&lt;pre&gt;source = fallback([queue,playlist])&lt;br /&gt;output_1(source)&lt;br /&gt;output_2(source)&lt;/pre&gt;This means that at each cycle of the clock, the source will be asked twice to fill a frame with a segment of its stream. Of course, the source should give the same data twice: we don't want to split our stream among the two outputs, one frame each. To deal with this, we have some caching mechanisms in &lt;code&gt;#get&lt;/code&gt;. In more details, we create new sources by inheriting from a base class which defines &lt;code&gt;#get&lt;/code&gt; as a public method wrapping the virtual private method &lt;code&gt;#get_frame&lt;/code&gt; which can be written without thinking about sharing at all.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Problem #1&lt;/h3&gt;&lt;br /&gt;Caching everything is really costly, so we have to detect when sharing is needed. The problem is that sometimes, it's not easy to tell statically:&lt;br /&gt;&lt;pre&gt;output(&lt;br /&gt;  switch([&lt;br /&gt;    ({am},fallback([queue,am_playlist]),&lt;br /&gt;    ({pm},fallback([queue,pm_playlist])]))))&lt;/pre&gt;Here it looks like the queue is shared, but in fact the first occurrence can only be used in the morning (am), the second only in the afternoon (pm). While we could try to detect some of those cases, it is hopeless to catch them all. So we're bound to over-approximate sharing. This has been done, and isn't too complicated, although it does introduce some activation/deactivation methods that must be used carefully, especially when using transitions. This is okay regarding performance, but it has one nasty side effect: the approximation can have an impact on the stream!&lt;br /&gt;&lt;br /&gt;The scenario is as follows: Take a source S which looks like it could be used by operators A and B. Now A asks S to start filling a frame &lt;em&gt;from the middle&lt;/em&gt; (it happens, cf. the fallback example above) but the source sees that it could be also be used by B, perhaps to fill a frame from the beginning. So S fills in its cache from the beginning, and copies the part of it that starts from the middle in A's frame. But if B never uses S, we'll have modified our behavior for nothing.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Problem #2&lt;/h3&gt;&lt;br /&gt;An even worse problem is that we implemented some caching mechanism for &lt;code&gt;#get&lt;/code&gt; but not &lt;code&gt;#is_ready&lt;/code&gt;. Now, it is possible that a source fills its cache, has no new track to produce, and hence declares itself as not ready. Which might not be correct from the viewpoint of an operator that wants to access the data from the beginning of the cached frame. As a result of this weakness, I recently had to allow what should be illegal behavior in some operators that rely quite precisely on the readiness of their sources. Of course, this is a slippery slope.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Next time, I'll describe a simple way to construct a better source protocol from first principles, avoiding those problems, and even getting more expressiveness by the way. On the other hand, it'll &lt;em&gt;have to&lt;/em&gt; be compiled. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2204047876510308880?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2204047876510308880/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2204047876510308880' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2204047876510308880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2204047876510308880'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/12/design-ii-liquidsoap-today.html' title='Design II: Liquidsoap today'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8846389725760264601</id><published>2010-12-09T08:42:00.006+01:00</published><updated>2010-12-09T08:49:44.010+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programmation'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='english'/><title type='text'>Design</title><content type='html'>I recently found a good series of articles on LtU, on the &lt;a href="http://lambda-the-ultimate.org/node/4156"&gt;Ghosts of UNIX past&lt;/a&gt;. The author reflects on some successes and failures of Unix, trying to find patterns. I enjoyed reading the articles, they teach you a few things, and are generally good food for thought.&lt;br /&gt;&lt;br /&gt;The first article describes the "full exploitation" pattern, successfully achieved in UNIX with files. The next articles describe various failures of UNIX design, classifying them in "conflated", "unfixable" and "high-maintenance" designs. While I don't have the culture to do the proposed exercises, I tried to relate this to programming language design -- which suprisingly hasn't been done on LtU.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Full exploitation&lt;/em&gt; is when you manage to re-use a concept a lot. This is good because it avoids inventing new things: it's hard enough to get a few concepts right. In programming languages, a good first-class notion of functions can be fully exploited to model control, event handlers, lazy computation, etc.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Conflated designs&lt;/em&gt; mix up several concepts. This is bad only if the two concepts cannot be separated. Otherwise, it's just syntactic sugar. Object oriented programming comes to mind: Methods are a conflated design, mixing functions and record members. Also, inheritance mixes record extension and dynamic binding -- which makes it hard for people to think about the latter aspect, a very important source of bugs.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Unfixable designs&lt;/em&gt; are unfixable designs. This is a bad definition, but sometimes it is hard to say why something is unfixable. Often, this has to do with the wide adoption of the wrong design. Note that conflated designs may often be fixable, essentially by creating ways to access conflated notions in isolation. I'm not sure what's a good programming language example here. Perhaps dynamic binding, probably stuck forever in emacs lisp. (By the way, a fun fact according to Olivier Danvy: dynamic binding was born from &lt;em&gt;exagerated exploitation&lt;/em&gt; of a single stack in the implementation of Lisp -- in those old days, people were psyched about stacks and got a bit carried away.)&lt;/li&gt;&lt;li&gt;&lt;em&gt;High-maintenance designs&lt;/em&gt; have nothing wrong in themselves but interfere with other things in such a way that requires a lot of care and work in those areas. With programming, various difficult things come to mind: state, concurrency, dynamic binding... Those aspects make it very hard to reason locally about a piece of code. In themselves, state and concurrency are cool, but their interaction leads to many problems.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;More than programming languages, liquidsoap was in the back of my mind. But there does not seem to be interesting examples of those patterns in liquidsoap. In fact, it is &lt;em&gt;not&lt;/em&gt; an exceptionally good design. It's just a first shot at making an end-user streaming application that is not just one object/tool but rather a system/language for building tools. Liquidsoap introduces an abstract notion of source, which is good, but &lt;em&gt;does not fully exploit&lt;/em&gt; it. For instance, blank detection operators are black boxes that encapsulate the computation of the average audio volume, but a more flexible and efficient design would be achieved by isolating the computation of the volume stream as a source, then write operators that act depending on the characteristics of the volume source. Liquidsoap does not have &lt;em&gt;unfixable designs&lt;/em&gt; because we give ourselves the liberty to change things when needed. It does have &lt;em&gt;high-maintenance designs&lt;/em&gt;: the source protocol is complex, and we've had &lt;a href="http://www.google.com/search?ie=UTF-8&amp;oe=UTF-8&amp;sourceid=navclient&amp;gfns=1&amp;q=get_frame+didn%27t+change+the+buffer#sclient=psy&amp;hl=en&amp;q=%22get_frame+didn%27t+add+exactly+one+break%22&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai=&amp;pbx=1&amp;fp=4824b41ba0d4cfd8"&gt;many&lt;/a&gt; &lt;a href="http://www.google.com/search?ie=UTF-8&amp;oe=UTF-8&amp;sourceid=navclient&amp;gfns=1&amp;q=get_frame+didn%27t+change+the+buffer#sclient=psy&amp;hl=en&amp;q=%22get_frame+didn%27t+change+the+buffer%22&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai=&amp;pbx=1&amp;fp=4824b41ba0d4cfd8"&gt;bugs&lt;/a&gt; because it wasn't properly followed.&lt;br /&gt;&lt;br /&gt;Beyond those not-so-good design examples, liquidsoap is broken in several ways. But I'm comfortable to admit it because it works good enough for many people and we know how to fix it. The code name for that exciting new line of work is, quite straightforwardly, &lt;b&gt;Liquidsoap 2.0&lt;/b&gt;. Until now, we've been writing sources by hand in OCaml. Liquidsoap users write scripts in our own scripting language, and can only compose sources, never write a new one. In other words, Liquidsoap is an interpreter for a dedicated script language that manipulates an abstract/opaque notion of source. But liquidsoap 2.0 will be a compiler that lets you write sources, and not only compose them, and will produce optimized code. It will be as simple as it is today for beginners, but will enable much more for power users. Importantly, it will allow us developers to not write as much bug-prone code. There is a lot to say about what could be in liquidsoap 2.0, but I'll start with a simple down-to-earth story... next post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8846389725760264601?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8846389725760264601/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8846389725760264601' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8846389725760264601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8846389725760264601'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/12/design.html' title='Design'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-1286447523989948066</id><published>2010-10-20T15:15:00.008+02:00</published><updated>2010-10-20T15:28:06.341+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><title type='text'>Random.self_init</title><content type='html'>Maintenant que je travaille un peu dans le domaine de la sécurité, je pense notamment aux générateurs de nombres aléatoires. Après quelques lectures &lt;a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator"&gt;sur&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator"&gt;le sujet&lt;/a&gt;, je me suis demandé comment fonctionnait le module &lt;code&gt;Random&lt;/code&gt; de Caml.&lt;br /&gt;&lt;br /&gt;Il y a sûrement beaucoup de choses à dire, mais mon attention a été retenue par un truc simple: &lt;code&gt;self_init&lt;/code&gt; initialise le générateur de façon très simple, à partir de l'heure et de l'identifiant du processus, données pour le moins aléatoires. Il faut donc vraiment se méfier de cela si on souhaite utiliser le module &lt;code&gt;Random&lt;/code&gt; à des fins cryptographiques. En pratique, le petit bout de code suivant devine assez rapidement la graine générée, en supposant connu l'identifiant du processus (ce n'est pas bien dur à deviner sinon) et en supposant approximativement connue l'heure de l'initialisation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(** Random.self_init relies on caml_sys_random_seed&lt;br /&gt;  * which returns an int.&lt;br /&gt;  * That integer is sec ^ usec ^ ppid&amp;lt;&amp;lt;16 ^ pid.&lt;br /&gt;  * We try to guess the seed to reproduce the output of&lt;br /&gt;  * the random generator.&lt;br /&gt;  * The PID and PPID are supposed to be known,&lt;br /&gt;  * the time in seconds and micro-seconds is supposed&lt;br /&gt;  * to be known resp. with precision 1s and 1000ms.&lt;br /&gt;  * With that knowledge it's really fast;&lt;br /&gt;  * with less it'd take longer. *)&lt;br /&gt;&lt;br /&gt;let gen sec usec pid ppid =&lt;br /&gt;  sec lxor usec lxor pid lxor (ppid lsl 16)&lt;br /&gt;&lt;br /&gt;let random _ = Random.int 100&lt;br /&gt;&lt;br /&gt;(** Given a leaked sequence of numbers consecutively&lt;br /&gt;  * generated by [random] _immediately after_&lt;br /&gt;  * [Random.self_init], call [k] with seeds that allow&lt;br /&gt;  * to reproduce that sequence. *)&lt;br /&gt;let crack leak k =&lt;br /&gt;  let t = Unix.gettimeofday () in&lt;br /&gt;  let sec = int_of_float t in&lt;br /&gt;  let usec = int_of_float (fst (modf t) *. 1_000_000.) in&lt;br /&gt;  let pid = Unix.getpid () in&lt;br /&gt;  let ppid = Unix.getppid () in&lt;br /&gt;    (* Since we sec and usec are xored, trying sec and&lt;br /&gt;     * sec-1 would be useless: all we'd be doing is&lt;br /&gt;     * flipping a bit that is flipped anyway when&lt;br /&gt;     * enumerating posssible values for usec. *)&lt;br /&gt;    for usec = usec - 10000 to usec do&lt;br /&gt;      let seed = gen sec usec pid ppid in&lt;br /&gt;        Random.init seed ;&lt;br /&gt;        if Array.init (Array.length leak) random = leak then&lt;br /&gt;          k seed&lt;br /&gt;    done&lt;br /&gt;&lt;br /&gt;let () =&lt;br /&gt;  let leak,valid =&lt;br /&gt;    Random.self_init () ;&lt;br /&gt;    let leak = Array.init 1000 random in&lt;br /&gt;    let valid = Array.init 5000 random in&lt;br /&gt;      leak, valid&lt;br /&gt;  in&lt;br /&gt;  let k seed =&lt;br /&gt;    let guess =&lt;br /&gt;      Random.init seed ;&lt;br /&gt;      ignore (Array.init (Array.length leak) random) ;&lt;br /&gt;      Array.init (Array.length valid) random&lt;br /&gt;    in&lt;br /&gt;      Printf.printf&lt;br /&gt;        "Guessed seed: %d. Validated: %b.\n"&lt;br /&gt;        seed (guess=valid)&lt;br /&gt;  in&lt;br /&gt;    crack leak k ;&lt;br /&gt;    Printf.printf "Search space exhausted.\n"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Quand on le lance, on a quelque chose comme ça en quelques secondes:&lt;br /&gt;&lt;pre&gt;$ ocamlopt unix.cmxa crack.ml -o crack &amp;&amp; ./crack&lt;br /&gt;Guessed seed: 262818353. Validated: true.&lt;br /&gt;Search space exhausted.&lt;/pre&gt;&lt;br /&gt;Il y a diverses variations possible. Ce qui m'intéresse, et qui est encore assez obscur pour moi, c'est la génération (répétitive) de graines à partir d'une partie privée et d'une partie publique, utilisée pour éviter d'avoir des séquences générées identiques (ce qui exposerait à des attaques dans certains cas). A quel point on affaiblit ou compromet son secret, en fonction du générateur utilisé, etc?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-1286447523989948066?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/1286447523989948066/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=1286447523989948066' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1286447523989948066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1286447523989948066'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/10/randomselfinit.html' title='Random.self_init'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-4275522991461329971</id><published>2010-08-30T06:38:00.001+02:00</published><updated>2010-08-30T13:17:52.162+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><title type='text'>Qui me regarde?</title><content type='html'>Deux petites histoires un peu angoissantes...&lt;br /&gt;&lt;br /&gt;(1) Je suis parti en vacances sur la route dans l'Ouest américain, et comme nous sommes passés par Las Vegas, j'avais cherché sur mon portable des hotels là bas. De retour de vacances, je me suis retrouvé plusieurs fois sur des pages webs quelconques avec de la pub pour des hotels à Las Vegas.&lt;br /&gt;&lt;br /&gt;(2) Suite à une mésaventure, je me suis acheté une nouvelle montre. Comme Estelle voulait voir comme elle était belle, j'ai fait une petite recherche d'image sur le web. Et hier, j'ai reçu un mail d'Amazon m'annonçant une promo sur cette marque de montre en particulier.&lt;br /&gt;&lt;br /&gt;Je suis pas parano, tout ceci n'est pas dû au hasard? Mais la seule explication serait que google ait vendu la mêche, mais cela suppose aussi que ces sites m'identifient, ce qui va un peu loin...&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Edit&lt;/em&gt;: En fait, j'ai dû cliquer sur un lien Amazon pour la montre, c'est le plus probable. On est toujours connecté à Amazon, c'est traître.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4275522991461329971?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4275522991461329971/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4275522991461329971' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4275522991461329971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4275522991461329971'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/08/qui-me-regarde.html' title='Qui me regarde?'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-1758309625827538934</id><published>2010-04-27T21:12:00.002+02:00</published><updated>2010-12-08T09:59:54.538+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Liquidsoap: retour aux sources</title><content type='html'>Vous savez sûrement que je passe cette année aux Etats Unis et plus précisemment à Minneapolis, Minnesota. Mais savez-vous vraiment pourquoi? C'est dans cet Etat qu'a été inventé le &lt;a href="http://en.wikipedia.org/wiki/Softsoap"&gt;savon liquide&lt;/a&gt;! C'est donc logique que je m'isole ici pour me recueillir et bourriner sur &lt;a href="http://savonet.rastageeks.org/timeline"&gt;liquidsoap&lt;/a&gt; le logiciel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-1758309625827538934?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/1758309625827538934/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=1758309625827538934' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1758309625827538934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1758309625827538934'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/04/liquid-soap-retour-aux-sources.html' title='Liquidsoap: retour aux sources'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-7227026820226687929</id><published>2010-02-17T18:20:00.003+01:00</published><updated>2010-02-17T18:23:59.071+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><title type='text'>Liens</title><content type='html'>Quelques lectures qui se font écho, dans l'air du temps. Je ne m'inquiète pas trop de certaines craintes vis-a-vis d'Internet, du genre "Google nous rend bête, l'homme n'utilise plus sa mémoire, n'écrit plus". Globalement, j'ai grandi avec et je me sens pas trop con. Par contre, je suis plus sensible à d'autres remarques sur la façon dont l'Internet évolue. Ce n'est pas que de la nostalgie, et il ne s'agit même pas seulement d'Internet: la politique, la créativité et la culture, la SF vs. le fantastique et le mystique, le rapport au monde.&lt;br /&gt;&lt;br /&gt;Sur Commondreams, &lt;a href="http://www.commondreams.org/view/2010/02/15-1"&gt;The Information Super-Sewer&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;“The crowd phenomenon exists, but the hive does not exist,” Lanier told me. “All there is, is a crowd phenomenon, which can often be dangerous. To a true believer, which I certainly am not, the hive is like the baby at the end of ‘2001 Space Odyssey.’ It is a super creature that surpasses humanity. To me it is the misinterpretation of the old crowd phenomenon with a digital vibe. It has all the same dangers. A crowd can turn into a mean mob all too easily, as it has throughout human history.”&lt;/blockquote&gt;&lt;br /&gt;Sur écrans.fr, &lt;a href="http://ecrans.fr/Fuck-Google-l-alternative,9202.html"&gt;Fuck Google&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Nous utilisons Google, Gmail, Youtube, ses calendriers, documents, cartes, etc. Nous les utilisons comme les WC publics quand nous devons aller pisser ; parce qu’il semble qu’il n’y ait pas d’autre option. Or il existe des alternatives. [...] Web 3.0 : le grand repli sur vos propres serveurs.&lt;/blockquote&gt;&lt;br /&gt;Et aussi &lt;a href="http://ecrans.fr/Le-Web-c-est-folk-LOL,9100.html"&gt;Le Web, c'est folk&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Les amateurs d’aujourd’hui préfèrent la « fantasy », les elfes et les animaux étranges aux thèmes de science-fiction très populaires au début du Web  : « L’idée de construire un vrai futur en ligne a été remplacée par une échappatoire vers un monde imaginaire. » [...] Les usagers sont « autorisés » à télécharger leur production sur de nombreux services différents, ce qu’on faisait déjà il y a quinze ans mais sur son propre serveur. Cette vision cynique des usagers se perpétue, ils sont divertis, mais également exploités en tant que producteurs de contenus et cliqueurs de publicités. Le « nuage informatique » va encore diminuer leur rôle au profit de puissants ordinateurs centralisés. C’est l’opposé de l’idée de peer to peer où les utilisateurs construisaient des systèmes en connectant leurs ordinateurs.&lt;/blockquote&gt;&lt;br /&gt;Grant Petersen à propos de sa compagnie de bicyclettes, Rivendell:&lt;br /&gt;&lt;blockquote&gt;Simple things make people feel smart, or at least competent, and complication has the opposite effect. If people feel smart and competent, they’re happy, and happy people are nice to other people, and it all starts or stops with how hard it is to use something.&lt;/blockquote&gt;&lt;br /&gt;Pour la route, une brochette d'artisanat:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://mrpingouin.free.fr"&gt;Super pingouins&lt;/a&gt;, un bon vieux site, qui me touche au moins moi pour les bons souvenirs.&lt;/li&gt;&lt;li&gt;&lt;a href="http://savonet.sf.net"&gt;Liquidsoap&lt;/a&gt;, un outil de streaming surpuissant, développé lentement mais sûrement depuis 2003. C'est du logiciel libre développé en toute indépendance (sauf la pression des utilisateurs), même si c'est hébergé par le monstre Sourceforge. Mais le mieux, c'est les projets plus ou moins fous que les gens construisent avec cet outil! (On devrait vraiment s'occuper de rassembler une meilleure page de liens.)&lt;/li&gt;&lt;li&gt;&lt;a href="http://dolebrai.net"&gt;Dolebraï&lt;/a&gt;, qui ne permet toujours pas à la foule de voter pour la musique qu'elle aime (en fait, c'est une feature militante) et qui est bien plus petit que &lt;a href="http://freemusicarchive.org/"&gt;Free Music Archive&lt;/a&gt; dans le même esprit.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-7227026820226687929?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/7227026820226687929/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=7227026820226687929' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7227026820226687929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7227026820226687929'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/02/liens.html' title='Liens'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2099428691046376546</id><published>2010-02-08T20:04:00.008+01:00</published><updated>2010-02-08T20:28:56.483+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Quel effet ça fait</title><content type='html'>Quelle différence entre &lt;code&gt;a&amp;rarr;b&amp;rarr;c&lt;/code&gt; et &lt;code&gt;a&amp;rarr;b&amp;rarr;c&lt;/code&gt;? Pour le savoir, lisez ce qui suit.&lt;br /&gt;&lt;br /&gt;De temps en temps, je regarde un article scientifique, ou un bout de code, et je n'en suis pas satisfait. Un truc me chiffonne, ça peut se réparer, mais ya autre chose qui cloche, et au fond c'est tout bancal, ça n'en finit pas, et il vaut mieux tout remettre à plat. Ceci est arrivé récemment dans liquidsoap avec le module de décodage de fichier. Ce n'est pas intéressant de détailler, il y a juste un point dont je voulais parler. Mais avant, je trouve que c'est important de dire qu'il faut remettre les choses à plat de temps en temps.&lt;br /&gt;&lt;br /&gt;Donc, il s'agit de décodage. Première question: qu'est ce que c'est un décodeur? J'ai mis un peu de temps à essayer plusieurs styles, pour finalement décider &lt;code&gt;input -&amp;gt; buffer -&amp;gt; unit&lt;/code&gt;, une fonction qui prend en entrée une méthode pour lire des données, et un buffer pour écrire le résultat du décodage, et qui ne renvoie rien mais remplit le buffer un peu plus à chaque fois qu'on l'appelle.&lt;br /&gt;&lt;br /&gt;A côté de cette notion très générique on a des notions plus spécialisées comme le &lt;code&gt;type file_decoder = { fill : Frame.t -&amp;gt; unit ; close : unit -&amp;gt; unit }&lt;/code&gt;. C'est un enregistrement qui contient une fonction de remplissage de flux (on lui donne une frame (un morceau de flux) à remplir) et une fonction de fermeture/nettoyage où l'on libère les ressources allouées pour le décodage.&lt;br /&gt;&lt;br /&gt;Ceci étant décidé, j'écris un bout de code générique qui emballe un décodeur pour construire un décodeur_de_fichier:&lt;pre&gt;let file_decoder filename decoder =&lt;br /&gt;  let input = input_from_file filename in&lt;br /&gt;  let buffer = create_buffer () in&lt;br /&gt;  let fill frame =&lt;br /&gt;    while not_enough_data_in buffer do&lt;br /&gt;      decoder input buffer&lt;br /&gt;    done ;&lt;br /&gt;    fill_frame_from_buffer frame buffer&lt;br /&gt;  in&lt;br /&gt;    { fill = fill ; close = fun () -&amp;gt; close input }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Vous me suivez? Maintenant, j'implémente un décodeur, pour le format MP3 en utilisant la bibliothèque mad:&lt;pre&gt;let create_decoder input =&lt;br /&gt;  let resampler = create_resampler () in&lt;br /&gt;  let mad_stream = Mad.openstream input in&lt;br /&gt;    (fun buffer -&amp;gt;&lt;br /&gt;       let data = Mad.decode_frame_float mad_stream in&lt;br /&gt;       let sample_freq,_,_ = Mad.get_output_format fd in&lt;br /&gt;       let content,length =&lt;br /&gt;         resampler ~audio_src_rate:(float sample_freq) data&lt;br /&gt;       in&lt;br /&gt;         put_audio_in_buffer buffer content length)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;PAF! Vous voyez le bug? Je parie que non, en tout cas moi je l'avais raté. J'ai réussi à ne pas être d'accord avec moi même, penser &lt;code&gt;a&amp;rarr;b&amp;rarr;c&lt;/code&gt; ici et &lt;code&gt;a&amp;rarr;b&amp;rarr;c&lt;/code&gt; là!...&lt;br /&gt;&lt;br /&gt;Le problème, c'est &lt;em&gt;les effets&lt;/em&gt;. En mathématiques, une fonction prend un argument et renvoie un résultat. On ne sait pas comment ça se passe "dedans", en tout cas ça n'interagit pas sur le "dehors", et ça se passe pareil à chaque fois: même entrée, même sortie. En informatique, c'est bien plus compliqué. La fonction interagit avec le monde, elle peut afficher quelquechose à l'écran, elle peut aller chercher un résultat sur internet, dans un fichier, ou simplement dans une case mémoire qu'elle partage avec d'autres fonctions. On est ainsi habitué à avoir tout un paquet de fonctions de type &lt;code&gt;a&amp;rarr;b&lt;/code&gt;, puisqu'il ne s'agit pas seulement de prendre un objet de type &lt;code&gt;a&lt;/code&gt; pour calculer un objet de type &lt;code&gt;b&lt;/code&gt; mais aussi potentiellement de se livrer à tout un tas d'interactions avec le monde.&lt;br /&gt;&lt;br /&gt;Mon code utilise cela, mais se prend les pieds dedans. Ce qui est joli, c'est que j'ai une "solution". Mais voyons d'abord le problème. Notre décodeur prend un canal d'entrée (&lt;code&gt;input&lt;/code&gt;), un canal de sortie (&lt;code&gt;buffer&lt;/code&gt;), et est supposé avoir comme &lt;em&gt;effet&lt;/em&gt; de lire un peu de données en entrée, de les convertir et les écrire en sortie. Il ne renvoie rien d'utile (&lt;code&gt;unit&lt;/code&gt;), tout son interet réside dans l'effet; si on l'appelle un assez grand nombre de fois, on finit par avoir assez de données dans notre buffer -- c'est ce qu'on a fait plus haut. On peut cacher un certains nombres d'informations dans le décodeur, c'était mon intention, par exemple j'y ai alloué un &lt;em&gt;resampler&lt;/em&gt; pour convertir les données vers la bonne fréquence d'échantillonage: cet outil doit être (et est bien) crée une fois et une seule pour chaque décodeur.&lt;br /&gt;&lt;br /&gt;Ce resampler maintient un état interne, tout comme le décodeur mad (&lt;code&gt;mad_stream&lt;/code&gt;). Allouer ces objets est aussi un effet! Mais à quel moment a-t-il lieu? Le type ne l'indique pas: dans &lt;code&gt;input-&gt;buffer-&gt;unit&lt;/code&gt;, après quel argument un effet peut-il avoir lieu? Dans le code de &lt;code&gt;file_decoder&lt;/code&gt; j'utilise un décodeur comme si le seul effet était le décodage, qui a lieu une fois qu'on a renseigné l'input et l'output. Mais dans le code du décodeur MP3, pas le choix, je m'autorise un effet entre le moment où on m'a donné l'input et le moment où on me donne le décodeur. Résultat, quand on utilise &lt;code&gt;file_decoder&lt;/code&gt; avec le &lt;code&gt;create_decoder&lt;/code&gt; MP3, on a un son tout haché, car le décodeur et le resampleur sont reinitialisés sans arrêt, ce qui provoque la perte d'une partie des données mémorisées dans leurs buffers internes.&lt;br /&gt;&lt;br /&gt;Ces problèmes sont très vicieux, et sont toujours un sujet de recherche active. Mais concrètement, que peut-on y faire avec les outils d'aujourd'hui? Documenter, espérer que tout le monde se comprend? Pas terrible, j'ai réussi à être en désaccord avec moi-même sur une courte période de temps. Comme d'habitude, &lt;em&gt;ce serait bien si le système de type nous servait de garde fou&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;En logique, la notion de focalisation (&lt;em&gt;focusing&lt;/em&gt;) est liée à la question des effets. Une formule logique est vue comme un jeu entre deux joueurs: un qui prouve l'autre qui réfute, ou encore, l'environnement qui fournit une entrée (argument) et la machine qui renvoie une sortie (valeur de retour). Les connecteurs logiques sont attribués à l'un ou à l'autre joueur: dans &lt;code&gt;(int*int)&amp;rarr;(int*int)&lt;/code&gt; c'est d'abord l'environnement qui donne un argument, directement composé de deux entiers; puis la machine calcule un résultat, directement composé de deux entiers. Ici je dis directement, car on ne peut pas demander une réponse partielle à la machine, tout ceci vient d'un coup, une unique réponse à une seule question. La dynamique associée au type &lt;code&gt;int&amp;rarr;int&amp;rarr;(int*int)&lt;/code&gt; est exactement la même: il n'y a pas deux questions à l'environnement, mais une seule, les deux entiers en entrée arrivent d'un coup. Là dedans, les seuls effets ne peuvent donc se situer qu'à l'interface entre les deux joueurs, dans le calcul qui se passe entre une question et une réponse.&lt;br /&gt;&lt;br /&gt;Commençons à redescendons sur terre. Pour introduire la possibilité d'un effet, en focalisation, on peut introduire un délai. Par exemple, si on veut une paire d'entiers paresseuse (dont le contenu n'est calculé que si nécessaire), on retarde le calcul des &lt;code&gt;int&lt;/code&gt;: &lt;code&gt;(unit-&amp;gt;int)*(unit-&amp;gt;int)&lt;/code&gt;. Dans l'autre sens, on peut aussi vouloir retarder le moment où un argument est passé, par exemple avec &lt;code&gt;a-&amp;gt;(unit*(b-&amp;gt;c))&lt;/code&gt;... c'est ce qu'il nous faut!&lt;br /&gt;&lt;br /&gt;On la refait avec un délai autour du décodeur, implémenté non pas comme &lt;code&gt;(unit*...)&lt;/code&gt; mais plus agréablement avec un type variant:&lt;pre&gt;type decoder = Decoder of (buffer -&gt; unit)&lt;br /&gt;type file_decoder = input -&gt; decoder&lt;br /&gt;&lt;br /&gt;let file_decoder filename decoder =&lt;br /&gt;  let input = input_from_file filename in&lt;br /&gt;  let buffer = create_buffer () in&lt;br /&gt;  let Decoder f = decoder input in&lt;br /&gt;  let fill frame =&lt;br /&gt;    while not_enough_data_in buffer do&lt;br /&gt;      f buffer&lt;br /&gt;    done ;&lt;br /&gt;    fill_frame_from_buffer frame buffer&lt;br /&gt;  in&lt;br /&gt;    { fill = fill ; close = fun () -&amp;gt; close input }&lt;br /&gt;&lt;br /&gt;let create_decoder input =&lt;br /&gt;  let resampler = create_resampler () in&lt;br /&gt;  let mad_stream = Mad.openstream input in&lt;br /&gt;    Decoder (fun buffer -&amp;gt;&lt;br /&gt;       let data = Mad.decode_frame_float mad_stream in&lt;br /&gt;       let sample_freq,_,_ = Mad.get_output_format fd in&lt;br /&gt;       let content,length =&lt;br /&gt;         resampler ~audio_src_rate:(float sample_freq) data&lt;br /&gt;       in&lt;br /&gt;         put_audio_in_buffer buffer content length)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Le code du décodeur MP3 n'a changé que d'un iota, mais cela suffit à forcer sa bonne utilisation dans &lt;code&gt;file_decoder&lt;/code&gt;, c'est à dire à passer l'input une fois pour toute, et ne plus passer que le buffer dans les appels suivants. Vraiment? Non, à vrai dire, on peut toujours se prendre les pieds dedans, ne serait-ce que parce que c'est possible de traduire entre le vieux type de décodeur et le nouveau, en violant ainsi la logique qu'on a tenté de forcer. Mais en pratique, ce petit garde fou pousse à faire naturellement la bonne chose, ou au moins à se poser la question.&lt;br /&gt;&lt;br /&gt;Tout est bien qui fini bien. Cette histoire pourrait aussi s'intituler "à quoi diable pourrait bien servir un type variant avec un seul constructeur?" Ou encore, "c'est fou comme de belles idées théoriques ont du sens même en dehors de leur strict cadre théorique."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2099428691046376546?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2099428691046376546/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2099428691046376546' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2099428691046376546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2099428691046376546'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2010/02/quel-effet-ca-fait.html' title='Quel effet ça fait'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-6574897479092879162</id><published>2009-09-08T00:50:00.005+02:00</published><updated>2009-09-15T13:55:57.772+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><title type='text'>Pointilleux</title><content type='html'>Cet été j'ai (re)bricolé à une petite idée, au début en Caml, puis pour diverses raisons je me suis essayé au flash via &lt;a href="http://haxe.org/"&gt;HaXe&lt;/a&gt;. Bah c'est globalement chouette.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;object style="cursor:pointer" align="middle"&gt;&lt;param name="movie" value="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/euh.swf"/&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;param name="quality" value="high" /&gt;&lt;param name="scale" value="noscale" /&gt;&lt;param name="salign" value="lt" /&gt;&lt;embed src="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/euh.swf" bgcolor="#000000" width="400" height="400" quality="high" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /&gt;&lt;/object&gt;&lt;/center&gt;&lt;br /&gt;Ce truc n'est qu'un premier résultat, mais il m'a déja pris trop de temps alors je le lâche ici, en guise d'abandon sur la route du retour de vacances. Par contre je me sens pas encore de lâcher le source (relativement court).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-6574897479092879162?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/6574897479092879162/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=6574897479092879162' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6574897479092879162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6574897479092879162'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/09/pointilleux.html' title='Pointilleux'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-1852273907196452572</id><published>2009-07-17T15:19:00.005+02:00</published><updated>2009-07-17T15:27:37.130+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rien'/><title type='text'>Citations</title><content type='html'>Je viens de retomber sur des citations que j'avais glanées quand je préparais la rédaction de ma thèse. Finalement je n'en ai mis aucune dans mon manuscript, tout simplement. Mais comme je les aime toujours bien, voici.&lt;br /&gt;&lt;blockquote&gt;Reality is that which, when you stop believing in it, doesn't go away.&lt;br /&gt;Philip K. Dick.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;A partir d'un certain moment, il devient simple de comprendre des choses très compliquées; et compliqué de comprendre des choses très simples.&lt;br /&gt;Francis Dannemark, &lt;em&gt;L'hiver ailleurs&lt;/em&gt;.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;La vie n'est ni simple ni complexe, elle est.&lt;br /&gt;Antoine de Saint-Exupéry, &lt;em&gt;Citadelle&lt;/em&gt;, 1948.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Ne parle plus. Ne pense plus. Laisse ta main se promener sur moi. Laisse-la être heureuse toute seule. Tout redeviendrait si simple si tu laissais ta main seule m'aimer. Sans plus rien dire...&lt;br /&gt;Jean Anouilh, &lt;em&gt;Eurydice&lt;/em&gt;, 1942.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Quand on n'a rien à dire, comment le dire simplement.&lt;br /&gt;René Etiemble, &lt;em&gt;L'Hygiène des lettres&lt;/em&gt; (1952-1967), à propos de Julien Gracq.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Simple ne veut pas dire facile.&lt;br /&gt;John Francis Jr, dit Jack Welch.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Il est toujours aisé d'être logique. Il est presque impossible d'être logique jusqu'au bout.&lt;br /&gt;Albert Camus, &lt;em&gt;Le mythe de Sisyphe&lt;/em&gt;, 1942.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Rêver, c'est se choisir soi-même selon une logique chaque fois particulière.&lt;br /&gt;Jean Duvignaud, &lt;em&gt;La Banque des rêves&lt;/em&gt;, 1979.&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;Si la vie réelle est un chaos, en revanche une terrible logique gouverne l'imagination.&lt;br /&gt;Oscar Wilde, &lt;em&gt;Le Portrait de Dorian Gray&lt;/em&gt;, 1891.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-1852273907196452572?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/1852273907196452572/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=1852273907196452572' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1852273907196452572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1852273907196452572'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/07/citations.html' title='Citations'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3022307538306502206</id><published>2009-07-16T08:13:00.009+02:00</published><updated>2009-07-17T21:55:31.896+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='jeu'/><category scheme='http://www.blogger.com/atom/ns#' term='english'/><title type='text'>Illumination</title><content type='html'>For some reason, I've found myself implementing bits of a text-mode &lt;a href="http://en.wikipedia.org/wiki/Roguelike"&gt;rogue-like&lt;/a&gt; game. In a nutshell, this is a turn-based kind of game where the player moves on a grid which usually depicts a dungeon or a cave. Some cells of that grid/map might contain a wall/rock, in which case the player cannot see or walk through them. All this is rather straightforward to implement, but the computation of what the player sees deserves some attention.&lt;br /&gt;&lt;br /&gt;I started thinking of casting rays, but only found clumsy, costly solutions. So I did a little research. Some people (including &lt;a href="http://www.google.com/codesearch/p?hl=fr&amp;sa=N&amp;cd=2&amp;ct=rc#ds1vKBNOpqs/stone_soup-0.2.5-src/source/view.cc&amp;q=monstuff%20crawl&amp;l=994"&gt;crawl&lt;/a&gt;) actually developed algorithms along these lines for computing what is called a &lt;a href="http://roguebasin.roguelikedevelopment.org/index.php?title=Permissive_Field_of_View"&gt;permissive field of view&lt;/a&gt;: &lt;blockquote&gt;A destination square is visible from a source square if there is any unobstructed line from some point in the source square to some point in the destination square.&lt;/blockquote&gt;&lt;br /&gt;It's apparently a modern notion of field of view, that has one advantage over older techniques: it ensures symmetry, i.e., if I can see you, you can see me.&lt;br /&gt;&lt;br /&gt;The same article on roguebasin points to several algorithms, including the one implemented in crawl. They all seemed unsatisfyingly complicated to me. I eventually came up with a different idea that looks good and ensures symmetry. It might have been considered already and discarded for some of its funny aspects, but those are interested to look at.&lt;br /&gt;&lt;br /&gt;The basic idea is to forget about those lines. We are talking about a discrete universe, let's try to make its physics discrete too. &lt;a href="http://en.wikipedia.org/wiki/Geometrical_optics"&gt;Geometrical optics&lt;/a&gt; is only a convenient metaphor, that is justified by more elementary principles such as &lt;a href="http://en.wikipedia.org/wiki/Fermat%27s_principle"&gt;Fermat's&lt;/a&gt;: &lt;blockquote&gt;The path taken between two points of a ray of light is the path that can be traversed in the least time.&lt;/blockquote&gt;&lt;br /&gt;This is in fact a definition of a ray of light that we can take literally in our discrete rogue world: &lt;blockquote&gt;A cell is visible from another if one of the shortest paths between them is unobstructed.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Let's look at a simple example. For now, suppose that the movements are only allowed along the axis (no diagonals):&lt;br /&gt;&lt;center&gt;&lt;pre&gt;.# &lt;br /&gt;@#y&lt;br /&gt;.x.&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;The player is represented by &lt;code&gt;@&lt;/code&gt;, and &lt;code&gt;#&lt;/code&gt; are walls/rocks. The cell marked &lt;code&gt;y&lt;/code&gt; is not visible: it is at distance 2, there is only one path of length 2 that connects it to the player but it is obstructed. Cell &lt;code&gt;x&lt;/code&gt; is also at distance 2, but it is visible since one of the two paths of length 2 that connects it to the player is not obstructed.&lt;br /&gt;&lt;br /&gt;A funny thing happens when you consider the traditional rogue movements which include diagonals: cell &lt;code&gt;y&lt;/code&gt; becomes visible! Indeed, the light can take a path of length 2 through &lt;code&gt;x&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;I would tend to adopt rules where the topology is the same for players and light. Either embrace the diagonal movements but accept the surprising effect on light, or remove them both for the light and the player. I chose the less experimental way for now. But it is also possible to use different topologies for the two entities.&lt;br /&gt;&lt;br /&gt;To finish, I will give the last reason why I like this solution: the code is stupid simple. Assuming that the radius of the field of view will always be within a fixed bound, we can compute once and for all the map of shortest paths with their dependencies.&lt;br /&gt;&lt;pre&gt;(** The maps will be used to associate&lt;br /&gt;  * the coordinates of the destination of a path&lt;br /&gt;  * to the lists of the coordinates of possible previous step&lt;br /&gt;  * in shortest paths leading to that destination. *)&lt;br /&gt;module M = Map.Make (struct type t = int*int let compare = compare end)&lt;br /&gt;&lt;br /&gt;let neighbors (x,y) =&lt;br /&gt;  [ x-1,y ;&lt;br /&gt;    x,y-1 ;&lt;br /&gt;    x+1,y ;&lt;br /&gt;    x,y+1 ]&lt;br /&gt;&lt;br /&gt;let shortest_paths max =&lt;br /&gt;  (** Map of distances to the center of the matrix. *)&lt;br /&gt;  let dist = Array.make_matrix (2*max+1) (2*max+1) max_int in&lt;br /&gt;  (** At each step we compute the shortests paths to cells&lt;br /&gt;    * at distance [d=n+1] from those for distance [n]. *)&lt;br /&gt;  let step d paths_n =&lt;br /&gt;    M.fold&lt;br /&gt;      (fun (x,y) _ m -&gt;&lt;br /&gt;         List.fold_left&lt;br /&gt;           (fun m (x',y') -&gt;&lt;br /&gt;              if dist.(max+x').(max+y') &lt; d then&lt;br /&gt;                (* Seen in a previous iteration. *)&lt;br /&gt;                m&lt;br /&gt;              else if dist.(max+x').(max+y') = d then&lt;br /&gt;                (* We already found a path of length n+1,&lt;br /&gt;                 * but we need to keep track of this new one too. *)&lt;br /&gt;                M.add (x',y') ((x,y)::M.find (x',y') m) m&lt;br /&gt;              else begin&lt;br /&gt;                (* First time we see it: first shortest path. *)&lt;br /&gt;                dist.(max+x').(max+y') &lt;- d ;&lt;br /&gt;                M.add (x',y') [x,y] m&lt;br /&gt;              end)&lt;br /&gt;           m&lt;br /&gt;           (neighbors (x,y)))&lt;br /&gt;      paths_n&lt;br /&gt;      M.empty&lt;br /&gt;  in&lt;br /&gt;  let rec aux d frontiers =&lt;br /&gt;    if d=max then frontiers else&lt;br /&gt;      aux (d+1) (step d (List.hd frontiers) :: frontiers)&lt;br /&gt;  in&lt;br /&gt;    List.rev (aux 1 [M.add (0,0) [] M.empty])&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then, it only remains to parse dependencies:&lt;br /&gt;&lt;pre&gt;(** Takes a radius (d) and returns a field of view function&lt;br /&gt;  * for that radius. *)&lt;br /&gt;let fov d =&lt;br /&gt;  let frontiers = shortest_paths d in&lt;br /&gt;    (* The field of view function,&lt;br /&gt;     * which takes a function and calls it on each visible cell.&lt;br /&gt;     * The function [f] returns whether a cell is transparent or not. *)&lt;br /&gt;    fun f -&gt;&lt;br /&gt;      let transparent = Array.make_matrix (2*d+1) (2*d+1) false in&lt;br /&gt;        transparent.(d).(d) &lt;- true ;&lt;br /&gt;        List.iter&lt;br /&gt;          (fun frontier -&gt;&lt;br /&gt;             M.iter&lt;br /&gt;               (fun (x',y') deps -&gt;&lt;br /&gt;                  if&lt;br /&gt;                    List.exists (fun (x,y) -&gt; transparent.(d+x).(d+y)) deps&lt;br /&gt;                  then&lt;br /&gt;                    transparent.(d+x').(d+y') &lt;- f x' y')&lt;br /&gt;               frontier)&lt;br /&gt;          (List.tl frontiers)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hurray to (impure) functional programming! I leave it to you to glue this to whatever testing code you want. I'll finish with "screenshots".&lt;br /&gt;&lt;br /&gt;Without diagonal moves, notice that it is possible to see through a wall on a diagonal:&lt;br /&gt;&lt;center&gt;&lt;pre&gt;              .&lt;br /&gt;       .      ..&lt;br /&gt;      ..    ##...&lt;br /&gt;     #.. ###...# .&lt;br /&gt;     #..#......##.#&lt;br /&gt;     #.....@......#&lt;br /&gt;     #...##........&lt;br /&gt;     ...#.........&lt;br /&gt;      ###........&lt;br /&gt;        #.......&lt;br /&gt;        ..####.&lt;br /&gt;         .&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;With diagonal moves, we now have shadows along the diagonals, but we can see around walls placed along the axis:&lt;br /&gt;&lt;center&gt;&lt;pre&gt;        ..#..#...&lt;br /&gt;         .......&lt;br /&gt;   .######.....&lt;br /&gt;   ...........&lt;br /&gt;   .##.......&lt;br /&gt;    #.......#&lt;br /&gt;    #.......####   #&lt;br /&gt;    #..........## ..&lt;br /&gt;   .##..##.@....#...&lt;br /&gt;   #...  ##...##..##&lt;br /&gt;   ###    .......###&lt;br /&gt;         ...........&lt;br /&gt;        ............&lt;br /&gt;       .............&lt;br /&gt;      ###...........&lt;br /&gt;        ............&lt;br /&gt;       .##.####.....&lt;br /&gt;&lt;/pre&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3022307538306502206?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3022307538306502206/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3022307538306502206' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3022307538306502206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3022307538306502206'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/07/illumination.html' title='Illumination'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-1095518715716630052</id><published>2009-07-15T18:09:00.003+02:00</published><updated>2009-07-15T18:14:00.804+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Dynamisme=échec</title><content type='html'>Petite update sur le post précédent.&lt;br /&gt;&lt;br /&gt;Après la dernière modification, je me suis rendu compte que je ne prenais pas la linéarité assez au sérieux dans la version actuelle. J'ai essayé de corriger ça, mais je n'ai pas réussi à concilier linéarité et convivialité du système de types (i.e., pas d'annotation barbare).&lt;br /&gt;&lt;br /&gt;La morale est qu'il n'y aura probablement pas de vérification statique du boxing temporel dans liquidsoap 1.0. Ce n'est pas la mort du petit cheval, on a déja une vérification dynamique pour la fallibilité (faite à l'instantiation d'une source). J'espère donc trouver le temps d'implémenter une vérification dynamique du boxing, ce serait largement mieux que le rien actuel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-1095518715716630052?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/1095518715716630052/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=1095518715716630052' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1095518715716630052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/1095518715716630052'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/07/dynamismeechec.html' title='Dynamisme=échec'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-4605953196993492728</id><published>2009-06-04T13:38:00.011+02:00</published><updated>2009-06-06T12:31:26.473+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Mise en boîte</title><content type='html'>Depuis un bon moment, liquidsoap dispose d'un langage de configuration/script fonctionnel, fortement et statiquement typé, qui infère des types à la ML, le tout à l'insu de la plupart des utilisateurs. Pour liquidsoap 1.0 nous irons plus loin dans l'utilisation de concepts avancés avec (un peu) de vrai polymorphisme.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;J'ai &lt;b&gt;édité&lt;/b&gt; ce post deux ou trois dans les jours suivant sa publication. Peut-être que le blog n'était pas le format idéal.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pourquoi?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Dans une conf liquidsoap, les fonctions sont parfois utiles pour éviter de recopier du code, ou pour spécifier une action à effectuer en réaction à certains évenements. Mais au coeur même de la génération du flux, les fonctions sont utilisées pour représenter les transitions entre pistes audio. (Détails &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/jfla08.pdf"&gt;ici&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Cette même notion de transition pose des problèmes quant à l'écoulement du temps. Actuellement dans liquidsoap, toutes les sources de flux audio évoluent à la même vitesse, cadencées par une unique horloge. Pour calculer une transition entre deux pistes d'une même source, l'opérateur &lt;code&gt;cross&lt;/code&gt; doit obtenir en avance le début de la piste suivante, et le combiner avec la fin de la piste en cours. Cela requiert d'accélérer cette source.&lt;br /&gt;&lt;br /&gt;L'implémentation actuelle n'est pas une solution: Les opérateurs qui en ont besoin simulent l'action de l'horloge auprès de leur source, afin de l'accélérer. Cela marche souvent, mais il se peut que deux opérateurs lisent une même source à des vitesses différentes. Le résultat est inattendu, à éviter. Notre mission est d'éviter cela statiquement, avant même la construction des sources. Nous allons donc attacher un paramètre au type des sources, qui représentera son horloge, et spécifier dans le type des opérateurs s'ils requièrent des horloges particulières.&lt;br /&gt;&lt;br /&gt;S'il est assez facile de bricoler le système de type pour obtenir l'effet désiré, il faut d'abord identifier les concepts "logiques" mis en jeux. J'ai honte, mais ça m'a pris du temps, car j'ai &lt;a href="http://savonet.rastageeks.org/wiki/FutureBoxes"&gt;commencé&lt;/a&gt; par chercher dans des contrées exotiques alors que c'est assez connu, bien que pointu.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Polymorphisme&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Le polymorphisme est la possibilité de former une quantification universelle sur les types. Si on a un objet de type &lt;code&gt;&amp;forall;x. x-&gt;x&lt;/code&gt;, on peut l'instantier en une fonction de type &lt;code&gt;int-&gt;int&lt;/code&gt; aussi bien que &lt;code&gt;(bool-&gt;bool)-&gt;(bool-&gt;bool)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Dans les langages dérivés de ML, le polymorphisme est limité à une quantification externe. On peut avoir &lt;code&gt;&amp;forall;x. x-&gt;x&lt;/code&gt; mais pas &lt;code&gt;(&amp;forall;x. x-&gt;x)-&gt;int-&gt;int&lt;/code&gt;. Le polymorphisme dans toute sa généralité, par exemple dans le système F, rend en effet l'inférence de type indécidable.&lt;br /&gt;&lt;br /&gt;OCaml permet cependant d'aller un peu plus loin. La clé est que la création d'un type polymorphe doit être explicite dans le programme (cf. &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.4858"&gt;ce papier&lt;/a&gt;), par exemple associée à la création d'un enregistrement. Considérons la signature suivante:&lt;br /&gt;&lt;div class="code"&gt;(** Une source associée à l'horloge 'a *)&lt;br /&gt;type 'a src&lt;br /&gt;&lt;br /&gt;(** Une fonction qui renvoie une source qu'on peut&lt;br /&gt;  * associer à n'importe quelle horloge. *)&lt;br /&gt;type boxed = { c : 'a. unit -&gt; 'a src }&lt;br /&gt;&lt;br /&gt;(** Cet opérateur prend une source en boîte,&lt;br /&gt;  * cela pourrait être le cross() de liquidsoap. *)&lt;br /&gt;val box  : boxed -&gt; 'a src&lt;br /&gt;&lt;br /&gt;val leaf : unit -&gt; 'a src            (* en gros, single *)&lt;br /&gt;val node : 'a src list -&gt; 'a src     (* en gros, fallback *)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Voyons voir ce qu'on peut et ne peut pas faire avec ce système. On peut créer un certain nombre de sources avec &lt;code&gt;leaf ()&lt;/code&gt; initialement, elles auront le type &lt;code&gt;'_a src&lt;/code&gt;: leur horloge est indéfinie, mais pas généralisable. On est content de ne pas voir de &lt;code&gt;'a src&lt;/code&gt;: cela correspondrait à une source qui peut se brancher sur toutes les horloges &lt;em&gt;à la fois&lt;/em&gt;, non-sens. (C'est aussi pour cela qu'on n'a pas écrit &lt;code&gt;boxed = { c : 'a. 'a src }&lt;/code&gt;, on n'aurait jamais pu construire de boîte.)&lt;br /&gt;&lt;br /&gt;On peut passer une source de type &lt;code&gt;'_a src&lt;/code&gt; à notre opérateur &lt;code&gt;node&lt;/code&gt;, on obtient une autre source à la même horloge &lt;code&gt;'_a&lt;/code&gt;. Si on passe deux sources à &lt;code&gt;node&lt;/code&gt;, le système de type requiert que leurs horloges soient les mêmes (des inconnues &lt;code&gt;'_a&lt;/code&gt; et &lt;code&gt;'_b&lt;/code&gt; sont unifiées).&lt;br /&gt;&lt;br /&gt;Maintenant, tentons de former des boîtes:&lt;br /&gt;&lt;div class="code"&gt;let b = box { c = leaf }&lt;br /&gt;(* Gagné:&lt;br /&gt; * une boîte qui nous donne une nouvelle feuille à chaque fois,&lt;br /&gt; * horloge au choix. *)&lt;br /&gt;&lt;br /&gt;let a = leaf ()&lt;br /&gt;let b = box { c = fun () -&gt; b }&lt;br /&gt;(* Raté, erreur de type:&lt;br /&gt; * la source a est de type '_a src,&lt;br /&gt; * la fonction (fun () -&gt; b) est de type unit -&gt; '_a src,&lt;br /&gt; * qu'on ne peut généraliser en 'a. unit -&gt; 'a src. *)&lt;br /&gt;&lt;br /&gt;let b =&lt;br /&gt;  box { c = fun () -&gt;&lt;br /&gt;              let a = leaf () in&lt;br /&gt;                 node [a;a] }&lt;br /&gt;(* Gagné, on a une boîte qui nous renvoie une source composée,&lt;br /&gt; * dont on peut choisir l'horloge. *)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;On tient clairement le bon concept: le polymorphisme assure que l'horloge peut être choisie. En particulier on va pouvoir créer des nouvelles horloges dédiées à certaines sources (et leurs sous-sources). Reste à transférer ce petit exemple en quelquechose d'agréable à utiliser dans liquidsoap.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Liquidsoap 1.0&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Actuellement dans liquidsoap, on écrit des choses comme:&lt;br /&gt;&lt;div class="code"&gt;music = playlist("list.txt")&lt;br /&gt;backup = single("default.ogg")&lt;br /&gt;source = fallback([music,backup])&lt;br /&gt;transition = fun (a,b) -&gt; ...&lt;br /&gt;source = cross(transition,source)&lt;br /&gt;output.icecast(source)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;En collant au style de notre exemple en OCaml, nous devrions réécrire les choses ainsi:&lt;br /&gt;&lt;div class="code"&gt;transition = fun (a,b) -&gt; ...&lt;br /&gt;source =&lt;br /&gt;  cross(transition, {&lt;br /&gt;    music = playlist("list.txt")&lt;br /&gt;    backup = single("default.ogg")&lt;br /&gt;    fallback([music,backup])&lt;br /&gt;  })&lt;br /&gt;output.icecast(source)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;C'est trop lourd, et ma solution ne va différer que d'un epsilon du style courant:&lt;br /&gt;&lt;div class="code"&gt;music = playlist("list.txt")&lt;br /&gt;backup = single("default.ogg")&lt;br /&gt;source = fallback([music,backup])&lt;br /&gt;transition = fun (a,b) -&gt; ...&lt;br /&gt;source = cross(transition,{source})&lt;br /&gt;output.icecast(source)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Un point clé qui permet cette simplification est qu'on n'a besoin que d'une partie du polymorphisme: on veut la généricité, mais une seule fois. Pas besoin d'une fonction qui à chaque appel pond une source, comme dans l'exemple en Caml. Il suffit d'une seule source, tant que son horloge est générique.&lt;br /&gt;&lt;br /&gt;Je pense qu'on ne peut pas se passer aisément du marqueur &lt;code&gt;{source}&lt;/code&gt; qui indique qu'on généralise cette source. Il me semble acceptable de demander à l'utilisateur de marquer le coup quand il utilise cette notion complexe. (Par contre il va nous falloir choisir une syntaxe qui ne rentre pas en conflit avec l'actuel &lt;code&gt;{...}&lt;/code&gt;, raccourci pour &lt;code&gt;fun () -&gt; ...&lt;/code&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Comment ça marche&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;J'ai une &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/boxes.ml.html"&gt;implémentation&lt;/a&gt; en OCaml qui me semble transposable à liquidsoap.&lt;br /&gt;&lt;br /&gt;Comment OCaml vérifie-t-il que &lt;code&gt;{ c = fun () -&gt; blah }&lt;/code&gt; est bien typé? Il introduit une nouvelle variable de type &lt;code&gt;n&lt;/code&gt; pour représenter le &lt;code&gt;'a&lt;/code&gt; de &lt;code&gt;'a. unit -&gt; 'a src&lt;/code&gt;, et vérifie qu'on peut donner le type &lt;code&gt;n src&lt;/code&gt; à &lt;code&gt;blah&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Nous allons faire la même chose, mais dans le désordre, pour permettre le genre d'écriture promis plus haut. Pour former une boîte (un type universel) sur une source, il faut que son horloge soit encore indéterminée. On vérifie cela en unifiant le type de cette source avec &lt;code&gt;n src&lt;/code&gt; pour une nouvelle variable de type &lt;code&gt;n&lt;/code&gt; comme OCaml faisait. Et une fois qu'on a ainsi réussit à former une boîte, on affecte cette variable à type à une valeur interdite &lt;code&gt;Boom&lt;/code&gt; pour empêcher son utilisation ailleurs. Au lieu de créer les sources dans une zone protégée, on les crée en dehors, et on les y affecte après coup, ce qui rend alors leur horloge dénuée de sens à l'extérieur.&lt;br /&gt;&lt;br /&gt;Un difficulté essentielle du polymorphisme vient du fait que pour inférer, on a besoin de savoir quel type universel on forme. Dans le cas de liquidsoap ma solution est très simple: on ne forme que &lt;code&gt;&amp;forall;x. x src&lt;/code&gt;. On pourrait avoir d'autres types polymorphes, mais chacun aurait son constructeur particulier.&lt;br /&gt;&lt;br /&gt;Ces mécanismes fonctionnent bien sur quelques exemples disponibles dans mon code:&lt;br /&gt;&lt;div class="code"&gt;ex0 = single ()&lt;br /&gt;ex0 : '_a src   # pas de généralisation, c'est comme avec ref&lt;br /&gt;&lt;br /&gt;ex00 = let x = single () in {x}&lt;br /&gt;ex00 : 'a. 'a src&lt;br /&gt;&lt;br /&gt;ex1 = fun (x) -&gt; cross(x)&lt;br /&gt;ex1 : 'b. ('a. 'a src) -&gt; 'b src&lt;br /&gt;&lt;br /&gt;ex4 = fun (_) -&gt; cross({single("blah.ogg")})&lt;br /&gt;ex4 : 'a.'b. 'a -&gt; 'b src&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Un exemple plus subtil est &lt;code&gt;ex2 = fun (x) -&gt; {x}&lt;/code&gt;, ou la variation &lt;code&gt;ex4 = fun (x) -&gt; cross({x})&lt;/code&gt; qui se rapproche de &lt;code&gt;ex1&lt;/code&gt;. Ici une boîte est formée sur l'argument de la fonction, qui doit donc être une source. Ce genre de construction est problématique: la source doit être introduite avant son horloge. En pratique, cela se traduit par l'impossibilité de former le type de la fonction où devrait apparaitre le symbole interdit: &lt;code&gt;Boom src -&gt; 'a. 'a src&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4605953196993492728?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4605953196993492728/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4605953196993492728' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4605953196993492728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4605953196993492728'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/06/mise-en-boite.html' title='Mise en boîte'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-7997152217625800003</id><published>2009-05-05T10:56:00.003+02:00</published><updated>2009-05-05T10:59:16.161+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='informatique'/><category scheme='http://www.blogger.com/atom/ns#' term='libertés'/><title type='text'>Fouille de documents informatiques</title><content type='html'>Ca fait plusieurs fois que je le lis, cette fois-ci d'une source officielle (CNRS), alors je l'écris pour les incrédules:&lt;br /&gt;&lt;quote&gt;&lt;br /&gt;Il est fermement déconseillé d’emporter à l’étranger des supports informatiques contenant (ou ayant contenu) des données sensibles voire des données privées. Ces supports informatiques (ordinateurs portables, PDA, clés USB, CD, DVD, disques amovibles…) peuvent être perdus, volés ou frauduleusement consultés.&lt;br /&gt;Ils peuvent aussi faire l’objet d’un contrôle par les autorités douanières de certains pays.&lt;br /&gt;C’est le cas notamment aux Etats-Unis où des dispositions réglementaires récentes autorisent les douanes américaines à procéder à la fouille de documents informatiques (Instruction du 16 juillet 2008 « Policy Regarding Border Search of Information »).&lt;br /&gt;Sous certaines conditions, les douaniers peuvent même exiger la consultation en clair de dossiers chiffrés et, si nécessaire, avoir recours à des moyens de déchiffrement.&lt;br /&gt;&lt;/quote&gt;&lt;br /&gt;Le risque concerne bien sûr la vie privée mais aussi des fichiers illégaux, ou dont la légalité serait difficile à justifier auprès d'un douanier...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-7997152217625800003?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/7997152217625800003/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=7997152217625800003' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7997152217625800003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7997152217625800003'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/05/fouille-de-documents-informatiques.html' title='Fouille de documents informatiques'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8831858578097554138</id><published>2009-03-22T03:10:00.008+01:00</published><updated>2010-02-08T18:29:52.441+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='anarchie'/><category scheme='http://www.blogger.com/atom/ns#' term='bd'/><category scheme='http://www.blogger.com/atom/ns#' term='voyage'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>La vraie vie</title><content type='html'>Le regard varie selon l'humeur. Je me suis plutôt bien accomodé de ma situation de visiteur de passage à Pittsburgh. Par exemple, après la morne absence de café à la maison, je me suis mis au soluble: wouahou, carrément mieux que rien quand on a pas envie de sortir pour petit-déjeuner. Mais bon, là je m'en lasse, et ça me fait penser à une chanson d'un groupe d'ici.&lt;br /&gt;&lt;br /&gt;&lt;!--&lt;object width="450" height="295"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-CD6nXYr34s&amp;hl=fr&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/-CD6nXYr34s&amp;hl=fr&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="450" height="295"&gt;&lt;/embed&gt;&lt;/object&gt;--&gt;&lt;br /&gt;(Ici, il y avait une vidéo, mais le lien ne pointe plus sur la bonne alors fuck off.)&lt;br /&gt;&lt;br /&gt;Sinon, vous pouvez lire:&lt;ul&gt;&lt;li&gt;&lt;a href="http://crapart.spacebar.org/"&gt;Crap art&lt;/a&gt;: The creation of art is more important than its consumption.&lt;/li&gt;&lt;li&gt;Watchmen, le livre pas le film, et surtout l'auteur &lt;a href="http://www.avclub.com/articles/alan-moore,13740/"&gt;Alan Moore&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Si vous trouvez ce post vide, disons que c'est du micro-blogging, c'est à la mode... (même &lt;a href="http://search.twitter.com/search?q=%23liquidsoap"&gt;liquidsoap&lt;/a&gt; est dans le coup).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8831858578097554138?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8831858578097554138/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8831858578097554138' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8831858578097554138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8831858578097554138'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/03/la-vraie-vie.html' title='La vraie vie'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-7137541156691583050</id><published>2009-02-27T22:54:00.005+01:00</published><updated>2009-02-28T01:43:19.672+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='logique'/><title type='text'>La plus grosse</title><content type='html'>Franchement, c'est lourd...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lAKV-lpQ4_s/Sahhcn31NXI/AAAAAAAAACM/DLFSRxTeSMA/s1600-h/eq.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 20px;" src="http://2.bp.blogspot.com/_lAKV-lpQ4_s/Sahhcn31NXI/AAAAAAAAACM/DLFSRxTeSMA/s400/eq.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5307599305223517554" /&gt;&lt;/a&gt;&lt;br /&gt;Pour y voir quelquechose, voici la version &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/eq.xml.ps"&gt;postscript&lt;/a&gt; (ou &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/eq.xml.png"&gt;un GROS PNG&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-7137541156691583050?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/7137541156691583050/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=7137541156691583050' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7137541156691583050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7137541156691583050'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2009/02/la-plus-grosse.html' title='La plus grosse'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_lAKV-lpQ4_s/Sahhcn31NXI/AAAAAAAAACM/DLFSRxTeSMA/s72-c/eq.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8603733573407148489</id><published>2008-12-17T01:43:00.005+01:00</published><updated>2008-12-17T02:28:44.597+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Queues</title><content type='html'>La suite du billet précédent...&lt;br /&gt;&lt;br /&gt;Initialement, je me suis mis à Mercurial dans l'idée de mieux gérer mes projets, à commencer par &lt;a href="http://savonet.sf.net"&gt;Savonet&lt;/a&gt;. J'ai commencé par tester Mercurial sur un projet en solo, où j'utilise des &lt;a href="http://www.lri.fr/~filliatr/ftp/publis/cordes.pdf"&gt;ropes&lt;/a&gt; annotées (oui, c'est une réponse lapidaire à un &lt;a href="http://misterpingouin.blogspot.com/2008/10/exercice.html"&gt;billet précédent&lt;/a&gt;) pour écrire proprement un éditeur de texte qui supporte bien l'analyse lexicale et syntaxique du texte (oui, c'est &lt;a href="https://gna.org/projects/bed/"&gt;bed&lt;/a&gt;). Cela m'avait plu, et inspiré les remarques du précédent billet.&lt;br /&gt;&lt;br /&gt;Maintenant, quel interêt a Mercurial pour un projet comme Savonet? Nous avons actuellement un écosystème assez bien foutu autour de notre SVN, dont nous sommes globalement contents. Pas de vrai besoin de décentralisation, ni de super gestion des branches. Les apports de Mercurial seraient en fait: le commit local, les queues de patchs. Je ne parlerai que des queues de patchs car elles permettent grosso modo d'émuler le commit local de toutes façons.&lt;br /&gt;&lt;br /&gt;Dans Mercurial, un patch est une modification (révision, &lt;em&gt;changeset&lt;/em&gt;...) modifiable. Imaginez faire quelques commits, puis vouloir en fusionner deux ou en modifier un. C'est quelque chose de risqué: si quelqun a déja vos modifications et que vous les modifiez, c'est très dur de se resynchroniser. Mais si les modifications sont restées locales, tout va bien. Et ça peut être très pratique pour éviter de se retrouver avec un historique SVN plein de modifications type "Typo", "Oops, I didn't mean to commit that file" ou encore "Remove debug code" et autres "Fixed the fix".&lt;br /&gt;&lt;br /&gt;Les patchs sont gérées dans une queue, d'où l'appellation &lt;em&gt;mercurial queue&lt;/em&gt; (MQ). C'est à dire qu'on va avoir une queue de modifications en attente, qu'on peut appliquer à son dépôt, ou annuler de façon très pratique. Par exemple, on va avoir un patch avec du code de debug, un patch avec un correctif, et on peut rapidement enlever l'un ou l'autre pour tester si le correctif a bien l'effet voulu, avec plus ou moins d'informations affichées. Une fois qu'on a un patch bien propre, on peut le transformer en révision normale et la partager avec le monde. Si on a envie de passer à autre chose, on met le patch en attente. Avant, pour faire ça, j'avais plusieurs copies du dépôt Savonet: une pour bosser le système de type, une pour bosser sur le smart cross, etc.&lt;br /&gt;&lt;br /&gt;Travailler avec MQ est très intuitif et très pratique. Je me suis donc demandé comment l'utiliser pour Savonet, pour espérer avoir un jour des logs un peu plus lisibles.&lt;br /&gt;&lt;br /&gt;J'ai testé &lt;a href="http://www.bitbucket.org/durin42/hgsubversion/wiki/Home"&gt;hgsubversion&lt;/a&gt; pour convertir le dépôt SVN de savonet en Mercurial. Bien qu'expérimentale, cette extension marche bien, et surtout bien plus rapidement que l'import SVN actuellement officiellement inclus dans Mercurial. On obtient un dépôt Mercurial avec tout l'historique SVN, et on peut échanger de nouvelles révisions avec le dépôt SVN. J'ai ainsi pu élaborer un patch, puis le commiter &lt;a href="http://savonet.rastageeks.org/changeset/6232"&gt;sur le SVN&lt;/a&gt;. Par contre, il semble inutile de vouloir partager le dépôt Mercurial et mélanger le versioning Mercurial et SVN, ça pète assez vite. En plus, on perd quelques trucs propres au SVN dans Savonet: l'inclusion de la révision SVN dans la version, et les liens &lt;code&gt;external&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Une autre possibilité est de rester à SVN mais d'utiliser MQ par dessus. Cela implique encore de mélanger le versioning SVN et Mercurial: si on fait une mise a jour SVN, il faut la propager à la main dans le dépôt Mercurial, avant de ré-appliquer éventuellement les patches en queue. Je n'ai pas encore essayé, mais je ne suis pas très optimiste.&lt;br /&gt;&lt;br /&gt;Enfin, on peut utiliser les outils de gestion de patches qui ont inspiré MQ, notamment &lt;a href="http://savannah.nongnu.org/projects/quilt/"&gt;quilt&lt;/a&gt;. Je me disais qu'il n'y avait pas tant que ça à perdre, mais ils ne mentent pas dans Mercurial: l'intégration des queues dans Mercurial même fait toute la différence. Il est beaucoup plus pénible de bosser avec quilt: par exemple, il n'a aucun moyen de savoir qu'un fichier est modifié par rapport à sa version SVN, et donc de passer cette modification locale dans un patch. On peut &lt;a href="http://www.carfax.org.uk/node/35"&gt;bricoler&lt;/a&gt; deux trois trucs, et arriver à &lt;a href="http://savonet.rastageeks.org/changeset/6257"&gt;ses&lt;/a&gt; &lt;a href="http://savonet.rastageeks.org/changeset/6258"&gt;fins&lt;/a&gt;, mais ça reste peu confortable. Au fond, quilt ne m'inspire pas trop, c'est assez rugueux à l'usage, pis... c'est codé en shell.&lt;br /&gt;&lt;br /&gt;Bref, il y a encore du boulot pour pousser les développeurs Savonet à tous utiliser un gestionnaire de patches avant de passer une modif sur le SVN. La seule chose claire dans tout ça, c'est qu'on peut déja utiliser ma queue de patches, quel que soit l'outil et la méthode, c'est relativement standard: elle est publiée (sous forme de dépôt Mercurial) sur &lt;a href="http://dolebrai.net/~dbaelde/savonet_patches/"&gt;dolebrai.net&lt;/a&gt;. C'était d'abord une queue Mercurial mais je l'utilise désormais via quilt sur des dépôts SVN. Dans les deux cas je partage ainsi des patchs entre mon portable et le serveur: ainsi, je ne salis pas le SVN pour tester sur le serveur une modif en cours d'élaboration.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8603733573407148489?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8603733573407148489/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8603733573407148489' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8603733573407148489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8603733573407148489'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/12/queues.html' title='Queues'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-6455934255784078063</id><published>2008-12-07T20:02:00.010+01:00</published><updated>2008-12-07T22:23:49.323+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Gestion de code pour les nuls</title><content type='html'>Les programmeurs qui travaillent en groupe ont l'habitude d'utiliser des outils pour contrôler l'évolution de leur code source. Ces outils peuvent en fait être utiles à quiconque travaille sur du texte. Par exemple, j'utilise &lt;a href="http://subversion.tigris.org/"&gt;SVN&lt;/a&gt; aussi bien pour développer &lt;a href="http://savonet.sf.net"&gt;savonet&lt;/a&gt; que pour rédiger des articles à plusieurs, ou ma thèse tout seul. Leur utilité est par contre grandement réduite pour des fichiers comme des images ou du son, mais aussi un document de traitement de texte: c'est un avantage quand on travaille avec LaTeX ou HTML, le document est du texte brut, contrairement aux divers Machin Office.&lt;br /&gt;&lt;br /&gt;Un objectif clair quand on travaille à plusieurs est d'éviter les conflits. Monsieur Machin et Madame Bidule font des modifications en même temps, il faut que tout le monde puisse en profiter, si possible fusionner les modifications (si elles portent sur des morceaux de texte différents) et sinon signaler le conflit et permettre de le résoudre manuellement.&lt;br /&gt;&lt;br /&gt;Même quand on travaille seul, ces outils sont très utiles car il permettent de suivre l'évolution d'un fichier ("Quand et pourquoi ai-je changé cette ligne?") de récupérer une version précédente, de visualiser les modifications entre plusieurs versions, et bien d'autres choses.&lt;br /&gt;&lt;br /&gt;En ce moment, la gestion de version &lt;em&gt;distribuée&lt;/em&gt; (&lt;a href="http://en.wikipedia.org/wiki/Distributed_Concurrent_Versions_System"&gt;DCVS&lt;/a&gt;) a le vent en poupe. C'est conceptuellement perturbant pour ceux qui connaissent la traditionelle gestion centralisée. Mais la décentralisation simplifie beaucoup de choses. Notamment, pour commencer à travailler avec un outil centralisé il faut (1) créer un dépôt central puis (2) obtenir une copie de travail de ce dépot. C'est souvent un peu fastidieux. Avec un outil distribué (décentralisé) les dépôts sont partout, attachés à chaque copie de travail. Créer un nouveau dépôt est une opération très naturelle et simple.&lt;br /&gt;&lt;br /&gt;J'ai récemment commencé à utiliser &lt;a href="http://www.selenic.com/mercurial/"&gt;Mercurial&lt;/a&gt;, ce qui m'a d'abord mené à l'observation ci-dessus. J'ai ensuite découvert d'autres avantages. Mais j'aimerais ici présenter à quel point il est aisé d'utiliser Mercurial pour un usage personnel. Comme pré-requis, il faut cependant savoir un petit peu utiliser le shell. Les personnes visées sont surtout celles qui n'ont jamais utilisé d'outil de gestion de code. Par la suite je présenterai peut être une utilisation plus avancée.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Créer un dépôt&lt;/h3&gt;&lt;br /&gt;Vous avez un répertoire dans lequel vous développez un projet: un livre, quelques pages, des programmes, n'importe. Pour commencer à utiliser Mercurial, qu'on appelle hg pour faire court (c'est le code de l'élément Mercure en chimie), placez vous dans ce répertoire et commandez simplement: &lt;code&gt;hg init&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Cette commande initialise, dans le sous-répertoire caché &lt;code&gt;.hg&lt;/code&gt;, une quantité d'informations dont Mercurial a l'usage. Ce sous-répertoire incarne le &lt;em&gt;dépot&lt;/em&gt;, qui va tracer toute l'histoire de (certains de) vos fichiers, et les fichiers avec lesquels vous travaillerez comme avant constituent votre &lt;em&gt;copie de travail&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Le travail comme d'habitude&lt;/h2&gt;&lt;br /&gt;&lt;h3&gt;Ajouter des fichiers au dépôt&lt;/h3&gt;&lt;br /&gt;Mercurial ne s'occupe pas de suivre un fichier si on ne lui demande pas. Sinon, il suivrait tout un tas de fichiers temporaires, ce qui serait gênant -- dans un contexte ou on partage un dépôt, on veut aussi éviter de tracer des fichiers secrets. Pour commencer à suivre un fichier, on utilise la commande: &lt;code&gt;hg add FICHIER_1 FICHIER_2 ...&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Cette commande ne répond rien de spécial, elle prend note, c'est tout. Après cela, vous pouvez continuer de modifier vos fichiers comme avant.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Enregistrer une modification&lt;/h3&gt;&lt;br /&gt;Quand vous pensez avoir atteint un point critique dans votre travail, fini une partie important, ou sur le point de commencer quelque chose de délicat, ou tout simplement si vous avez envie de sauvegarder votre travail, il faut enregistrer vos modifications: &lt;code&gt;hg commit&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Cette commande va vous demander de saisir un message décrivant la modification. Cela peut paraitre ennuyant mais c'est bien pratique quand on revient plus tard, pour comprendre une modification.&lt;br /&gt;&lt;br /&gt;Il est possible de n'enregistrer les modifications que sur certains fichiers: &lt;code&gt;hg commit FICHIER_1 FICHIER_2&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Supprimer un fichier&lt;/h3&gt;&lt;br /&gt;Quand on veut supprimer un fichier, il faut aussi le dire à Mercurial: &lt;code&gt;hg remove FICHIER&lt;/code&gt;. Au prochain &lt;code&gt;commit&lt;/code&gt; le fichier sera effacé et Mercurial arrêtera d'essayer de le suivre.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Les nouvelles possibilités&lt;/h2&gt;&lt;br /&gt;&lt;h3&gt;Visualiser les modifications en cours&lt;/h3&gt;&lt;br /&gt;Un premier avantage est la possibilité de visualiser rapidement les modifications apportées depuis la dernière sauvegarde (le dernier &lt;em&gt;commit&lt;/em&gt;). Pour cela: &lt;code&gt;hg diff&lt;/code&gt;, ou &lt;code&gt;hg diff FICHIERS&lt;/code&gt; si on ne s'intéresse qu'à certains fichiers. Cette commande est bien pratique pour voir où on en est, vérifier que tout est propre avant d'enregistrer et de documenter une modification.&lt;br /&gt;&lt;br /&gt;On peut aussi avoir un aperçu du statut de nos fichiers: &lt;code&gt;hg stat&lt;/code&gt; (parfois verbeux) ou &lt;code&gt;hg stat -m&lt;/code&gt; pour avoir la liste des fichiers modifiés.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Visualiser, visuellement&lt;/h3&gt;&lt;br /&gt;La commande &lt;code&gt;diff&lt;/code&gt; permet aussi de voir les différences entre des versions enregistrées dans le dépot, cf. &lt;code&gt;hg help diff&lt;/code&gt;. Il y a deux façons plus conviviales de faire cela, et plus encore. D'abord, &lt;code&gt;hg view&lt;/code&gt; qui permet de naviguer dans la liste des révisions et permet de voir les modifications associées à chacune. Plus agréable, &lt;code&gt;hg serve&lt;/code&gt; lance un serveur en local sur le port 8000: dans votre navigateur, à l'adresse &lt;code&gt;http://localhost:8000&lt;/code&gt;, vous pourrez naviguer dans les révisions et les fichiers, visualiser des différences et des versions passées.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Annuler une modification&lt;/h3&gt;&lt;br /&gt;Souvent, on se rend compte d'une erreur, avec ou sans l'aide de Mercurial pour comparer aux versions précédentes. Parfois, il est facile de la corriger. Mais ce n'est pas toujours le cas, et on souhaite alors pouvoir tout simplement annuler un ensemble de modifications enregistrées. Pour cela il y a la commande &lt;code&gt;revert&lt;/code&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tout seul, &lt;code&gt;hg revert --all&lt;/code&gt; annule les modifications non sauvergardées, et annule aussi les ajouts/suppressions de fichiers. On peut lui spécifier un ou plusieurs fichiers en particulier, au lieu de &lt;code&gt;--all&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;On peut aussi faire &lt;code&gt;hg revert -r -2 [FICHIER ou --all]&lt;/code&gt; pour revenir à la version précédente enregistrée, &lt;code&gt;-3&lt;/code&gt; encore un cran avant, etc. La version &lt;code&gt;-1&lt;/code&gt; est la dernière version enregistrée, c'est donc équivalent à ne pas passer d'option &lt;code&gt;-r&lt;/code&gt;. Attention, dans tous les cas on perd aussi les modifications non enregistrées.&lt;/li&gt;&lt;li&gt;Finalement on peut utiliser &lt;code&gt;-r REV&lt;/code&gt; où &lt;code&gt;REV&lt;/code&gt; est l'entier positif désignant une version, telle qu'on peut le lire via &lt;code&gt;hg view/serve/log&lt;/code&gt;. Par exemple la dénomination complète d'une version sera &lt;code&gt;2:26e8052bce45&lt;/code&gt; mais &lt;code&gt;2&lt;/code&gt; suffit pour la désigner. Même remarque qu'avant: attention, cela supprime les modifications en cours.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Fini&lt;/h2&gt;&lt;br /&gt;Il y aurait encore beaucoup à dire mais pour une utilisation simple c'est déja largement suffisant. En cas de doute au cours de votre apprentissage, n'hésitez pas à faire une copie sauvegarde de votre répertoire, le dépôt caché dedans sera sauvé aussi.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-6455934255784078063?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/6455934255784078063/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=6455934255784078063' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6455934255784078063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6455934255784078063'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/12/gestion-de-code-pour-les-nuls.html' title='Gestion de code pour les nuls'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8098595735200176363</id><published>2008-10-13T15:15:00.007+02:00</published><updated>2008-10-13T15:27:58.653+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><title type='text'>Exercice</title><content type='html'>Il me reste treize jours pour finir de rédiger ma thèse. Pendant ce temps là, pour que je ne sois pas le seul à bosser, voici un petit exercice de prog qui m'est passé par la tête. On peut représenter du texte par le type &lt;code&gt;string&lt;/code&gt; en Caml. On veut ensuite représenter du texte annoté, quand les annotations forment un arbre: soit deux annotations sont disjointes, soit l'une est incluse dans l'autre. Pensez par exemple à la grammaire au collège, "sujet" , "verbe", "complément" sont regroupés pour former une "phrase":&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;type annot =&lt;br /&gt;  (* Par exemple.. *)&lt;br /&gt;  | Sujet | Verbe | Complément | Phrase&lt;br /&gt;type t =&lt;br /&gt;  | Text of string&lt;br /&gt;  | Annot of string * t&lt;br /&gt;  | Concat of t list&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Il est aisé de travailler avec ce type. Et il représente exactement ce qu'on veut, il y a bijection. Maintenant, je veux une solution aussi satisfaisante quand les annotations ne forment plus un arbre mais peuvent se recouvrir partiellement. Pensez par exemple à du HTML mal formé: &lt;code&gt;&amp;lt;red&amp;gt;b&amp;lt;b&amp;gt;a&amp;lt;/red&amp;gt;b&amp;lt;/b&amp;gt;i&lt;/code&gt;. Sauf que moi j'ai une utilisation moins crade en tête, mais c'est une autre histoire. Vos idées sont bienvenues, sinon je posterai peut être une solution plus tard...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8098595735200176363?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8098595735200176363/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8098595735200176363' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8098595735200176363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8098595735200176363'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/10/exercice.html' title='Exercice'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5650046921118878819</id><published>2008-09-01T07:29:00.003+02:00</published><updated>2008-09-01T07:41:56.267+02:00</updated><title type='text'>Je me demande</title><content type='html'>Cette nuit je fais un rêve, dont les détails m'échappent forcément déja. De temps en temps, j'essaie de faire &lt;em&gt;quelquechose&lt;/em&gt;, et ça foire en faisant un petit &lt;em&gt;boum&lt;/em&gt;. La deux ou troisième fois, je me réveille un peu pour réaliser que ce bruit n'est autre que celui de la porte qui claque.&lt;br /&gt;&lt;br /&gt;Comment ça marche? Des scientifiques savent peut-être. Je vois deux solutions. Soit le rêve est juste une histoire qui se déroule "toute seule". Alors, la perception de la porte peut créer la tentative d'action -- la causalité se renverse juste. Soit il y a un dialogue, où une partie de mon cerveau projette un rêve que je (une autre partie de mon cerveau) peux influer par mes choix. Dans ce cas, qu'est-ce qui se passe si je n'agis pas dans le rêve, si le bruit ne peut se coller sur aucun élement du rêve? Peut-être la perception est-elle mise en attente un moment, et recrachée (un peu déformée/adaptée) dans le rêve un peu plus tard si une opportunité se présente.&lt;br /&gt;&lt;br /&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5650046921118878819?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5650046921118878819/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5650046921118878819' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5650046921118878819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5650046921118878819'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/09/je-me-demande.html' title='Je me demande'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2300831941714103617</id><published>2008-07-03T14:53:00.008+02:00</published><updated>2008-07-05T10:14:22.459+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='radio'/><category scheme='http://www.blogger.com/atom/ns#' term='musique'/><category scheme='http://www.blogger.com/atom/ns#' term='savonet'/><category scheme='http://www.blogger.com/atom/ns#' term='these'/><title type='text'>Time flies</title><content type='html'>Non, je n'écris pas une nouvelle de science fiction sur des mouches qui voyageraient dans le temps. Le temps passe vite, c'est tout. Il est bien rempli. Niveau boulot, un fichier &lt;code&gt;phd.tex&lt;/code&gt; et une conférence aux &amp;Eacute;tats-Unix suivie d'une visite intense de NYC. Niveau Savonet on a publié la 0.3.7 et annoncé des &lt;a href="http://www.mail-archive.com/savonet-users@lists.sourceforge.net/msg00500.html"&gt;bières gratuites mecredi en huit au Corcoran&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;De son côté Frank a publié la seconde compilation &lt;a href="http://dolebrai.net"&gt;Dolebraï&lt;/a&gt;, un peu plus électro que la précédente mais démontrant néanmoins encore une fois la richesse de la scène libre -- à moins que son but soit plutôt d'aider les paresseux mais néanmoins convaincus à trouver les joyaux dans la botte de paille. Il y a quelques morceaux sélectionnés par moi, mais l'envie m'a pris de jouer avec les widgets Jamendo et de vous proposer ici plus de morceaux de ma sélection.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;object width="200" height="300" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" align="middle"&gt; &lt;param name="allowScriptAccess" value="always" /&gt;&lt;param name="wmode" value="transparent" /&gt; &lt;param name="movie" value="http://widgets.jamendo.com/fr/playlist/?playertype=2008&amp;playlist_id=68944" /&gt; &lt;param name="quality" value="high" /&gt; &lt;param name="bgcolor" value="#FFFFFF" /&gt; &lt;embed src="http://widgets.jamendo.com/fr/playlist/?playertype=2008&amp;playlist_id=68944" base="http://widgets.jamendo.com/fr/playlist/" quality="high" wmode="transparent" bgcolor="#FFFFFF" width="200" height="300" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"&gt;&amp;nbsp;&lt;/embed&gt;&amp;nbsp;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Bien sûr il y a aussi beaucoup de bons artistes absents de Jamendo. Vous pouvez toujours aller voir leurs pages Dolebraï: &lt;a href="http://dolebrai.net/playlist/morceau/peyote-sunrise-psyrok"&gt;Peyote Sunrise&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/redemption-baroque-dub-remix-sure-dread"&gt;Redemption (Baroque Dub Remix)&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/seedin-time-in-the-oak-room-loveshadow"&gt;Seeding Time In The Oak Room&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/i-saw-my-lady-weep-panic-ensemble"&gt;I Saw My Lady Weep&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/tattoo-beatmapper"&gt;Tattoo (Remix)&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/cutting-tags-off-new-pants-brotherhood-of-the-drill--mc"&gt;Cutting Tags Off New Pants&lt;/a&gt;, &lt;a href="http://dolebrai.net/playlist/morceau/sideburn-margin-of-safety"&gt;Sideburn&lt;/a&gt;, etc.&lt;br /&gt;&lt;br /&gt;En fait, écoutez toute &lt;a href="http://dolebrai.net/blog/2008/06/24/compilation-dolebrai-volume-02/"&gt;la compil #2&lt;/a&gt; et faites moi une critique de 1000 mots pour lundi!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2300831941714103617?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2300831941714103617/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2300831941714103617' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2300831941714103617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2300831941714103617'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/07/time-flies.html' title='Time flies'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2339529904874251124</id><published>2008-03-06T09:35:00.007+01:00</published><updated>2008-10-03T08:22:42.565+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><category scheme='http://www.blogger.com/atom/ns#' term='logique'/><title type='text'>Blagues</title><content type='html'>En attendant de finir un post passionant sur le polymorphisme dans OCaml, justifions le nom de ce blog...&lt;br /&gt;&lt;br /&gt;Ces temps-ci je m'amuse beaucoup des sujets des spams que je reçois. Mon préféré est arrivé ce matin: &lt;code&gt;[SPAM] Are there any side effects?&lt;/code&gt; Choix judicieux pour les adresses récoltées sur les mailing-listes de programmation fonctionnelle.&lt;br /&gt;&lt;br /&gt;Olivier, l'autre jour dans le RER, m'a fait part d'une autre interprétation obsessive perchée, devant l'affiche formidable de &lt;em&gt;2&lt;sup&gt;ème&lt;/sup&gt; sous-sol&lt;/em&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_lAKV-lpQ4_s/R8-txybw8bI/AAAAAAAAABE/C8_6pVAQIn0/s1600-h/133_73031.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_lAKV-lpQ4_s/R8-txybw8bI/AAAAAAAAABE/C8_6pVAQIn0/s320/133_73031.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5174545567735411122" /&gt;&lt;/a&gt;&lt;br /&gt;Pour ceux qui ne connaissent pas, ou qui sont moins obsédés: Olivier pensait à Girard qui classifie les 1&lt;sup&gt;er&lt;/sup&gt;, 2&lt;sup&gt;ème&lt;/sup&gt; et 3&lt;sup&gt;ème&lt;/sup&gt; sous-sols de la logique.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2339529904874251124?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2339529904874251124/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2339529904874251124' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2339529904874251124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2339529904874251124'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/03/blagues.html' title='Blagues'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_lAKV-lpQ4_s/R8-txybw8bI/AAAAAAAAABE/C8_6pVAQIn0/s72-c/133_73031.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5475757098716001967</id><published>2008-02-03T22:23:00.000+01:00</published><updated>2008-02-03T23:27:48.621+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>OCaml write-only</title><content type='html'>J'ai découvert un petit site sympa suite à une annonce sur la Caml-list: &lt;a href="http://golf.shinh.org/"&gt;Anarchy Golf&lt;/a&gt;. Au golf, on fini un parcours en un nombre minimum de coups. Ici, on résout un problème en un nombre minimum d'octets de code. De nombreux langages sont disponibles, dont OCaml.&lt;br /&gt;&lt;br /&gt;Le problème annoncé sur la Caml-list laisse rêveur: trouver un &lt;em&gt;Quine&lt;/em&gt; qui soit aussi un palindrome. En clair: un programme dont l'exécution affiche le code du programme, et dont le code est un palindrome, i.e. identique qu'on le lise de droite à gauche ou le contraire. Il est assez simple d'écrire un Quine, quel que soit le langage. J'ai écrit un palindrome en Caml, c'est déja un peu plus ardu. Mais satisfaire aux deux contraintes en même temps est décourageant. Alors j'ai perdu mon temps sur d'autres problèmes plus simples, en attendant de voir les solutions à celui-ci (le 08 Février, 01:46:39 heure japonaise).&lt;br /&gt;&lt;br /&gt;La contrainte de concision force à faire des choses illisibles. Par exemple, ma solution pour le problème &lt;a href="http://golf.shinh.org/p.rb?rot13"&gt;rot13&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;let rec(!)?(c=input_byte stdin)x=output_byte stdout[|c;c;65+c mod x;97+(c-6)mod x|].(c/32);!x;;!26&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&amp;Agrave; ce stade vient l'expression consacrée à Perl: ce code est &lt;em&gt;write-only&lt;/em&gt;. Et encore c'est assez lisible comparé aux solutions du champion de Golf en OCaml: &lt;code&gt;ksk&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;La concision force à faire des choses qu'on ne pourrait qualifier de bonnes pratiques de programmation. Cela dit, il faut en général réfléchir à un algorithme pas trop con pour pouvoir prétendre au podium. Par exemple, même en déployant toutes les ruses de compression possibles, je sentais bien que je n'atteindrais pas les 54 octets de &lt;code&gt;ksk&lt;/code&gt; pour écrire un &lt;a href="http://golf.shinh.org/p.rb?Minimal+scheme+interpreter"&gt;interpéteur Scheme minimal&lt;/a&gt;. Après la fin du défi, quand &lt;a href="http://golf.shinh.org/reveal.rb?Minimal+scheme+interpreter/ksk/1201104485&amp;ml"&gt;son code&lt;/a&gt; a été publié, j'ai pu constater qu'il avait rusé:&lt;br /&gt;&lt;pre&gt;print_string[|"3";"24";"5&lt;br /&gt;8&lt;br /&gt;58"|].(-Obj.magic(@)mod 3)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;De là à comprendre la ruse, ce n'est pas si simple. Tout repose sur le fait que le code ne doit pas vraiment implémenter un interpréteur Scheme: il suffit qu'il donne les bonnes réponses pour trois entrées différentes, toujours les mêmes. La plupart des participants ont utilisé cette "faille" pour répondre, par exemple &lt;code&gt;m.ukai&lt;/code&gt;, classé second en OCaml:&lt;br /&gt;&lt;pre&gt;print_string[|"24";"3";"5&lt;br /&gt;8&lt;br /&gt;58"|].(String.length(read_line())-16)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ici, la réponse est choisie en fonction de la longueur de la première ligne de l'entrée, cette information étant suffisante pour distinguer les tests. La solution de &lt;code&gt;ksk&lt;/code&gt; reste incompréhensible: il n'y a aucune instruction de lecture, aucun test dépendant de l'entrée. Pire: si vous prenez son code et le compilez (en natif ou &lt;em&gt;bytecode&lt;/em&gt;) vous obtiendrez un programme déterministe (il affiche toujours &lt;code&gt;3&lt;/code&gt; chez moi).&lt;br /&gt;&lt;br /&gt;La clé du mystère ? Exécuté dans la boucle d'interaction &lt;code&gt;ocaml&lt;/code&gt; comme le fait la procédure de vérification du Code Golf, ce code a une sortie aléatoire. Selon les exécutions de &lt;code&gt;ocaml ksk.ml&lt;/code&gt;, on reçoit la réponse de l'un des trois tests. Le hasard réside dans l'initialisation de la boucle d'interaction, qui fait que l'opérateur de concaténation &lt;code&gt;(@)&lt;/code&gt;, transtypé en un &lt;code&gt;int&lt;/code&gt; par &lt;code&gt;Obj.magic&lt;/code&gt; va avoir une valeur grosso-modo aléatoire. Je ne fais que constater, je ne comprends pas.&lt;br /&gt;&lt;br /&gt;Mais cela ne répond toujours pas au problème... enfin, pas toujours. Il aura probablement fallu à &lt;code&gt;ksk&lt;/code&gt; pas mal de patience pour soumettre et re-soumettre son code jusqu'à ce que le hasard renvoie les bonnes réponses aux bons tests, et le classe premier! Cette solution est vraiment &lt;em&gt;write-only&lt;/em&gt;: c'est illisible, et même son exécution laisse à désirer :)&lt;br /&gt;&lt;br /&gt;Moi je trouve ça un peu trop immoral, mais il faut avouer que ça respecte les règles du jeu. Et on aura appris quelquechose. C'est moche, mais ça marche.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5475757098716001967?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5475757098716001967/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5475757098716001967' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5475757098716001967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5475757098716001967'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2008/02/ocaml-write-only.html' title='OCaml write-only'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-332444556729647776</id><published>2007-12-10T11:50:00.000+01:00</published><updated>2007-12-10T12:03:03.803+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='programmation'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>De la webradio lambda à la λ-webradio</title><content type='html'>Un article sur quelques aspects théoriques de la conception de liquidsoap, par Samuel et moi-même, a été accepté aux Journées Francophones des Langages Applicatifs (&lt;a href="http://jfla.inria.fr/2008/"&gt;JFLA08&lt;/a&gt;). Sous un titre suivant la tradition blagueuse des JFLA (e.g., &lt;em&gt;Le foncteur sonne toujours deux fois&lt;/em&gt;) nous présentons le modèle de flux sur lequel sont construits les opérateurs de liquidsoap, puis formalisons le langage de script propre à notre outil. &amp;Ccedil;a nous change des articles purement techniques, et ça vous changera de la doc des outils de tous les jours: jetez-y donc &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/jfla08.pdf"&gt;un oeil&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-332444556729647776?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/332444556729647776/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=332444556729647776' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/332444556729647776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/332444556729647776'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/12/de-la-webradio-lambda-la.html' title='De la webradio lambda à la &amp;lambda;-webradio'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3959708926113718657</id><published>2007-11-22T23:00:00.000+01:00</published><updated>2008-01-14T18:24:33.990+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='voyage'/><category scheme='http://www.blogger.com/atom/ns#' term='velo'/><title type='text'>Vélo</title><content type='html'>Il y a trois ans, mon père m'a légué son vieux vélo de randonnée. J'ai eu envie de le faire retourner en Irlande, puis c'est en Bretagne et aux Pays-Bas que nous sommes partis en cyclotouristes avec Estelle. Malgré notre style très calme (grasses matinées, pauses café et autres douceurs) nous avons pu voir beaucoup de pays. C'est vraiment un chouette genre de vacances, un bon compromis entre la marche et la voiture.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/deuxpingouins/2053324580/in/set-72157603260226089/"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="http://farm3.static.flickr.com/2320/2053324580_1976b57b61.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;(Sur la photo, moi et le vélo en question, aux Pays-Bas. Au passage, j'ai publié quelques unes des photos de ce voyage &lt;a href="http://www.flickr.com/photos/deuxpingouins/sets/72157603260226089/"&gt;sur Flickr&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;En Septembre, un petit soucis technique sur ce vieux vélo m'a décidé à en acheter un nouveau. J'ai passé un bon moment à chercher un vélo qui pourrait le remplacer: léger, rapide, élégant, fonctionnel avec ses portes bagages. Je ne vais pas faire des tartines de ces considérations, de tout ce que j'ai lu et de mon choix final. Toujours est-il que j'ai un nouveau vélo pas mal du tout, que je commence à équiper pour la randonnée, et que ça m'a donné envie de tester le trajet de chez moi à l'&amp;Eacute;cole Polytechnique. La distance n'est pas négligeable, avec 20km depuis Montparnasse, mais le parcours presque tout en piste cyclable est très agréable. Plusieurs personnes font cette ballade pour aller au labo, et ils n'ont pas tous l'air de gros stakhanovistes: pourquoi pas moi/vous ?&lt;br /&gt;&lt;br /&gt;J'ai mis un petit moment à peaufiner mon trajet. La première fois fut avant les grèves, les deux suivantes pendant: ça tombe bien. Toujours est-il que maintenant que je connais bien la route, j'ai tracé le plan sur Google Maps. Les intéressés cliqueront sur l'image:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://maps.google.fr/maps/ms?ie=UTF8&amp;hl=fr&amp;t=k&amp;om=1&amp;msa=0&amp;msid=113143591456302335054.00043f61910a45be6068e&amp;ll=48.81229,2.298889&amp;spn=0.316523,0.583649&amp;z=10&amp;source=embed"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_lAKV-lpQ4_s/R4uZ9NVF-VI/AAAAAAAAAA8/jTNZPN0fSqU/s320/g.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155383475284867410" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pour finir, quelques liens que j'ai trouvé utiles dans mes recherches.&lt;br /&gt;&lt;br /&gt;D'abord les fabricants. Peu font encore de l'acier, pour des raisons économiques déplorables car ce matériau est plus souple donc plus solide, et permet l'utilisation de tubes extrêmement fins donc des vélos beaucoup plus élégants et tout aussi légers qu'en aluminium. &lt;a href="http://www.rivbike.com/"&gt;Rivendell&lt;/a&gt; fait des vélos en acier tout simplement sublimes, mais tellement chers! &lt;a href="http://www.surlybikes.com/"&gt;Surly&lt;/a&gt; est plus accessible et son Long Haul Trucker a la côte pour la randonnée, mais reste un gros investissement à mon échelle. Si l'on se résigne à l'aluminium, on découvre quand même de beaux vélos, et on s'aperçoit que Decathlon n'a pas forcément un rapport qualité/prix imbattable (par contre niveau visibilité ils écrasent tout le monde à Paris): par exemple les vélos &lt;a href="http://www.trekbikes.com/ca/fr/"&gt;Trek&lt;/a&gt; sont plutôt bien faits et pas aussi chers que le design du site ne le laisse croire. J'ai opté pour le &lt;a href="http://www.trekbikes.com/ca/fr/bikes/2008/bike_path/fx/73fx/"&gt;7.3FX&lt;/a&gt;, il n'est pas plus cher que le milieu/haut de gamme Decathlon et correspond mieux à ce que je voulais. Pis quand on le voit, on se dit qu'il vaut son prix :)&lt;br /&gt;&lt;br /&gt;Sinon pour la technique du vélo, des anecdotes et des conseil sur le matériel, de l'antique au plus moderne, &lt;a href="http://www.sheldonbrown.com/"&gt;Sheldon Brown&lt;/a&gt; (en anglais) est super bon.&lt;br /&gt;&lt;br /&gt;Enfin, n'oublions pas qu'on roule pour voyager. Niveau matériel, deux marques sont omniprésentes: Tubus pour les porte-bagages et Ortlieb pour les sacoches. Le matos est bien foutu (en en voyant aux Pays-Bas j'avais déja commencé à penser à me re-équiper) mais putain qu'est-ce que c'est cher.  On pourra admirer des vélos voyageurs bien chargés dans la galerie &lt;a href="http://www.pbase.com/canyonlands/fullyloaded"&gt;Fully Loaded Bicycle&lt;/a&gt;, du pliant au tandem. Enfin vraiment sur le voyage, le site &lt;a href="http://www.crazyguyonabike.com/"&gt;Crazy Guy on a Bike&lt;/a&gt; recense des récits de voyages à vélo (du court au très long) ainsi que de nombreux conseils. Comme très long voyage balisé, la &lt;a href="http://www.eurovelo6.org/"&gt;route EuroVelo6&lt;/a&gt; s'illustre avec 4000km de St Nazaire à la Mer Noire par la Loire, le Rhin et le Danube.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3959708926113718657?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3959708926113718657/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3959708926113718657' title='5 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3959708926113718657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3959708926113718657'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/11/vlo.html' title='Vélo'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2320/2053324580_1976b57b61_t.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5226956284706444364</id><published>2007-11-21T15:33:00.001+01:00</published><updated>2008-07-03T15:30:18.187+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><title type='text'>Enigmes</title><content type='html'>Quand on pose une énigme mathématique, à moitié formalisée, on finit toujours par avoir une réponse type: "on enlève le bandeau qu'on a sur les yeux", "on casse la gueule au bourreau", etc. D'où l'idée de formaliser vraiment, sous forme d'un exercice de programmation... (qui a dit "maniaque" ?)&lt;br /&gt;&lt;br /&gt;Un groupe de &lt;code&gt;n&lt;/code&gt; prisonniers se trouve en mauvaise posture. Ils vont être mis en file indienne, chaque prisonnier voyant seulement les prisonniers devant lui. Puis on leur mettra sur la tête un chapeau bleu, blanc ou rouge, qu'ils ne peuvent voir. Un bourreau procède alors comme suit: en partant du dernier prisonnier il demande "Quelle est la couleur de ton chapeau ?", et le prisonnier n'a le droit qu'à une réponse, qui doit être une couleur. A la fin, les prisonniers qui ont deviné la couleur de leur chapeau sont épargnés, les autres exécutés. Les prisonniers peuvent se concerter avant l'épreuve sur la stratégie à adopter. Quelle est la meilleure stratégie ?&lt;br /&gt;&lt;br /&gt;Voici maintenant l'énoncé complètement formalisé. Un prisonnier est représenté par une fonction qui prend deux listes de couleurs (celles qu'il voit devant lui, celles qui ont été prononcées comme réponses derrière lui), et renvoie une couleur (sa réponse). Dans la liste des réponses précédentes, la réponse du dernier de la file est la dernière de la liste. Trouver une fonction &lt;code&gt;prisonniers&lt;/code&gt; qui à un entier &lt;code&gt;n&lt;/code&gt; associe une liste de &lt;code&gt;n&lt;/code&gt; fonctions/prisonniers telle que le nombre de morts calculé par &lt;code&gt;(execution (prisonniers n))&lt;/code&gt; soit le plus petit possible dans le pire cas. La fonction d'exécution est la suivante:&lt;br /&gt;&lt;pre&gt;type couleur = Bleu | Blanc | Rouge&lt;br /&gt;type prisonnier = couleur list -&amp;gt; couleur list -&amp;gt; couleur&lt;br /&gt;&lt;br /&gt;let random_couleur () =&lt;br /&gt;  let n = Random.int 3 in&lt;br /&gt;    if n = 0 then Bleu else if n = 1 then Blanc else Rouge&lt;br /&gt;&lt;br /&gt;let execution (prisonniers : prisonnier list) =&lt;br /&gt;  let prisonniers =&lt;br /&gt;    List.map (fun p -&amp;gt; p, random_couleur ()) prisonniers&lt;br /&gt;  in&lt;br /&gt;  let rec morts avant = function&lt;br /&gt;    | (p,c)::l -&amp;gt;&lt;br /&gt;        let reponse = p (List.map snd l) avant in&lt;br /&gt;          (if reponse = c then 0 else 1) +&lt;br /&gt;          (morts (reponse::avant) l)&lt;br /&gt;    | [] -&amp;gt; 0&lt;br /&gt;  in&lt;br /&gt;    morts [] prisonniers&lt;/pre&gt;&lt;br /&gt;Amusez-vous bien, et postez vos réponses dans le langage de votre choix...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit&lt;/b&gt;: une autre énigme beaucoup plus étonnante, que Florent et Julien m'ont racontée. Vous avez devant vous sur une table 7 pièces côté pile et 19 pièces côté face. Mais vos yeux sont bandés (et vous portez des moufles) de sorte que vous ne pouvez savoir l'état d'une pièce. Tout ce que vous pouvez faire c'est en retourner certaines, autant que vous voulez, et les déplacer. Il vous faut les séparer en deux groupes qui contiennent le même nombre de pièces côté pile.&lt;br /&gt;&lt;br /&gt;La solution sera une fonction qui prend le nombre de piles et le nombre de faces (je vous aide bien en généralisant) et qui renvoie deux tableaux de taille &lt;code&gt;piles+faces&lt;/code&gt;: le premier indique les indices des pièces choisies, le second indique les pièces qu'il faut retourner. La fonction sera passée à la fonction de test suivantes:&lt;br /&gt;&lt;pre&gt;(** Perfect Fisher-Yates shuffle&lt;br /&gt;  * (http://www.nist.gov/dads/HTML/fisherYatesShuffle.html). *)&lt;br /&gt;let randomize a =&lt;br /&gt;  let permute i j =&lt;br /&gt;    let tmp = a.(i) in&lt;br /&gt;      a.(i) &amp;lt;- a.(j);&lt;br /&gt;      a.(j) &amp;lt;- tmp&lt;br /&gt;  in&lt;br /&gt;  let l = Array.length a in&lt;br /&gt;    if l&amp;gt;=2 then&lt;br /&gt;      for i=0 to l-2 do&lt;br /&gt;        permute i (i + Random.int (l-i))&lt;br /&gt;      done&lt;br /&gt;&lt;br /&gt;let test nb_piles nb_faces joueur =&lt;br /&gt;  let choix,retourne = joueur nb_piles nb_faces in&lt;br /&gt;  let n = nb_piles + nb_faces in&lt;br /&gt;  let a = Array.init n (fun i -&amp;gt; i&amp;lt;nb_piles) in&lt;br /&gt;  (* Nombre de piles à gauche - nombre de piles à droite *)&lt;br /&gt;  let d = ref 0 in&lt;br /&gt;    randomize a ;&lt;br /&gt;    for i = 0 to n-1 do&lt;br /&gt;      if retourne.(i) then a.(i) &amp;lt;- not a.(i) ;&lt;br /&gt;      d := (if choix.(i) then (+) else (-)) !d (if a.(i) then 1 else 0)&lt;br /&gt;    done ;&lt;br /&gt;    !d = 0&lt;/pre&gt;&lt;br /&gt;A suivre: les solutions commentées...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5226956284706444364?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5226956284706444364/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5226956284706444364' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5226956284706444364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5226956284706444364'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/11/enigme.html' title='Enigmes'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3879333588674241381</id><published>2007-09-08T02:47:00.000+02:00</published><updated>2007-11-09T10:39:44.844+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='savonet'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><title type='text'>Linux Mag</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_lAKV-lpQ4_s/RuHxZnGGPYI/AAAAAAAAAA0/1Sn2y6Ghujk/s1600-h/damag-000001.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_lAKV-lpQ4_s/RuHxZnGGPYI/AAAAAAAAAA0/1Sn2y6Ghujk/s400/damag-000001.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5107628874708434306" /&gt;&lt;/a&gt;&lt;br /&gt;Bravo à Romain qui est sur la couverture de Linux Magazine ce mois-ci, avec un article sur l'équipe Savonet qui développe un machin appelé Liquidsoap... la suite dans le numéro de Novembre!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3879333588674241381?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3879333588674241381/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3879333588674241381' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3879333588674241381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3879333588674241381'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/09/linux-mag.html' title='Linux Mag'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_lAKV-lpQ4_s/RuHxZnGGPYI/AAAAAAAAAA0/1Sn2y6Ghujk/s72-c/damag-000001.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-914275524195288156</id><published>2007-08-24T02:22:00.000+02:00</published><updated>2007-08-26T03:22:10.590+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philo'/><category scheme='http://www.blogger.com/atom/ns#' term='réalité'/><category scheme='http://www.blogger.com/atom/ns#' term='logique'/><title type='text'>Lectures estivales</title><content type='html'>Je suis de retour à Paris, après deux semaines à découvrir les Pays-Bas (un pays de hoef) en roulant (à vélo), puis quelques jours de camping dans les Alpes, séjour écourté par la pluie... Je pointerai plus tard des galeries de photos, pour l'instant j'avais envie de coucher quelques notes sur les bouquins sur lesquels je suis tombé, et qui m'ont permis de structurer un peu certaines &lt;a href="http://misterpingouin.blogspot.com/2007/02/meta-moutons.html"&gt;fascinations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Matière à pensée&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Cela commence avec un ancien prof de philo à la retraite, qui me conseille ce dialogue entre Alain Connes (mathématicien) et Jean-Pierre Changeux (neurobiologiste) pour nourrir "légèrement" ma curiosité en épistémologie.&lt;br /&gt;&lt;br /&gt;La première partie du bouquin m'a plu, et en particulier la forme du dialogue, où les idées ne sont pas posées en absolus mais réellement discutées. La question initiale est celle du statut des mathématiques.&lt;br /&gt;&lt;br /&gt;Pour Connes les mathématiques constituent une réalité, autre que notre réalité physique, que les mathématiciens explorent, et qui a un caractère universel. Changeux voit plutôt les mathématiques comme un pur produit de l'esprit humain, qui n'aurait pas forcément de sens pour un être inhumain. Bizarrement, Connes admet ouvertement que sa vision plutôt absolue n'est qu'une croyance, alors que Changeux, malgré ses idées très relatives/subjectives, semble penser qu'on peut aller au delà de la croyance en ce domaine.&lt;br /&gt;&lt;br /&gt;Deux concepts importants restent indéfinis. D'abord les &lt;em&gt;mathématiques&lt;/em&gt;: y a-t-il une seule mathématique ? En tant qu'apprenti logicien je ne peux m'empêcher de penser aux multiples logiques et théories existantes. Comment concevoir une unique "réalité" malgré la possibilité de travailler avec l'hypothèse du continu ou son contraire ? Les énoncés indépendants sont abordés mais la question n'est pas traitée. Plus amusant, la définition de &lt;em&gt;réalité&lt;/em&gt; reste en suspens. Pour Connes il y a une "réalité" mathématique car il y a une &lt;em&gt;cohérence de la perception (des objets mathématiques), pour un même individu et d'un individu à l'autre&lt;/em&gt;. Pour lui c'est là la définition même de réalité. Changeux objecte alors qu'avec cette définition les hallucinations collectives font partie de la réalité, mais ne propose pas mieux. Et je retombe dans mes considérations Dickiennes...&lt;br /&gt;&lt;br /&gt;La seconde partie du bouquin parle du théorème de Gödel, d'intelligence artificielle, de la dissection puis de la mécanisation de l'activité du mathématicien... Cela devient un peu mou et on n'y lit rien de bien excitant ni même nouveau.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Interlude: Le Monde Diplomatique&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Cela faisait bien longtemps que je n'avais pas acheté le Monde Diplo, qui me semblait rabâcher les mêmes considérations déprimantes. Le numéro d'Août m'a fait changer d'avis: quasiment tous les articles m'ont semblé intéressants, qu'on y apprenne ou qu'on y trouve une structuration. En particulier Estelle et moi avons été séduits par Chomsky. Quelques uns de ses bouquins nous ont ainsi accompagnés dans les Alpes, mais je dois avouer que je ne m'y suis pas mis.&lt;br /&gt;&lt;br /&gt;Juste un petit mot pour &lt;a href="http://gelnior.free.fr/dotclear/index.php/2007/08/19/137-dezone"&gt;Gelnior&lt;/a&gt; qui a aussi lu cet été sur les vices "cachés" de notre société "parfaite": toi aussi lis Chomsky tu verras que cela ne s'arrête pas au mode de vie d'un individu et à son choix d'être lisse ou d'insulter les gens.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Le point aveugle&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Sous la pluie dans les Alpes, je lisais le premier tome du récent cours de logique de Girard -- j'en avais besoin pour un point technique. Le bouquin couvre bien le sujet des bases aux notions avancées, mais je ne suis pas sûr qu'il faille le conseiller aux débutants pour autant. Par contre c'est un plaisir à lire quand on a déja une vague idée de la totalité du sujet, on apprécie les remarques reliant un concept à un autre, donnant plus de profondeur qu'une présentation académique linéaire. Et il faut admettre qu'on se régale des jugements acérés sur telle idée ou tel mathématicien/logicien -- même si cela semble parfois superflu pour ces derniers. Par contre ça doit être agaçant quand on n'adhère pas aux mêmes idées que Girard...&lt;br /&gt;&lt;br /&gt;Si j'en parle ici, c'est qu'en fait le livre m'a fait retomber (presque) par hasard dans les considérations précédentes. Témoin le quatrième de couverture: "Epistémologiquement, le texte rompt avec la sempiternelle polarisation entre réalisme et anti-réalisme, en lui substituant l'opposition entre &lt;em&gt;existence&lt;/em&gt; et &lt;em&gt;essence&lt;/em&gt;. [...] La logique est-elle antérieure aux phénomènes qu'elle contrôle ?"&lt;br /&gt;&lt;br /&gt;En deux mots. Girard évacue la question de la réalité en arguant de ce que tout bon scientifique croit d'une certaine façon en ce qu'il fait. Il se pose une question plus productive: comment fonder la logique en évitant la fuite en avant &lt;em&gt;essentialiste&lt;/em&gt; qui va justifier un système par un meta-système, lui même fondé sur un meta-meta-... etc ? Dans le cas de la logique, comment définir la vérité sans faire référence à une notion pré-établie ? Girard reconnait en fait l'impossibilité de cet objectif, affirmant que "la vérité n'a pas de sens". Mais cet aveu est productif, puisqu'il va alors s'intéresser à la cohérence &lt;em&gt;interne&lt;/em&gt; des logiques, l'élimination des coupures par exemple.&lt;br /&gt;&lt;br /&gt;En fait, je ne suis pas sûr que Girard &lt;em&gt;croie&lt;/em&gt; que la vérité n'a pas de sens. C'est plutôt un programme qu'il propose, et qui mène à de très beaux travaux. De même, je ne &lt;em&gt;crois&lt;/em&gt; pas à l'idée de réalité consensuelle, mais je trouve que c'est une éventualité des plus amusantes à envisager.&lt;br /&gt;&lt;br /&gt;Je n'ai pas encore acheté le second tome du cours, et je ne sais pas quand je trouverai la force de le lire. Mais je sais déja que, du point de vue de la métaphysique de comptoir, ça va continuer à me plaire. Girard y parle de ludique, une nouvelle vision de la logique où tout commence par une notion de jeux &lt;em&gt;sans arbitre&lt;/em&gt;, qui se déroulent par consensus entre les deux joueurs. Plus d'absolu pré-établi, tout est subjectif... comme la réalité ?&lt;br /&gt;&lt;br /&gt;Et puisqu'on parle de jeux (théoriques), je finirai de nouveau en évoquant mes projets fous de (vrais) jeux qui implémentent fortement cette idée de &lt;a href="http://en.wikipedia.org/wiki/Consensus_reality"&gt;réalité consensuelle&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Modestement, on peut d'abord partir de l'idée qu'il ne doit pas y avoir d'arbitre, par exemple dans le cadre d'un jeu de stratégie en temps réel. Typiquement, un joueur n'a qu'une information partielle sur l'état des unités de l'autre joueur, e.g. à cause du brouillard de guerre. Au fur et à mesure qu'il acquiert de l'information, le joueur peut vérifier que son opposant n'a pas triché (s'il existe une stratégie qui mène à un état cohérent avec l'information découverte). En l'absence d'arbitre omnipotent, on ne peut pas faire mieux. Du coup, il y a au moins deux façons de jouer. Soit on joue comme d'habitude, en suivant une seule stratégie. Soit on joue au second degré, en ne décidant de sa stratégie qu'au fur et à mesure que l'opposant nous observe -- ce qui implique des choix dans le passé, du point de vue de l'opposant. Clairement, cela offre plus de possibilités puisqu'on attend, avant de faire un choix, d'avoir de l'information par l'observation mutuelle. Mais déja, on a du mal à imaginer l'interface qui rendrait cela praticable pour un joueur humain. Pire, on se demande s'il y a une troisième degré de jeu.&lt;br /&gt;&lt;br /&gt;Mais franchement, ce projet là me parait terne par rapport à la richesse de l'idée. Moi ce que je veux, c'est un monde où la réalité serait malléable, où les joueurs habiles se feraient magiciens en imposant leur vision du réel, où peut-être les réalités se feraient multiples en cas de conflit.&lt;br /&gt;&lt;br /&gt;Et puisqu'on est dans le doute, je finirai avec une citation de Dick qui va un peu contre cette idée de consensus.&lt;br /&gt;&lt;blockquote&gt;« La réalité, c'est ce qui continue à s'imposer de vous quand vous cessez d'y croire. » -- P.K.Dick&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-914275524195288156?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/914275524195288156/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=914275524195288156' title='15 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/914275524195288156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/914275524195288156'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/08/lectures-estivales.html' title='Lectures estivales'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8490542814998528306</id><published>2007-08-05T11:04:00.000+02:00</published><updated>2007-08-05T11:16:40.346+02:00</updated><title type='text'>Petite pierre</title><content type='html'>Merci à Romain pour l'&lt;a href="http://debaday.debian.net/2007/08/05/liquidsoap-a-versatile-icecast-source-client-and-much-more/"&gt;article Deb-a-Day&lt;/a&gt; sur liquidsoap!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8490542814998528306?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8490542814998528306/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8490542814998528306' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8490542814998528306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8490542814998528306'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/08/petite-pierre.html' title='Petite pierre'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-595721023246982866</id><published>2007-07-31T16:22:00.001+02:00</published><updated>2007-08-26T03:22:45.833+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='hack'/><title type='text'>Notification de bonnes vacances</title><content type='html'>Aujourd'hui est mon dernier jour au labo pour cette deuxième année de thèse. Je vais limite avoir du mal à arrêter de bosser, avec toutes ces questions excitantes qui tournent encore dans ma tête, tous ces trucs à écrire. Pour m'aider à décrocher (hum..) j'ai décidé de passer la journée à coder dans liquidsoap, en me concentrant sur deux-trois trucs chiants et pas du tout glorieux, qui ont trait à l'auto-documentation des fonctions définies dans les scripts liq. Cela devient important à mesure que nous accumulons de petites snippets sympas.&lt;br /&gt;&lt;br /&gt;Par exemple, j'utilise liquidsoap pour écouter ma musique, et pour écouter Dolebraï (sur laquelle je mixe les interventions de balbinus sur sa &lt;em&gt;number station&lt;/em&gt;). Dans les deux cas j'utilise deux petites fonctions pratiques: je parlerai plus tard de la platine interactive qui permet d'appliquer quelques effets audio, quand elle sera finalisée; l'autre fonctionnalité est un petit hack pour afficher à l'écran les metadonnées du flux joué par liquidsoap.&lt;br /&gt;&lt;br /&gt;Le principe est simple: attacher à l'évenement &lt;em&gt;on_metadata&lt;/em&gt; une fonction qui exécute la bonne commande. Quelle que soit la méthode, il va tout d'abord nous falloir une fonction pour transformer la métadonnée en chaine de caractères.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Standard function for displaying metadata.&lt;br /&gt;# Uses "Unknown" when a field is empty.&lt;br /&gt;# @param m Metadata packet to be displayed.&lt;br /&gt;def display_metadata(m)&lt;br /&gt;  artist = m["artist"]&lt;br /&gt;  title  = m["title"]&lt;br /&gt;  artist = if ""==artist then "Unknown" else artist end&lt;br /&gt;  title  = if ""==title  then "Unknown" else title  end&lt;br /&gt;  "#{artist} -- #{title}"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;OSD (On Screen Display)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;OSD est une technologie ancestrale de X. On peut l'utiliser simplement avec l'utilitaire &lt;code&gt;osd_cat&lt;/code&gt; qui affiche à l'écran (au dessus de toutes les fenêtres) le texte passé sur son entrée standard. Le problème est que les polices ne sont pas lissées, et qu'il est difficile de trouver une couleur de texte lisible quel que soit le fond au moment de l'affichage. Néanmoins, c'est un début..&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Use X On Screen Display to display metadata info.&lt;br /&gt;# @param ~color    Color of the text.&lt;br /&gt;# @param ~position Position of the text (top|middle|bottom).&lt;br /&gt;# @param ~font     Font used (xfontsel is your friend...)&lt;br /&gt;# @param ~display  Function used to display a metadata packet.&lt;br /&gt;def osd(~color="green",~position="top",&lt;br /&gt;        ~font="-*-courier-*-r-*-*-*-240-*-*-*-*-*-*",&lt;br /&gt;        ~display=display_metadata,&lt;br /&gt;        s)&lt;br /&gt;  osd = 'osd_cat -p #{position} --font #{quote(font)}'&lt;br /&gt;      ^ ' --color #{color}'&lt;br /&gt;  def feedback(m)&lt;br /&gt;    system("echo #{quote(display(m))} | #{osd} &amp;")&lt;br /&gt;  end&lt;br /&gt;  on_metadata(feedback,s)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Notify&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Notify est une technologie plus moderne émanant de l'intiative freedesktop. Elle est donc disponible avec les gestionnaires de bureau principaux, notamment gnome, kde et xfce. Si ça se trouve on peut même l'utiliser indépendamment du gestionnaire de bureau, mais l'idée ici est que l'intégration permet un comportement plus riche et agréable, ainsi qu'une apparence unifiée. Bref. Encore une fois on a un petit outil simple en ligne de commande: &lt;code&gt;notify-send&lt;/code&gt;. Et ce n'est pas plus compliqué à utiliser depuis liquidsoap:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Use notify to display metadata info.&lt;br /&gt;# @param ~urgency Urgency (low|normal|critical).&lt;br /&gt;# @param ~icon    Icon filename or stock icon to display.&lt;br /&gt;# @param ~time    Timeout in milliseconds.&lt;br /&gt;# @param ~display Function used to display a metadata packet.&lt;br /&gt;# @param ~title   Title of the notification message.&lt;br /&gt;def notify(~urgency="low",~icon="stock_smiley-22",~time=3000,&lt;br /&gt;           ~display=display_metadata,&lt;br /&gt;           ~title="Liquidsoap: new track",s)&lt;br /&gt;  send = 'notify-send -i #{icon} -u #{urgency}'&lt;br /&gt;       ^ ' -t #{time} #{quote(title)} '&lt;br /&gt;  on_metadata(fun (m) -&gt; system(send^quote(display(m))),s)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Tout ceci se teste assez simplement. Par exemple, pour faire simple, mettez mes petites fonctions dans un script, ajoutez en dernière ligne un &lt;code&gt;out(notify(playlist("~/ma/musique")))&lt;/code&gt; et c'est parti. Sous Debian les paquets nécessaires sont (&lt;code&gt;liquidsoap&lt;/code&gt; et) respectivement &lt;code&gt;xosd-bin&lt;/code&gt; et &lt;code&gt;libnotify-bin&lt;/code&gt;. Un petit instantané du résultat chez moi:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_lAKV-lpQ4_s/Rq9JYZDVn6I/AAAAAAAAAAs/LIL2Mocnmfc/s1600-h/screen.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_lAKV-lpQ4_s/Rq9JYZDVn6I/AAAAAAAAAAs/LIL2Mocnmfc/s400/screen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5093370386969894818" /&gt;&lt;/a&gt;&lt;br /&gt;Et bonnes vacances!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-595721023246982866?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/595721023246982866/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=595721023246982866' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/595721023246982866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/595721023246982866'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/07/notification-de-bonnes-vacances.html' title='Notification de bonnes vacances'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_lAKV-lpQ4_s/Rq9JYZDVn6I/AAAAAAAAAAs/LIL2Mocnmfc/s72-c/screen.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-4783934449209063305</id><published>2007-07-24T15:02:00.000+02:00</published><updated>2007-08-28T20:48:36.115+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mylife'/><category scheme='http://www.blogger.com/atom/ns#' term='open-source'/><category scheme='http://www.blogger.com/atom/ns#' term='savonet'/><title type='text'>Intello - nombriliste - hippie - réactionnaire</title><content type='html'>Depuis déja une semaine je suis de retour d'Allemagne, où je présentais le système que j'ai développé en première année. J'ai surtout pas mal bossé à tous ces exposés que je ne suivais pas, et je suis rentré avec plein d'idées à pousser, c'est assez excitant. J'ai appris ce matin que l'article résultant en gros de mon travail de cette année a été accepté à &lt;a href="http://www.lpar.net/2007/"&gt;LPAR&lt;/a&gt;. Ce travail me tenait assez à coeur, et le suspens était d'autant plus grand que l'article a d'abord été refusé ailleurs dans des conditions assez frustrantes... En tout cas, j'irai en Arménie en Octobre.&lt;br /&gt;&lt;br /&gt;Voilà pour le côté recherche, bien rempli. Côté &lt;a href="http://savonet.sf.net"&gt;Savonet&lt;/a&gt;, Sam Balbinus et Romain ont l'air de se sentir plus franchement en vacances que moi, et passent pas mal de temps sur le projet, ce qui m'y pousse forcément. On commence à étendre les possibilités d'interaction: à terme on n'aura plus besoin de régler les opérateurs de traitement de son à l'aveugle; ça devrait aussi aider à débuguer des trucs complexes comme la détection de beat; plus marrant, on peut imaginer utiliser liquidsoap comme un backend d'un logiciel de DJ. J'ai forcément été de la partie, pour le bricolage dans les coins sombres de liquidsoap, et puis parce que ça m'amuse bien tout simplement. Mais je n'ai clairement pas été à la hauteur de la frénésie de Sam. Pour sa part, Romain a rédigé un article pour &lt;a href="http://debaday.debian.net"&gt;DebADay&lt;/a&gt;, auquel j'ai contribué un peu, mais pas aussi vite qu'il ne l'espérait. Dans le même temps il préparait un dossier pour les &lt;a href="http://www.tropheesdulibre.org"&gt;Trophées du Libre&lt;/a&gt;. Et il a pour la troisième fois demandé au projet Icecast de lister liquidsoap parmi &lt;a href="http://icecast.org/3rdparty.php"&gt;les streamers compatibles&lt;/a&gt;, avec succès! Notre longue absence me fait bien sentir que la liste est loin d'être exhaustive. N'empêche, c'est une liste de choix, et liquidsoap y sort clairement du lot, ça fait plaisir.&lt;br /&gt;&lt;br /&gt;Plus que ma très passagère et très relative baisse d'activité de développement, mon manque d'intérêt pour la communication m'a fait me poser des questions, et nous en avons d'ailleurs un peu discuté avec Romain. Ma première réaction a été de me justifier dans l'absolu. Ce qui m'intéresse, ce n'est pas de maintenir un monument, d'assurer le support utilisateur, la portabilité et la &lt;em&gt;backward-compatibility&lt;/em&gt;... toutes ces choses, certes très importantes, ne m'excitent pas.  Et ce projet est d'abord et avant tout un hobby, je ne veux pas me laisser entraîner dans une direction qui ne me plait pas. Mais qu'est-ce qui me plait? Ce n'est pas très raisonnable, mais je crois qu'il faut avouer que c'est d'abord "coder". J'aime coder, de l'élégance des petites fonctions à la satisfaction de la maitrise de l'ensemble complexe de modules que forme liquidsoap. Sinon, plus généralement, "développer" une idée qui permette d'atteindre un résultat original, de dépasser les limites actuelles.&lt;br /&gt;&lt;br /&gt;En fait, tout est dans la portée du "développement". &amp;Ccedil;a me fait penser à Philip. K. Dick qui présente, en préface du recueil de ses nouvelles, sa vision de la différence entre nouvelle et roman. La nouvelle lui permet de mettre en scène une idée: on pose le décor, les personnages, dans l'unique but de présenter l'idée principale. Dans un roman, les personnages et l'environnement en général doivent être développés plus en profondeur, ils doivent prendre vie, avoir leur caractère. Selon Dick, l'auteur se retrouve du coup prisonnier de ses personnages, dont la vie propre force l'action. Les deux styles ont leurs avantages et inconvénients. Chacun son truc. Quant à Dick, il a écrit les deux. J'ai bien aimé ses romans, mais je dois dire que je suis soufflé quand je lis ses nouvelles: quasimment chaque histoire met en scène une idée étonnante, déroutante, fascinante! Je parle de Dick plus parce que j'adore le lire que parce que j'aime l'analogie, mais vous l'aurez compris, je me vois plutôt écrire des "nouvelles" que des "romans". L'autre tendance me semble glauque au possible: je pense aux armées de développeurs dans l'industrie, qui implémentent des suites bureautiques, de mornes projiciels ou autres automatisations de tâches administratives... En un sens ils peuvent être fiers de faire tourner le monde. Mais bon, comme dit Alan J. Perlis: &lt;em&gt;In computing, turning the obvious into the useful is a living definition of the word "frustration".&lt;/em&gt; (&lt;span style="font-size:smaller"&gt;Perlis a écrit un paquet d'&lt;em&gt;Epigrams on Programming&lt;/em&gt;, c'est une &lt;a href="http://www-pu.informatik.uni-tuebingen.de/users/klaeren/epigrams.html"&gt;lecture amusante&lt;/a&gt;, et on finit toujours par y lire midi à sa porte.&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;Bien entendu, peu de choses étant simples dans la vraie vie, je me suis vite rendu compte que ces réflexions ne sont pas honnêtes. Du moins, elles ne représentent qu'une facette de la réalité. J'ai la tête très occupée par la recherche en ce moment, mais ces choses là fluctuent. Je suis clairement touché quand un utilisateur apprécie liquidsoap, quand Xavier Cazin blogue là dessus chez O'Reilly, etc. Il y a là bien sûr un brin d'orgueil. Plus louablement, je crois qu'un des buts de liquidsoap est de montrer comment des courants d'idées actuellement plutôt enfermés dans le milieu de la recherche peuvent être utiles à tout le monde, développeurs comme utilisateurs. Le fait que le projet marche, et qu'il soit apprécié, et qu'il ait même rallié un brin de contributeurs, constitue un début de succès de ce point de vue... ce n'est peut-être pas tout à fait de la pédagogie ni du militantisme, mais il y a un peu de ça.&lt;br /&gt;&lt;br /&gt;Le problème des concours de logiciels libres cristallise bien ces questions. J'ai probablement été le premier à envisager de présenter liquidsoap à tel ou tel concours. J'ai toujours repoussé à une prochaine-version-encore-mieux. Sam a poussé et c'est finalement Romain qui a fait le pas. Le bon côté de la chose c'est qu'on risque d'entrer en contact avec de nouveaux gens intéressants, et probablement tomber sur de nouvelles idées. Le domaine est plutôt petit et on s'adresse à des gens plutôt capables techniquement, nous sommes probablement déja suffisamment référencés pour que les utilisateurs ciblés nous trouvent. Mais peut-être un peu de communication plus large nous fera-t-elle atteindre des applications et des gens auxquels nous ne pensons pas actuellement, et réciproquement. Ces pensées positives ne chassent pas l'idée du côté bizarre de tout ça. Pourquoi concourir à un prix, en euros et en matériel ? On se retrouve à lire dans le topic de &lt;code&gt;#savonet&lt;/code&gt;: "TODO: Find what to do with money for the project"! Pour caricaturer, on part d'un projet pour le fun et les belles idées, et on arrive à se demander comment dépenser du blé, en vulgaires consommateurs. &amp;Ccedil;a m'évoque aussi les grosses compagnies qui n'ont que l'objectif d'être les "premières", oubliant complètement l'interêt du client et de la société. Pas de méprise, ces &lt;em&gt;exagérations&lt;/em&gt; ne sont que les spectres &lt;em&gt;caricaturaux&lt;/em&gt; d'un doute qui me taraude. Mais je crois qu'il est très important de faire gaffe à ne pas dévier par mégarde des objectifs qu'on se fixe. Pour ne pas se réveiller un jour et réaliser qu'on a perdu du temps et de l'énergie (ou pire) à des choses qui ne nous intéressent pas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4783934449209063305?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4783934449209063305/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4783934449209063305' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4783934449209063305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4783934449209063305'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/07/intello-nombriliste-hippie-ractionnaire.html' title='Intello - nombriliste - hippie - réactionnaire'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8257004266970133516</id><published>2007-07-18T12:21:00.000+02:00</published><updated>2007-08-26T03:21:54.967+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocaml'/><category scheme='http://www.blogger.com/atom/ns#' term='conf'/><category scheme='http://www.blogger.com/atom/ns#' term='voyage'/><category scheme='http://www.blogger.com/atom/ns#' term='programmation'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Application</title><content type='html'>Je suis en conférence, ce qui me laisse plein de temps pour bosser pendant la plupart des exposés... Bremen est plutôt une jolie ville, le campus est super agréable et il fait beau. Blogger s'est mis à me parler en Allemand. Ici j'ai vu Al. Bundy, pour ceux qui connaissent...&lt;br /&gt;&lt;br /&gt;Bon sinon, un petit exemple simple m'est venu pour montrer que l'application en Caml n'est pas aussi simple qu'on le pense en présence d'arguments optionels. L'équation &lt;code&gt;f x y&lt;/code&gt; = &lt;code&gt;(f x) y&lt;/code&gt;, n'est pas toujours vérifiée. En fait, on n'a pas seulement une notion d'application mais bien une multi-application. Si je parle de ça c'est pour mettre au clair l'origine de la multi-abstraction du langage de script de liquidsoap.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# let f ?(a=false) () = a ;;&lt;br /&gt;val f : ?a:bool -&amp;gt; unit -&amp;gt; bool = &lt;fun&gt;&lt;br /&gt;# f () ~a:true ;;&lt;br /&gt;- : bool = true&lt;br /&gt;# (f ()) ~a:true ;;&lt;br /&gt;This expression is not a function, it cannot be applied&lt;br /&gt;# f () ;;&lt;br /&gt;- : bool = false&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8257004266970133516?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8257004266970133516/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8257004266970133516' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8257004266970133516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8257004266970133516'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/07/application.html' title='Application'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-678562935142769105</id><published>2007-07-15T11:49:00.000+02:00</published><updated>2007-07-16T09:09:06.772+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='radio'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>Scoop</title><content type='html'>Sam et Balbinus ont frénétiquement commencé un nouveau sous-projet au sein de Savonet: SoapLab! Il s'agit d'une application Gtk à deux facettes. D'abord un &lt;em&gt;ingester&lt;/em&gt;, premier maillon du futur système &lt;a href="http://savonet.sourceforge.net/wiki/IntegratedAutomationSystem"&gt;IAS&lt;/a&gt; cher à Balbinus: il permet de rapidement examiner un fichier de sa playlist, et d'éditer ses caractéristiques, notamment les points de fade-in/fade-out/crossing. Tout cela bien sûr sur n'importe quelle machine, pas forcément sur le serveur de la radio. Soaplab est aussi un éditeur audio, qui importe/affiche/joue/modifie/exporte une onde sonore. Plutôt classique, mais de bonne facture et surtout, re-utilisant tout le matériel développé dans liquidsoap. Je m'en sers notamment pour inspecter la sortie d'une source liquidsoap.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;soaplab --editor '&lt;br /&gt;s = sine(duration=5.)&lt;br /&gt;s = fade.in(duration=2.,type="sin",s)&lt;br /&gt;s = fade.out(duration=2.,type="sin",s)&lt;br /&gt;sequence(merge=true,[s,s,s,s,fallback([])])'&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvWmGl-BI/AAAAAAAAAAM/qz1_Zk7zYsQ/s1600-h/sin.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvWmGl-BI/AAAAAAAAAAM/qz1_Zk7zYsQ/s320/sin.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087360425556047890" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On voit ici quatres pistes de la source &lt;code&gt;s&lt;/code&gt;, qui émet des pistes de 5 secondes, sinusoïdales à 440Hz, sur laquelle on a rajouté du fading in et out, de type "sinusoïdal". Les autres types dispos sont dans l'ordre: exponentiel, logarithmique et linéaire.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvimGl-EI/AAAAAAAAAAk/tl8KS9wy630/s1600-h/exp.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvimGl-EI/AAAAAAAAAAk/tl8KS9wy630/s320/exp.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087360631714478146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_lAKV-lpQ4_s/RpnvfWGl-DI/AAAAAAAAAAc/F1muz-Hemak/s1600-h/log.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_lAKV-lpQ4_s/RpnvfWGl-DI/AAAAAAAAAAc/F1muz-Hemak/s320/log.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087360575879903282" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvbmGl-CI/AAAAAAAAAAU/Ch8i0nx5gvk/s1600-h/lin.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvbmGl-CI/AAAAAAAAAAU/Ch8i0nx5gvk/s320/lin.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087360511455393826" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-678562935142769105?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/678562935142769105/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=678562935142769105' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/678562935142769105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/678562935142769105'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/07/scoop.html' title='Scoop'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_lAKV-lpQ4_s/RpnvWmGl-BI/AAAAAAAAAAM/qz1_Zk7zYsQ/s72-c/sin.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5498286023220110416</id><published>2007-06-27T02:39:00.000+02:00</published><updated>2007-06-28T10:13:09.431+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='inférence'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Un type bien</title><content type='html'>La fête du ciné se termine. Je n'ai vu que deux films, &lt;em&gt;Boulevard de la Mort&lt;/em&gt; et &lt;em&gt;Dialogues avec mon Jardinier&lt;/em&gt;. J'ai beaucoup aimé les deux. Ils sont très différents, mais ont cependant un point commun: on sort des deux en réalisant comme les choses simples sont efficaces. Pour le premier je pense à la simplicité de la violence et à celle du ressort "vengeance" qui fait jubiler le public comme rarement. Pour le second il s'agit de la simplicité du retour aux sources, à la nature, au jardinage, s'opposant à la vie urbaine et une création artistique sur-intellectuallisante.&lt;br /&gt;&lt;br /&gt;Je ne peux pour ma part me résoudre à la simplicité, et, cherchant de nouvelles lectures, je suis retombé de plus belle sur Philip K. Dick, l'embrouilleur de réalités, avec le volume un (sur deux) de l'intégrale de ses nouvelles. Et, pour changer, je code: j'enrichis le système de type de liquidsoap, et je saisis cette occasion pour écrire un quelques mots sur l'inférence de type.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pourquoi typer ?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Lors de l'exécution d'un programme, si on ne fait rien pour s'en prémunir, certaines choses absurdes peuvent arriver. Une fonction à binaire peut ne recevoir qu'un argument, on peut se retrouver à additioner un entier et un couple de chaînes de caractères, etc. Il est difficile de prévoir exactement ces problèmes sans exécuter le programme, et cela devient impossible dès lors que le langage devient &lt;em&gt;Turing puissant&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Une première approche consiste à ne rien faire, et laisser le programmeur attendre que l'erreur à l'exécution arrive. C'est litéralement nul, il faut donc donner un nom à cela ("dynamique") et balancer quelques slogans qui font bien ("de toutes façons les tests unitaires sont plus précis que le typage") pour faire bonne figure. La majorité des langages de scripts adoptent cette approche. Selon l'expression absurde à évaluer, une vraie erreur va être levée, ou l'interpréteur va adopter une solution et continuer. Par exemple, si une fonction n'est pas appelée avec tous ses arguments, l'un d'eux pourra avoir la valeur spéciale &lt;code&gt;undefined&lt;/code&gt;. Tôt ou tard, cette valeur spéciale posera une vraie erreur (on peut imaginer que l'interpréteur refuse catégoriquement de l'additionner avec quoi que ce soit), et il  sera assez difficile pour le programmeur de trouver d'où venait cet &lt;code&gt;undefined&lt;/code&gt;, qui aura pu passer de fonction en fonction avant de poser réellement problème. Je ne vais pas en dire plus sur cette approche qui ne fait rien pour le programmeur.&lt;br /&gt;&lt;br /&gt;Le typage peut être vu comme une sur-approximation de l'ensemble des comportements qui peuvent arriver. Parfois le typage va donc détecter un problème qui ne peut pas vraiment arriver -- si on écrit une expression absurde dans une branche morte du code. En pratique, ça reste naturel. Quelques exemples rapides: &lt;code&gt;3&lt;/code&gt; aura le type &lt;code&gt;int&lt;/code&gt;; &lt;code&gt;("trois",3)&lt;/code&gt; le type &lt;code&gt;string*int&lt;/code&gt;; et la fonction &lt;code&gt;fun x -&amp;gt; x+1&lt;/code&gt; le type &lt;code&gt;int -&amp;gt;int&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Le typage &lt;em&gt;statique&lt;/em&gt; consiste à vérifier les types avant l'exécution du programme. Dans certains langages, le programmeur écrit les types de ses variables (C/C++, Java, ...). Cela peut devenir assez lourd. D'autres langages (OCaml, SML...) sont capables de calculer le type le plus général d'une expression, c'est ce qu'on appelle l'&lt;em&gt;inférence&lt;/em&gt;. Quand un langage a cette propriété, c'est la panacée: on n'écrit pas les lourdes annotations de type, et on a une vérification statique du code. De plus, aucune information de type n'étant nécessaire à l'exécution, les valeurs sont représentées de façon plus compacte et manipulées de façon plus immédiate, et on obtient des programmes plus rapides.&lt;br /&gt;&lt;br /&gt;Le bémol du typage statique inféré, c'est la complexité des messages en cas d'erreur de type. D'autre part, si le système est trop simple, cela contraindra trop le programmeur dans son utilisation du langage. Mais quand on étend le système de type, on complexifie rapidement les erreurs. Il y a là un compromis délicat.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Inférer les types&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Comment deviner le type d'une expression? Il suffit de regarder de près, en commencant par les expressions élémentaires et en remontant... Prenons l'exemple de &lt;code&gt;fun x -&amp;gt; x+1&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;On commence sur &lt;code&gt;1&lt;/code&gt;, qui a évidemment le type &lt;code&gt;int&lt;/code&gt;. Ensuite on rencontre &lt;code&gt;x&lt;/code&gt;, dont le type est inconnu. Mais pour que &lt;code&gt;x+1&lt;/code&gt; soit valide il faut bien que &lt;code&gt;x&lt;/code&gt; soit un entier. La fonction a donc le type &lt;code&gt;int -&amp;gt; int&lt;/code&gt;. Si je la nomme &lt;code&gt;f&lt;/code&gt;, on peut maintenant chercher le type de &lt;code&gt;fun y -&amp;gt; f("bla")&lt;/code&gt;. On voit qu'on utilise &lt;code&gt;f&lt;/code&gt; avec une chaîne comme paramètre au lieu d'un entier, c'est une erreur de type.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Polymorphisme&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Une extension simple et qui fonctionne bien est le polymorphisme -- ou l'appelle généricité dans certains langages. Si j'écris &lt;code&gt;fun x -&amp;gt; x&lt;/code&gt;, je ne fais aucune hypothèse sur le type de mon argument, et je pourrais utiliser cette fonction sur n'importequelle valeur. C'est possible, OCaml lui donnera par exemple le type &lt;code&gt;'a -&amp;gt; 'a&lt;/code&gt;, qui veut dire &lt;code&gt; pour tout a, a -&amp;gt; a&lt;/code&gt;. Exemple moins bidon: la fonction qui retourne une liste ne fait aucune hypothèse sur le type des éléments de la liste, et aura le type &lt;code&gt;'a list -&amp;gt; 'a list&lt;/code&gt;. (Exercice pénible: faites la même chose avec Java...)&lt;br /&gt;&lt;br /&gt;Comme inférer ces types ? Il suffit de généraliser sur les variables de type (1) qui ne sont pas instantiées et (2) qui ont été introduites dans la fonction. Quand on type &lt;code&gt;fun x -&amp;gt; x&lt;/code&gt;, on vérifie le corps de la fonction sans avoir besoin d'imposer aucune contrainte au type de &lt;code&gt;x&lt;/code&gt;, c'est encore une inconnue, que Caml note &lt;code&gt;'_t&lt;/code&gt;. L'expression a donc le type &lt;code&gt;'_t -&amp;gt; '_t&lt;/code&gt;, qu'on généralisera en &lt;code&gt;'a -&amp;gt; 'a&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Si par contre je type &lt;code&gt;fun x -&amp;gt; fun y -&amp;gt; x&lt;/code&gt;, il faut faire un peu plus attention. Mauvaise solution: la fonction interne a le type &lt;code&gt;'_Ty -&amp;gt; '_Tx&lt;/code&gt;, que je généralise en &lt;code&gt;'a -&amp;gt; 'b&lt;/code&gt;, l'expression complète a donc le type &lt;code&gt;'_Tx -&amp;gt; ('a -&amp;gt; 'b)&lt;/code&gt;, généralisé en &lt;code&gt;'c -&amp;gt; 'a -&amp;gt; 'b&lt;/code&gt;. C'est manifestement faux, car cela veut dire: je prends deux paramètres quelconque et je te renvoie un truc de n'importe quel type.&lt;br /&gt;&lt;br /&gt;Si on applique la condition (2) sur l'exemple &lt;code&gt;fun x -&amp;gt; fun y -&amp;gt; x&lt;/code&gt;, voila comment cela se passe. La fonction interne a le type &lt;code&gt;'_Ty -&amp;gt; '_Tx&lt;/code&gt;, mais &lt;code&gt;'_Tx&lt;/code&gt; n'a pas été introduit dans cette fonction interne. On ne généralise qu'en &lt;code&gt;'a -&amp;gt; '_Tx&lt;/code&gt;. La fonction externe a donc le type &lt;code&gt;'_Tx -&amp;gt; 'a -&amp;gt; '_Tx&lt;/code&gt;, qu'on généralise en &lt;code&gt;'b -&amp;gt; 'a -&amp;gt; 'b&lt;/code&gt;. C'est correct, cela veut dire: donne moi deux paramètres, je te renvoie un truc du type du premier.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Subtilités avec les références&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Encore un petit détail avant de conclure. La liste vide &lt;code&gt;[]&lt;/code&gt; peut sans problème avoir un type polymorphe &lt;code&gt;'a list&lt;/code&gt;. Il n'en est pas de même pour une référence &lt;code&gt;ref []&lt;/code&gt;, qui doit garder le type &lt;code&gt;'_T list ref&lt;/code&gt;, sans généralisation sur &lt;code&gt;'_T&lt;/code&gt;. On ne modifie jamais une liste: on en crée une autre qui pointe sur l'ancienne. Et il n'y a aucune problème à ce qu'une liste d'entiers finisse en pointant la même liste vide qu'une liste de chaines. Par contre on modifie une référence, c'est sa raison d'être. Si on utilise notre référence dans l'instruction &lt;code&gt;r := [1]&lt;/code&gt; on y range une liste d'entiers cela doit forcer &lt;code&gt;'_T&lt;/code&gt; à devenir &lt;code&gt;int&lt;/code&gt;. Car si par la suite on utilise un élément de la liste contenue dans la référence, cela ne peut pas être n'importe quoi, ce sera un entier.&lt;br /&gt;&lt;br /&gt;Exercice/exemple: vérifier que &lt;code&gt;fun x -&amp;gt; ref [x]&lt;/code&gt; a le type &lt;code&gt;'a -&gt; 'a list ref&lt;/code&gt;; que &lt;code&gt;let r = ref [] in (r, fun x -&amp;gt; r := [x])&lt;/code&gt; a le type &lt;code&gt;'_T list ref * ('_T -&amp;gt; unit)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Liquidsoap&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Pourquoi j'ai parlé de tout ça ? Ces jours ci, je rafraichis le code de l'inférence de type de liquidsoap. J'ai ces choses en tête et je crois que cela vaut le coup de les présenter. Bien sûr je n'ai pas détaillé tout ce qu'il y avait dans le système de type de liquidsoap. Mais tout ce que j'ai décrit s'y trouve. Ce qui me mène à mon second but: expliquer pourquoi toute cette technologie compliquée est nécessaire dans liquidsoap.&lt;br /&gt;&lt;br /&gt;Pour être honnête, ce n'est nécessaire que si l'on accepte le choix des types statiques et inférés dans le langage de script de liquidsoap. Pour moi il n'y a pas photo. Ensuite, on a besoin de fonctions dans le langage pour représenter les transitions. Enfin, nous prévoyons de généraliser liquidsoap, de générateur de flux audio à générateur de flux quelconque, en ajoutant la vidéo dans un premier temps. Pour cela, il faut du polymorphisme: au lieu des objets de type &lt;code&gt;source&lt;/code&gt; on aura des objets de type &lt;code&gt;format source&lt;/code&gt; où le format pourra être &lt;code&gt;audio&lt;/code&gt;, &lt;code&gt;video&lt;/code&gt;, etc. avec des informations en fait un peu plus raffinées. Certaines de fonctions actuelles de manipulation de flux, comme le &lt;code&gt;switch()&lt;/code&gt; qui passe d'un flux à l'autre, s'étendent naturellement à n'importe quel format. Elles auront donc un type polymorphe. Enfin, si j'ai parlé des limitations de la généralisation pour les références, c'est parce que les types source se comportent pareil.&lt;br /&gt;&lt;br /&gt;Le truc chouette, c'est que ça me donne une super excuse pour coder ces trucs que j'adore -- et que je vais enseigner l'an prochain en TP d'un cours de M1 de l'X, au passage. Et même avant l'arrivée du support vidéo, ça rend le langage plus souple et sympa pour un nombre considérable de choses. Mais je ne vais pas me lancer là dedans, c'est assez...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5498286023220110416?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5498286023220110416/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5498286023220110416' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5498286023220110416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5498286023220110416'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/06/un-type-bien.html' title='Un type bien'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3459533317941612259</id><published>2007-06-15T10:01:00.000+02:00</published><updated>2007-08-26T03:21:21.274+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mylife'/><category scheme='http://www.blogger.com/atom/ns#' term='radio'/><category scheme='http://www.blogger.com/atom/ns#' term='jeu'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='general'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Création</title><content type='html'>Je ne code plus trop ces temps-ci, après la release de liquidsoap-0.3.3. Déja, je suis pas mal occupé au labo, et ça porte ses fruits. Mais de toute façon, il faut bien qu'il y ait des périodes moins frénétiques: c'est un projet sans deadline ni client. Aucune raison de se faire du mal pour apporter une amélioration montre en main. Me voilà donc dans une période tranquille, où je me demande plutôt ce que je pourrais faire de créatif à la place.&lt;br /&gt;&lt;br /&gt;Mes pensées vont par exemple à ce projet de projet de jeu de piste (ou &lt;a href="http://en.wikipedia.org/wiki/Alternate_reality_game"&gt;&lt;acronym title="Alternate Reality Game"&gt;ARG&lt;/acronym&gt;&lt;/a&gt;?) radiophonique, parti de la &lt;a href="http://en.wikipedia.org/wiki/Numbers_station"&gt;numbers station&lt;/a&gt; de Balbinus... Disséminer des pistes, principalement par le biais de quelques webradios amies, vers les éléments d'une histoire/énigme/univers caché et mystérieux. Mais quelle histoire raconter, quelle idée faire passer? Parler de l'excès de communication, de l'usure des mots? des excès de l'individualisme?&lt;br /&gt;&lt;br /&gt;En parlant d'alliance création/technique, je suis tombé sur &lt;a href="http://lamenagerie.com"&gt;la ménagerie&lt;/a&gt;, un studio d'animation amateur sympathique, qui lie developpement open-source et création d'animations en stopmotion (jetez un oeil à la section &lt;a href="http://lamenagerie.com/studio/?el=243"&gt;studio&lt;/a&gt;, par exemple &lt;a href="http://lamenagerie.com/~menagerie/w.avi"&gt;cette surprise&lt;/a&gt;..) Chapeau bas!&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size:smaller"&gt;De façon moins intellectuelle, je me demande si j'accrocherais à des jeux à histoire comme un Final Fantasy ou Castlevania sur DS; et si le &lt;a href="http://linuxfr.org/2007/06/08/22597.html"&gt;EEE PC&lt;/a&gt; sortira vraiment en Aout, au prix annoncé et en quantité suffisamment énorme :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3459533317941612259?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3459533317941612259/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3459533317941612259' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3459533317941612259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3459533317941612259'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/06/cration.html' title='Création'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2444477082587708747</id><published>2007-06-01T22:46:00.000+02:00</published><updated>2007-06-01T23:00:47.805+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mylife'/><category scheme='http://www.blogger.com/atom/ns#' term='general'/><category scheme='http://www.blogger.com/atom/ns#' term='these'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><title type='text'>Bientôt deux ans..</title><content type='html'>J'anticipe un peu mais le temps passe vite, et en Septembre prochain j'entamerai ma troisième année de thèse. Pour ceux qui ne savent pas, ou pour mémoire, quelques mots sur ces derniers temps.&lt;br /&gt;&lt;br /&gt;J'ai bouclé un &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/papers.html"&gt;article&lt;/a&gt; que j'aime bien, des observations mignonnes de théorie de la démonstration, dans une logique linéaire dotée de principes d'induction et coinduction. L'article a été soumis à une conférence, et rejeté. Les relecteurs n'étaient pas du domaine et ont décidé que ce n'était pas bien. Je ne vais pas trop m'étendre, le papier retente sa chance à une prochaine conférence sous peu. En plus, celle là m'enverrait en Arménie, c'est plus funky que la Suisse.&lt;br /&gt;&lt;br /&gt;Sinon j'ai passé un week-end fatiguant mais fructueux à un workshop à Edinburgh. Les gens s'intéressaient globalement aux mêmes choses que moi, et réciproquement. J'ai pu lier quelques connaissances, et ça m'a remué quelques idées en tête. Il faisait pas beau, mais la ville est très classe dans son rôle froid et solennel. Par contre j'ai pas trouvé le moyen de me faire happer par un pub sympathique, on m'a même déconseillé d'essayer.&lt;br /&gt;&lt;br /&gt;Pendant ce temps là Frank était au Canada et Dolebraï a peu bougé. Avant-hier on s'y est remis doucement, et il recommence à alimenter la playlist. J'&lt;a href="http://www.dolebrai.net/tracks/voyage-i---the-japanese-garden-alternarama.mp3"&gt;écoute&lt;/a&gt; avec plaisir ses derniers &lt;a href="http://dolebrai.net/playlist/morceau/voyage-i---the-japanese-garden-alternarama/"&gt;ajouts&lt;/a&gt;. C'est très zen, parfait pour l'humeur du moment.&lt;br /&gt;&lt;br /&gt;Ooomm...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2444477082587708747?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2444477082587708747/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2444477082587708747' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2444477082587708747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2444477082587708747'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/06/bientt-deux-ans.html' title='Bientôt deux ans..'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-4699977644875510689</id><published>2007-05-24T14:31:00.000+02:00</published><updated>2007-06-15T10:01:22.561+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='caml'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Pour être honnête..</title><content type='html'>J'ai critiqué ici Python et Javascript.. Je vous ai déja dit que Caml aussi avait quelques comportements décevants, à la limite du bug ?&lt;br /&gt;&lt;div class="code"&gt;# let f () =&lt;br /&gt;   let s = "abc" in&lt;br /&gt;     s.[0] &lt;- char_of_int (1 + int_of_char s.[0]) ;&lt;br /&gt;     s ;;&lt;br /&gt;val f : unit -&gt; string = &amp;lt;fun&amp;gt;&lt;br /&gt;# f () ;;&lt;br /&gt;- : string = "bbc"&lt;br /&gt;# f () ;;&lt;br /&gt;- : string = "cbc"&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Et grosse dédicace à Romain qui se met à OCaml pour de bon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4699977644875510689?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4699977644875510689/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4699977644875510689' title='6 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4699977644875510689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4699977644875510689'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/05/pour-tre-honnte.html' title='Pour être honnête..'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-5870434696779350072</id><published>2007-05-18T02:21:00.000+02:00</published><updated>2007-05-18T03:04:02.945+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='caml'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Sucre</title><content type='html'>Déja un mois depuis mon dernier post, il est temps d'en aligner un autre, dans la lignée des notes bien techniques. Le developpement de liquidsoap continue sûrement et plutôt pas lentement. L'API s'étoffe, notamment avec le crossfade intelligent utilisant les intensités relatives des débuts/fins de fichier, et des traitements de son de fou grâce à la libsoundtouch; le format AAC est supporté; nous n'avons presque plus à rougir du support ALSA; la doc devient plus lisible; et une multitude de petits détails s'améliorent. Romain nous pousse à releaser au plus vite, ce qui devrait se faire vu les grands chantiers qui se profilent de nouveau à l'horizon. Pour ma part j'oscille entre l'excitation de voir tout cela si bien tourner, et l'énervement de passer beaucoup de temps à orchestrer ça, corrigeant ou ajoutant du code selon des priorités qui ne sont plus seulement les miennes: tel utilisateur insiste sur un point, tel développeur fait une modification pas forcément judicieuse... et je ne peux m'empêcher de vite intervenir, peut être à tort.&lt;br /&gt;&lt;br /&gt;Après la release, ma priorité sera à l'enrichissement du système de type de liquidsoap, avec du polymorphisme et du sous-typage, amenant une simplification de certains opérateurs, et surtout la possibilité de faire cohabiter des sources manipulant différent formats de flux. Après ça, Sam va pouvoir se faire plaisir avec la vidéo... On envisage aussi de généraliser les notions de fade et de crossfade intelligent au delà de la simple mesure de volume: on peut désormais mesurer et changer le BPM d'une source, on se prend à penser à des transitions préservant la continuité du BPM. Voila pour le futur. J'espère parler de typage la prochaine fois, mais pour tout de suite je vous propose encore de l'analyse syntaxique.&lt;br /&gt;&lt;br /&gt;Certains sucres syntaxiques semblent tout simples, mais ne rentrent pas dans la sacro-sainte architecture lex/yacc. Par exemple, le preprocessing, qui permet de n'inclure certaines parties du script que quand telle feature est activée: &lt;code&gt;%ifdef FEATURE CODE %endif&lt;/code&gt;. Cela ne peut être traité par le parser, ne serait-ce que parce que la construction peut être utilisée à tous les niveaux de la grammaire, ce qui l'alourdirait considérablement. Autre exemple, la notation bien pratique à la Ruby: &lt;code&gt;"Bonjour #{get_name()}!"&lt;/code&gt; au lieu de &lt;code&gt;"Bonjour "+get_name()&lt;/code&gt;. Ce n'est pas faisable dans le lexer tout seul, et pénible à traiter au niveau du parser, qui en théorie ne dépend pas du lexer.&lt;br /&gt;&lt;br /&gt;La solution est d'accepter de s'éloigner un chouilla de l'archi habituelle, en ajoutant des intermédiaires entre analyse syntaxique et lexicale. C'est particulièrement simple en Caml, où un lexer n'est autre qu'une fonction prenant un état (position dans le texte) et renvoyant le symbole suivant dans le flux. On peut donc écrire des fonctions pour enrober le lexer original, afin d'obtenir les notations décrites -- et on simplifie par ailleurs notre lexer en traitant de la même façon les retours à la ligne pour lever les ambiguités dont je parlais la dernières fois. Un petit exemple, le traitement des &lt;code&gt;%ifdef&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;(* takes a function of type Lexing.lexbuf-&gt;Lang_parser.token,&lt;br /&gt;   and returns a function of the same type *)&lt;br /&gt;let preprocess tokenizer =&lt;br /&gt;  let state = ref 0 in (* number of nested %ifdef *)&lt;br /&gt;  let rec token lexbuf =&lt;br /&gt;    match tokenizer lexbuf with&lt;br /&gt;      | Lang_parser.PP_IFDEF -&amp;gt;&lt;br /&gt;          begin match tokenizer lexbuf with&lt;br /&gt;            | Lang_parser.VAR v -&amp;gt;&lt;br /&gt;                if feature_enabled v then begin&lt;br /&gt;                  incr state ;&lt;br /&gt;                  token lexbuf&lt;br /&gt;                end else&lt;br /&gt;                  let rec skip () =&lt;br /&gt;                    match tokenizer lexbuf with&lt;br /&gt;                      | Lang_parser.PP_ENDIF -&amp;gt; token lexbuf&lt;br /&gt;                      | _ -&amp;gt; skip ()&lt;br /&gt;                  in&lt;br /&gt;                    skip ()&lt;br /&gt;            | _ -&amp;gt; failwith "expected a variable after %ifdef"&lt;br /&gt;          end&lt;br /&gt;      | Lang_parser.PP_ENDIF -&amp;gt;&lt;br /&gt;          if !state=0 then failwith "no %ifdef to end here" ;&lt;br /&gt;          decr state ;&lt;br /&gt;          token lexbuf&lt;br /&gt;      | x -&amp;gt; x&lt;br /&gt;  in&lt;br /&gt;    token&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Après avoir défini quelques sucres syntaxiques, on utilise tout simplement le lexer étendu &lt;code&gt;expand (preprocess (strip_newlines Lang_lexer.token))&lt;/code&gt; au lieu de &lt;code&gt;Lang_lexer.token&lt;/code&gt;. L'exemple complet se trouve sur notre &lt;a href="http://savonet.svn.sourceforge.net/viewvc/savonet/trunk/liquidsoap/src/tools/lang_user.ml?view=markup"&gt;SVN&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-5870434696779350072?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/5870434696779350072/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=5870434696779350072' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5870434696779350072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/5870434696779350072'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/05/sucre.html' title='Sucre'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-770201739831863997</id><published>2007-04-20T11:54:00.000+02:00</published><updated>2007-04-20T13:25:03.536+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='yacc'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Grammaire</title><content type='html'>J'ai parlé &lt;a href="http://misterpingouin.blogspot.com/2006/05/newline-sensitive-parser.html"&gt;ici-même&lt;/a&gt;, il y a presque un an, d'une petite astuce pour obtenir un langage sans point-virgule dans les séquences, juste un peu whitespace-sensitive, tout en utilisant le générateur de parser (ocaml)yacc. Je suis toujours dans cette optique, car je veux garder cette syntaxe légère, et je crois toujours qu'écrire mon parser à la main est source d'emmerdes au moins à long terme.&lt;br /&gt;&lt;br /&gt;Résume de l'épisode précédent: le seul endroit où le retour à la ligne compte, c'est pour distinguer &lt;code&gt;f ; (1,2)&lt;/code&gt; de &lt;code&gt;f(1,2)&lt;/code&gt;. Bien sûr la première expression n'a peu d'intérêt, la séquence ne servant qu'aux effets de bord que &lt;code&gt;f&lt;/code&gt; ne fait pas, mais cela ne se voit pas au stage de l'analyse syntaxique. Ma solution a été d'introduire un token &lt;code&gt;VARLPAR&lt;/code&gt; qui regroupe la variable et la parenthèse qui la suit si elles ne sont pas séparées par un retour à la ligne.&lt;br /&gt;&lt;br /&gt;Second épisode: &lt;a href="http://savonet.sf.net/wiki/Liquidsoap"&gt;liquidsoap&lt;/a&gt; est en plein boom. Nous avons de nouveaux contributeurs, de nouveaux utilisateurs, on parle de nous, de nouvelles idées sont implémentées, etc.&lt;br /&gt;&lt;br /&gt;Une de ces idées est le cross-fading intelligent. Au lieu de passer au cross-fading une fonction de transition qui décrit comment sont combinés les débuts et fins de piste, on y passe une liste de &lt;code&gt;(condition,transition)&lt;/code&gt;. La condition est une fonction à qui le &lt;code&gt;smart_cross&lt;/code&gt; passe les puissances du signal sonore de part et d'autre de la transition. L'opérateur choisit la première fonction de transition dont la condition est validée. On peut ainsi choisir de superposer, fader, en fonction du volume des débuts et fin de piste. Romain a commencé à coder dans &lt;a href="http://savonet.svn.sourceforge.net/viewvc/savonet/trunk/liquidsoap/scripts/utils.liq.in?revision=3399&amp;view=markup"&gt;utils.liq&lt;/a&gt; l'utilisation du smart cross selon la description que mouke de bide-et-musique nous a faite.&lt;br /&gt;&lt;br /&gt;Cet opérateur amène le besoin de coder dans notre langage de script des expressions arithmétiques, des comparaisons, etc. Et j'ai donc du étendre la grammaire. Pour faire simple, disons qu'on ajoute &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt; et &lt;code&gt;-&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Premier conflit: comment distinguer &lt;code&gt;f(x) \n -1&lt;/code&gt; de &lt;code&gt;f(x)-1&lt;/code&gt;. Les deux sont naturels, on ne peut en éliminer aucun d'office. A moins d'empêcher le programmeur d'éclater ses expressions arithmétiques sur plusieurs lignes, ce qui est peu naturel et de toute façon difficilement réalisable dans mon cadre.&lt;br /&gt;&lt;br /&gt;La solution vient de zmdkrbou, qui me propose de distinguer les expressions closes &lt;code&gt;cexpr&lt;/code&gt; et les expressions générales &lt;code&gt;expr&lt;/code&gt;. Une expression close peut être utilisée sans ambiguité dans une séquence: pour cela on limite les symboles pouvant apparaitre en tête, i.e. on élimine donc les négatifs &lt;code&gt;-42&lt;/code&gt;, qui ne sont présents que dans les expressions générales. On peut obtenir une expression close représentant un négatif en l'entourant de parenthèses. Dans la plupart des règles, on peut continuer à utiliser des expressions générales, mais la règle de séquençage d'expression est restreinte aux expressions closes. Ainsi &lt;code&gt;f(x) - 1&lt;/code&gt;, où que soient les retours à la ligne, sera la valeur de &lt;code&gt;f(x)&lt;/code&gt; décrémentée de &lt;code&gt;1&lt;/code&gt;. Et on écrira &lt;code&gt;f(x) (-1)&lt;/code&gt; (en général sur deux lignes, mais rien n'oblige) pour signifier qu'on évalue &lt;code&gt;f(x)&lt;/code&gt; et qu'on retourne &lt;code&gt;-1&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;On tient le bon bout, mais l'histoire ne s'arrête pas là, et yacc m'en a fait baver. On a dans notre grammaire la règle (1) &lt;code&gt;expr: cexpr&lt;/code&gt;, qui dit qu'une expression close est aussi une expression, et la règle (2) &lt;code&gt;cexpr: cexpr PLUS expr&lt;/code&gt;. J'avais laissé un &lt;code&gt;expr&lt;/code&gt; à droite du &lt;code&gt;PLUS&lt;/code&gt; car l'ambiguité vue ci-dessus n'est présente qu'en début d'expression.&lt;br /&gt;&lt;br /&gt;Sachant que l'automate d'analyse syntaxique doit décider de ce qu'il fait en ne regardant qu'un symbole en avant, comment savoir dans la situation &lt;code&gt;cexpr PLUS ...&lt;/code&gt; si la &lt;code&gt;cexpr&lt;/code&gt; doit être considérée comme une &lt;code&gt;expr&lt;/code&gt;, auquel cas on réduit la règle (1), ou s'il faut avancer dans la règle (2) en mangeant de suite le &lt;code&gt;+&lt;/code&gt;. L'automate est bête, pour lui une addition peut arriver après une expression générale car une expression générale peut être, en particulier, close. On ne peut le guider qu'avec des priorités, je mets donc une priorité plus faible à la coercion (1) qu'à la règle (2).&lt;br /&gt;&lt;br /&gt;Et là, c'est le drame. Les priorités entre l'addition et la multiplication ne sont plus du tout respectées, l'analyseur parenthèse tout à droite comme un sale. On lui donne &lt;code&gt;2*3+1&lt;/code&gt; il lit &lt;code&gt;2*(3+1)&lt;/code&gt;. Après masse de bataille, je m'aperçois que la formulation de la règle (2), bien qu'inambigue, pose problème. On a &lt;code&gt;expr: cexpr PLUS expr | cexpr MULT expr ...&lt;/code&gt;. Le problème est que l'automate défavorise maintenant la coercion &lt;code&gt;expr:cexpr&lt;/code&gt;. Du coup quand il voit le &lt;code&gt;+&lt;/code&gt; après le &lt;code&gt;3&lt;/code&gt; il ne va pas réduire l'expression close &lt;code&gt;3&lt;/code&gt; en expression pour réduire ensuite l'expression close &lt;code&gt;2*3&lt;/code&gt;. Il va préférer manger le &lt;code&gt;+&lt;/code&gt;, ce qui conduit à réduire l'expression close &lt;code&gt;3+1&lt;/code&gt; en premier.&lt;br /&gt;&lt;br /&gt;Au final la règle (2) doit s'écrire &lt;code&gt;cexpr: cexpr PLUS cexpr&lt;/code&gt;. Et on n'y perd pas trop. On ne peut plus écrire &lt;code&gt;3+-1&lt;/code&gt; mais il faut parenthéser en &lt;code&gt;3+(-1)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;La morale: c'est toujours possible d'utiliser le couple lex/yacc pour une syntaxe sans point-virgule, en limitant énormément la sensibilité aux blancs (espace et retour à la ligne), ouf. Par contre l'automate de yacc est bien bête sur une production du type &lt;code&gt;expr: cexpr&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Un jour faudra que je voie si c'est si difficile de ne pas ignorer les retours à la ligne à l'analyse syntaxique, et de les traiter explicitement partout dans la grammaire. A priori c'est lourd, comme il ne compte pas dans la majorité des cas. Mais une astuce n'est pas à exclure..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-770201739831863997?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/770201739831863997/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=770201739831863997' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/770201739831863997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/770201739831863997'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/04/grammaire.html' title='Grammaire'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-9137633453553681167</id><published>2007-04-05T15:38:00.000+02:00</published><updated>2007-04-06T09:25:21.462+02:00</updated><title type='text'>Libertés</title><content type='html'>&lt;span style="font-style:italic;"&gt;Ceci est un post en préparation pour Dolebraï...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Je suis tombé récemment sur &lt;a href="http://diogene.ch"&gt;Diogène&lt;/a&gt;, un éditeur de culture libre, qui se pose une question intéressante: Qu'est-ce que les arts libres ? Je rebondis sur leur opinion.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;La culture libre est une véritable provocation au système capitaliste du copyright.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Non. Diffuser librement une oeuvre ne veut pas dire renoncer au copyright, c'est à dire à son droit d'auteur. &lt;a href="http://creativecommons.org/"&gt;Creative Commons&lt;/a&gt; décrit par exemple ses licences comme un moyen de changer les termes de son droit d'auteur, passer du "tous droits réservés" à "certains droits réservés", en offrant au public certaines libertés.&lt;br /&gt;&lt;br /&gt;Le copyright est une bonne chose. Il a été instauré pour éviter que les auteurs soient dépossédés de leurs oeuvres et gardent certains droit fondamentaux, auparavant détenus par les éditeurs. Le droit d'auteur a aussi introduit certains droits pour le public, comme la garantie d'utilisation libre d'une oeuvre, la copie privée, le droit de courte citation ou de satyre. De nos jours il faudrait même défendre le droit d'auteur, car les droits des auteurs et du public sont menacés par les majors de la distribution musicale (qui attaquent le droit à la copie privée), voire par la SACEM (qui ne laisse pas la possibilité à ses adhérents de diffuser librement leurs oeuvres).&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;L’art libre, c’est aussi mettre en oeuvre la philosophie du don, une philosophie à développer aujourd’hui plus que jamais, car le capitalisme a mangé tous les cerveaux (ou presque) de nos contemporains.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Bien sûr. Le don c'est beau. Le partage et l'échange c'est aussi créatif et utile. Et il est vrai que cela devient très important de nos jours, où pour se faire encore plus de gros sous sur la culture, certains poids lourds tentent de la verrouiller de plus en plus.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Les arts libres, c’est de la culture faite par les pauvres, pour les pauvres ! [...] En effet, la philosophie du don ne peut fonctionner que si on accepte de vivre de rien, sans consommer ce qui est payant, donc en ne consommant que de la culture ou des produits gratuits. Cela implique de vivre en grande partie hors du système !&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Certainement pas, ni en théorie ni en pratique. D'abord dans les faits, les gens qui produisent et consomment de la culture libre ne sont pas tant hors du système que ça, ce ne sont pas les plus démunis, ne serait-ce que parce que la culture libre passe par le net. Et puis donner ne doit pas vouloir dire accepter de ne rien attendre en échange -- c'est quelquechose qu'on retrouve aussi dans le logiciel libre, où l'on donne en attendant des dons en échange.&lt;br /&gt;&lt;br /&gt;De nombreux artistes diffusent librement leur musique parce que c'est la meilleure opportunité qu'ils ont pour être visibles. Cela ne veut pas dire qu'ils n'espèrent pas vivre le leur musique. Cela n'exclut pas non plus que certains envisagent d'abandonner les licences libres s'ils peuvent gagner mieux leur vie ainsi.&lt;br /&gt;&lt;br /&gt;Les licences d'art libre sont un moyen ouvert à chacun de diffuser son art, tout en défendant son droit d'auteur, et éventuellement d'en vivre, en se faisant connaître, ce qui permet de faire des concerts, etc. La culture libre c'est aussi un bel idéal, surtout dans le contexte actuel, mais pas seulement.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-9137633453553681167?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/9137633453553681167/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=9137633453553681167' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/9137633453553681167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/9137633453553681167'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/04/liberts.html' title='Libertés'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-8557054753178222090</id><published>2007-03-30T11:48:00.000+02:00</published><updated>2007-03-30T12:51:47.272+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><category scheme='http://www.blogger.com/atom/ns#' term='general'/><title type='text'>Re-Paf!</title><content type='html'>Il n'y a pas que &lt;a href="http://misterpingouin.blogspot.com/2006/12/paf.html"&gt;Toots&lt;/a&gt; qui s'amuse aux dépens de ceux qui utilisent son contenu graphique.. un blogueur américain s'est ainsi &lt;a href="http://www.ecrans.fr/spip.php?article1057"&gt;rendu justice&lt;/a&gt; en se payant la tête du sénateur américain qui l'avait spolié.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-8557054753178222090?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/8557054753178222090/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=8557054753178222090' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8557054753178222090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/8557054753178222090'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/03/re-paf.html' title='Re-Paf!'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3904009446905900090</id><published>2007-03-22T18:01:00.000+01:00</published><updated>2007-03-22T21:37:00.105+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>J'en peux plus</title><content type='html'>En fin de semaine dernière j'ai donné un coup de collier pour releaser &lt;code&gt;liquidsoap 0.3.2&lt;/code&gt;, merci au passage à Romain qui s'est occupé des releases des librairies associées, et du packaging Debian par derrière. Le but pour moi était de passer ensuite une semaine studieuse à écrire mon article. Impossible.&lt;br /&gt;&lt;br /&gt;Lundi nous recevons sur la liste &lt;code&gt;savonet-users&lt;/code&gt; un mail de mouke. Je cite car l'archive de la mailing-list est plus que pourrie:&lt;br /&gt;&lt;blockquote&gt;I recently discovered LiquidSoap and it seems it is the streamer I have dreamed of for some months. I am the tech guru of the french webradio "Bide et Musique".&lt;/blockquote&gt;&lt;br /&gt;Mouke a déja un clone de Bide et Musique qui tourne avec liquidsoap et songe à distribuer son système de gestion de la programmation musicale. La description qu'il en fait est alléchante, cela ferait un beau compagnon à liquidsoap!&lt;br /&gt;&lt;br /&gt;Nous avons de plus en plus de résidents sur le canal IRC &lt;code&gt;#savonet&lt;/code&gt; chez freenode. La plupart utilisent liquidsoap pour leur radio underground ou étudiante. Avec l'arrivée de ce mail tous les français se sont excités. J'ai passé la nuit à coder, sur la sortie ALSA et plusieurs autres détails; Samuel s'y est remis aussi et a mis au point un opérateur de renormalisation dynamique du volume; Balbinus s'est laissé pousser à coder un opérateur de compression. Et Mouke interface liquidsoap avec son outil. Quand j'arrive à décrocher je me fais rappeler à l'ordre par masse de questions et remarques. Je vais demander aux admins du labo de me désinstaller xchat... &lt;br /&gt;&lt;br /&gt;Mais ce n'est pas tout. Car O'Reilly parle de nous, comme me l'apprend Romain: &lt;a href="http://www.oreilly.fr/contenu/2007/03/18/une-radio-scriptable-avec-liquidsoap-et-savonet"&gt;Une radio scriptable avec Liquidsoap et Savonet&lt;/a&gt;. Je n'étais pas au courant, mais je remercie Xavier Cazin, qui avait découvert liquidsoap par hasard il y a un an.&lt;br /&gt;&lt;br /&gt;Ce genre de phénomène est exponentiel. &amp;Ccedil;a va dépoter :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3904009446905900090?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3904009446905900090/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3904009446905900090' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3904009446905900090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3904009446905900090'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/03/jen-peux-plus.html' title='J&apos;en peux plus'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-2699861261394189922</id><published>2007-03-16T20:49:00.000+01:00</published><updated>2007-03-16T21:03:31.086+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='logique'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Pendant ce temps là...</title><content type='html'>Pas posté depuis longtemps. Tout va bien, c'est le Printemps. La lumière est belle le soir en retrant de l'école, et l'herbe sent comme une fille qui sort de la douche. Si la bonne recherche c'est d'ouvrir des questions plutôt que d'en fermer, ça ressemble à ce que je fais... J'aurais bien aimé parler de beau code, malheureusement je me suis empêtré dans mes constructions et le temps me manque. Il semble que je doive remettre ça à cet été, où on aura d'ailleurs encore un visiteur codeur pour jouer avec moi. Voici quand même un petit screencast amusant -- mais long à charger:&lt;br /&gt;&lt;a href="http://mrpingouin.free.fr/boingue.gif"&gt;&lt;img style="width:430px" src="http://mrpingouin.free.fr/boingue.gif" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-2699861261394189922?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/2699861261394189922/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=2699861261394189922' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2699861261394189922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/2699861261394189922'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/03/pendant-ce-temps-l.html' title='Pendant ce temps là...'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-7337357472779773591</id><published>2007-02-25T00:04:00.000+01:00</published><updated>2007-02-25T00:32:11.238+01:00</updated><title type='text'>Meta-moutons</title><content type='html'>L'univers est composé d'atomes, eux-mêmes composés de trucs encore plus petits qui régissent leurs interactions. Enfin, c'est le modèle qu'en ont les hommes. Les hommes sont des tas de molécules vivant sur une planète (un autre gros tas de molécules) qu'ils appellent la Terre. Ils ont appris à survivre sur cette planète, et au bout d'un moment se sont mis à faire des choses un peu plus complexes comme compter les moutons, faire du commerce, etc. Viennent ensuite la théorie des nombres et les mathématiques en général. Quel sens donner à ces abstractions ? Comment rattacher ces notions formelles simples aux choses affreusement compliquées qui nous entourent ? Comment délimiter un mouton, avant d'en compter des troupeaux ?&lt;br /&gt;&lt;br /&gt;Vous comprendrez que ce train de pensée me mène à remettre en cause toute tentative de donner un sens à notre univers. Et de croire en particulier que toute cette science formelle qui nous fascine et nous fait "progresser" n'est qu'une construction folle, qui nous rend service presque par hasard... Ce genre de métaphysique est loin d'être malsain à mon avis, mais mène facilement à la déprime. Je me trompe peut-être à tout relativiser comme ça. Mais il me semble difficile, dans la position où nous sommes, d'affirmer quoi que ce soit sur le sens du monde ou la vérité des mathématiques.&lt;br /&gt;&lt;br /&gt;Une idée loin d'être déprimante sort de tout ça: créer un jeu où les joueurs évoluent selon les règles qu'ils se sont fixés, c'est à dire dans leur propre modèle de la réalité. Bien sûr ce modèle devrait avoir quelque chose à voir avec le modèle réel-dans-jeu pour que ce ne soit pas n'importe quoi -- le lecteur attentif pourra noter ici une faille possible de mon point de vue. Bien sûr aussi, cette réalité serait inconnue. Tout le monde pourrait jouer au physicien dans ce monde, et on pourrait imaginer des joueurs malins qui découvrent des possibilités si folles qu'on les appeleraient magiques.&lt;br /&gt;&lt;br /&gt;Bon, ne retenez pas votre souffle car je n'ai malheureusement rien de bien concret...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-7337357472779773591?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/7337357472779773591/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=7337357472779773591' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7337357472779773591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/7337357472779773591'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/02/meta-moutons.html' title='Meta-moutons'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-6342684522064059157</id><published>2007-02-12T19:37:00.000+01:00</published><updated>2007-02-12T19:49:47.721+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jeu'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>En attendant...</title><content type='html'>Je n'ai toujours pas reçu ma carte Arduino. Je m'en étonne ce matin et on me répond (comme par hasard) qu'elle partira aujourd'hui, problèmes avec un fournisseur, etc. On verra...&lt;br /&gt;&lt;br /&gt;En attendant, le jeu &lt;a href="http://anotherworld.fr"&gt;Another World&lt;/a&gt; a fêté ses quinze ans. Pour l'occasion, l'éditeur nous "offre" une édition spéciale, avec des décors réhaussés (nombre de couleurs augmenté, détails ajoutés) et (enfin) les graphismes vectoriels rendus en haute résolution. Je dis "offre" parce que c'est payant, uniquement disponible pour Windows. Ya certainement plein de gens qu'aimeraient voir la recette de ce mythe. &amp;Agrave; la place l'éditeur préfère se faire quelques recettes supplémentaires, qui seront probablement ridicules, d'autant plus que la nouvelle édition est déja craquée. Pour ma part j'étais chaud pour payer, mais j'ai voulu tester d'abord si la démo tournait sous Wine. Le non-émulateur fait tourner Warcraft III et WoW, mais.. pas Another World. Ils ont en effet trouvé le moyen d'utiliser les dernières fonctionnalités de DirectX, pour un jeu qui tourne sans problème sur NES ou GBA...&lt;br /&gt;&lt;br /&gt;Au final, j'ai ressorti ma ROM GBA, installé VisualBoyAdvance, et re-fini le jeu. C'est assez court quand on se souvient des ficelles -- et (j'avoue) qu'on zieute la soluce une ou deux fois pour ce dont on ne se souvient pas. Mais ce n'est pas pour ça qu'Another World doit être le seul jeu que j'ai fini plusieurs fois. C'est parceque c'est beau (même tout pixelisé) et c'est bien (même si l'histoire est linéaire) et c'est de la balle.&lt;br /&gt;&lt;br /&gt;Allez, un petit site marrant au passage: &lt;a href="http://www.clemenskogler.net/grandcontent"&gt;philosophie.ppt&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-6342684522064059157?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/6342684522064059157/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=6342684522064059157' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6342684522064059157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/6342684522064059157'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/02/en-attendant.html' title='En attendant...'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-3465308305200843383</id><published>2007-01-28T15:52:00.000+01:00</published><updated>2007-01-29T21:30:46.999+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='electronique'/><category scheme='http://www.blogger.com/atom/ns#' term='liquidsoap'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Art &amp; Technique</title><content type='html'>On pourrait croire que je vais me plonger/noyer dans le débat "la programmation est-elle un art ?", et bien non, je ne vais même pas parler de programmation. Ne pas en parler fournit cependant une excuse valable pour y mettre mon grain de sel, j'en profite... Mon avis personnel est que la programmation est une maladie. Plus sérieusement, je pense que cela relève plus de l'artisanat que de l'art, avec tout l'amour du travail bien fait qui est présent dans beaucoup d'autres disciplines, mais une notion de &lt;em&gt;bien fait&lt;/em&gt; qui n'existe pas avec l'art, et qui est liée à la fonctionalité du programme. Les poèmes et autres &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/pool/palindrome.ml"&gt;palindromes&lt;/a&gt; écrits dans des langages de programmation, n'ont (dans les cas que j'ai rencontrés) aucun intérêt en tant que programmes.&lt;br /&gt;&lt;br /&gt;Revenons à nos moutons. Je voudrais parler de Gumstix, Arduino, PureData et Liquidsoap. L'histoire commence il y a bien longtemps avec la panne de notre Nabaztag. Le lapin wifi est une réussite niveau design, mais n'est pas super solide, et les utilisations possibles de l'engin étaient un peu restreintes: il ne communique qu'avec le serveur officiel, certains services sont payants, on ne peut que jouer de courts fichiers sonores. On peut dire que c'était juste assez bien pour que je commence à penser à le remplacer, mais pas assez pour que je sois prêt à débourser 130€, même pour la nouvelle version avec un nombril-microphone. Bref, je me suis mis à chercher un moyen de fabriquer mon propre lapin wifi, si possible en re-utilisant des pièces. Voici deux trois trucs sur lesquels je suis tombé.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gumstix&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Piloter une carte wifi est une chose compliquée, et en plus ça consomme beaucoup. En revanche il semble relativement aisé de bricoler des circuits communiquant via Bluetooth ou Zigbee. Très bien, mais comment faire le lien avec Internet? Il faut un serveur qui y soit branché et communique avec le lapin. Dans un premier temps ce sera mon portable, mais à terme je crois que ce sera un &lt;a href="http://www.gumstix.com"&gt;Gumstix&lt;/a&gt; bricolé: un micro-PC linux, plus compact tu meurs, et relativement bon marché.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Arduino&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;A plus court terme il faut un circuit pour contrôler le haut-parleur, les moteurs et lampes du lapin. Le LEGO Mindstorm c'est rigolo, ça pourrait sûrement faire tout ça, mais c'est pas très compact et surtout super cher. Les microcontrolleurs programmables ça fait peur... Jusqu'à ce que je tombe sur le projet &lt;a href="http://www.arduino.cc"&gt;Arduino&lt;/a&gt;. Il s'agit d'un projet ouvert (code source et spec. matériel distribuées sous licences libres) qui développe des cartes programmables, avec pour cible première des étudiants en art. Ils semblent avoir un truc facile d'accès, qui tourne avec des outils libres (gcc + IDE à eux), supporté par une certaine communauté. A première vue c'est donc une solution à la fois sérieuse (vrai microcontrolleur, qui parle à n'importe quel composant électronique, qu'on peut à terme monter dans un circuit indépendant de la carte) et assez simple d'accès pour laisser un peu de place à la créativité.&lt;br /&gt;&lt;br /&gt;J'ai craqué et acheté le starter kit (carte + matos électronique de base) pour 50€, avec pour premier but de piloter un équivalent du nabaztag depuis mon portable. Ensuite je rajoute le streaming audio, la communication sans-fil, et.. qui sait ?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PureData et Liquidsoap&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;La communauté des bricoleurs sur Arduino semblent utiliser de temps en temps PureData, je me suis donc repenché un peu sur cet outil.&lt;br /&gt;&lt;blockquote&gt;PD (aka Pure Data) is a real-time graphical programming environment for audio, video, and graphical processing. It is the third major branch of the family of patcher programming languages [...]&lt;/blockquote&gt;&lt;br /&gt;Bon. Realtime, ça veut rien dire, tout est temps réel avec assez de puissance. J'arrive pas à comprendre ce qu'est Patcher, si c'est vraiment un langage ou une interface graphique. Je sais pas en quoi PD permet de manipuler audio, vidéo et images de façon plus intéressante que le C. Faudrait que j'essaie ça.&lt;br /&gt;&lt;br /&gt;Toujours est-il que PD a l'air très prisé pour réaliser des outils interactifs de synthèse et traitement audio. La question est: quelle différence avec Liquidsoap? Le but initial est différent, jusque là je ne me posais donc même pas la question. Mais après tout ce sont deux architectures assez génériques de traitement de son.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;La configuration de Liquidsoap n'est pas modifiable à la volée.&lt;/li&gt;&lt;li&gt;Liquidsoap n'a pas d'interface graphique pour composer son script.&lt;/li&gt;&lt;li&gt;Les possibilités d'interaction avec les sources sont limitées (interface telnet).&lt;/li&gt;&lt;li&gt;Liquidsoap a peu de fonctions de synthèse de son, pas de feedback.&lt;/li&gt;&lt;li&gt;On a pas d'entrée microphone stable.&lt;/li&gt;&lt;/ol&gt;Le premier point est délicat, c'est une modif non triviale que je ne ferais pas de sitôt, mais c'est faisable sans aucun doute. Les points 2-4 requierent encore pas mal de code mais aucune modif bien profonde, rien d'infaisable. Il faudrait bosser sur un protocole expressif et structuré pour interagir avec les sources -- à moins qu'on continue avec le telnet, la source mix() marche plutôt bien comme ça, pilotée depuis la GUI en python. Le point 5 requiert du code et du courage, j'ai aucune envie de me faire chier avec le hardware, mais c'est clairement faisable. Au final, j'ai envie de conclure qu'avec quelques contributeurs motivés pour pousser le projet dans cette direction, c'est faisable.&lt;br /&gt;&lt;br /&gt;Mais quel avantage par rapport aux projets existants? Un premier truc qui distingue Liquidsoap d'un paquet de toolkits est que sa notion de flux comporte un notion de piste, ce qui permet d'avoir des opérateurs qui opèrent au niveau de la piste (sélecteurs, transitions entre pistes, etc.). Sinon, l'archi est propre et robuste grâce au typage de Caml. Enfin, ça me semble pas mal d'avoir un démon et un langage de script sous l'interface graphique, même si du coup on a pas d'interface graphique dans un premier temps.&lt;br /&gt;&lt;br /&gt;J'en apprendrai peut-être plus aux &lt;a href="http://www.rmll.info/"&gt;Rencontres Mondiales du Logiciel Libre 2007&lt;/a&gt; cet été à Amiens. J'ai décidé d'y présenter Liquidsoap! Je guette l'appel à présentations pour le thème multimédia sur leur &lt;a href="http://www.rmll.info/news.rss"&gt;fil RSS&lt;/a&gt;. Pour l'instant seuls les thèmes Communautés et Embarqué ont été appelés: ordre de préférence, organisateurs plus rapides?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-3465308305200843383?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/3465308305200843383/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=3465308305200843383' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3465308305200843383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/3465308305200843383'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/01/art-technique.html' title='Art &amp; Technique'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-4815406669705237099</id><published>2007-01-21T03:03:00.000+01:00</published><updated>2007-01-21T03:09:24.630+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Browser shots</title><content type='html'>Un petit post pour noter une adresse bien utile: &lt;a href="http://browsershots.org"&gt;BrowserShots&lt;/a&gt;. Ce site gratuit permet d'obtenir des captures d'écran de plusieurs navigateurs sur la page de votre choix. Bien utile pour s'apercevoir que &lt;a href="http://browsershots.org/website/184245/#success"&gt;sa page&lt;/a&gt; n'est pas complètement portable malgré la validité du XHTML...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-4815406669705237099?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/4815406669705237099/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=4815406669705237099' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4815406669705237099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/4815406669705237099'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/01/browser-shots.html' title='Browser shots'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-700279029731558752</id><published>2007-01-02T10:44:00.000+01:00</published><updated>2007-01-02T10:52:14.861+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><category scheme='http://www.blogger.com/atom/ns#' term='general'/><category scheme='http://www.blogger.com/atom/ns#' term='geek'/><title type='text'>Bye bye 2006...</title><content type='html'>Bonne année 2007 à tous ! L'année 2006 aura été riche d'évenements, jusqu'au bout: &lt;a href="http://eucd.info/index.php?2006/12/31/341-publication-du-decret-relatif-au-contournement-d-une-mesure-technique-a-l-aide-d-outils-dedies"&gt;EUCD.info&lt;/a&gt; nous apprend en effet que le décret relatif au contournement d'une mesure technique a été publié le 30 Décembre.&lt;br /&gt;&lt;blockquote&gt;Avec la publication de ce décret la lecture d'un DVD avec un logiciel s'appuyant sur un moyen de contournement existant (comme DeCSS, utilisé par de très nombreux systèmes logiciels libres) est donc passible d'une contravention de 4ème classe. Ainsi donc lire un DVD, légalement acheté par exemple, sur un système d'exploitation libre devient un acte passible d'une amende.&lt;/blockquote&gt;&lt;br /&gt;Loin de pousser au boycott, je suis quand même content de n'avoir ni offert ni reçu de DVD ce Noël...&lt;br /&gt;&lt;br /&gt;Sinon, pour 2007, j'ai migré le blog sur le nouvelle version de Blogger, qui n'est plus en Beta. Je n'ai pas perdu mon modèle, et je vais essayer d'y ajouter l'affichage des catégories/libellés, tant attendues.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-700279029731558752?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/700279029731558752/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=700279029731558752' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/700279029731558752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/700279029731558752'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2007/01/bye-bye-2006.html' title='Bye bye 2006...'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116550674936627543</id><published>2006-12-07T16:48:00.000+01:00</published><updated>2006-12-07T16:58:28.956+01:00</updated><title type='text'>Paf!</title><content type='html'>Dans la série "les pièges de l'Internet", ne pas pomper bêtement les images des autres. Ou alors mieux vaut les copier sur son site que d'utiliser l'adresse originale. Vous ne voyez pas &lt;a href="http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&amp;friendid=50172192"&gt;pourquoi&lt;/a&gt; ? &lt;a href="http://blog.rastageeks.org"&gt;Toots&lt;/a&gt; a déplacé son &lt;a href="http://www.rastageeks.org/images/Screenshot.png"&gt;petit rasta&lt;/a&gt; réutilisé, et l'a remplacé par ... heu ... &lt;a href="http://www.rastageeks.org/images/screenshot.png"&gt;ça&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116550674936627543?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116550674936627543/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116550674936627543' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116550674936627543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116550674936627543'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/12/paf.html' title='Paf!'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116492165241896304</id><published>2006-12-01T18:19:00.000+01:00</published><updated>2006-12-01T18:42:21.730+01:00</updated><title type='text'>Debugging mémoire: quatre jours pour une ligne</title><content type='html'>Tout commence par un série de crashs de liquidsoap sur GeekRadio, causés par une pénurie de mémoire. Pendant quatre jours j'ai passé pas mal de temps à émettre des hypothèses, fausses pour la plupart, lire des analyses, mais surtout chercher des outils pour obtenir des analyses plus précises, pour finalement arriver à la fonction respondable et remarquer l'absence évidente d'une unique ligne de code.&lt;br /&gt;&lt;br /&gt;La recherche de techniques de debugging aurait du être plus simple, j'ajoute donc un peu d'information utile dans la soupe, au cas où ça peut aider quelqun un jour...&lt;br /&gt;&lt;br /&gt;Pour information liquidsoap est un logiciel de streaming audio programmé en OCaml, mais il utilise de nombreuses librairies interfaçant OCaml avec de fameuses librairies C comme Vorbis, Mad ou Shout. Dans un premier temps j'ai soupçonné un problème dans le tas Caml (les valeurs gérées par le &lt;em&gt;garbage collector&lt;/em&gt;) pour finir par comprendre que c'était une bête fuite de mémoire dans le tas C (géré par &lt;em&gt;malloc&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Ce n'est qu'à la fin de ce post que vient l'information la plus utile potentiellement. En effet j'y décris quelques techniques de débuguage avec le malloc &lt;em&gt;standard&lt;/em&gt; GNU, qui sont peu connues à mon avis mais très pratiques.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;exmap&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Je ne m'attarderai pas sur cet outil car il est compliqué à mettre en place, puisqu'il repose sur un module du noyau linux. Je soupçonne que la plupart de ce que j'ai appris par &lt;code&gt;gexmap&lt;/code&gt; était accessible dans &lt;code&gt;/proc/$PID/maps&lt;/code&gt; ou autre. En plus ça m'a induit en erreur. L'outil nous a indiqué que ce n'est pas le tas qui explosait (&lt;code&gt;[heap]&lt;/code&gt;) mais la mémoire anonyme (&lt;code&gt;[anon]&lt;/code&gt;), et nous avons cru qu'il s'agissait du tas Caml. En fait, j'ai &lt;a href="http://www.gnu.org/software/libc/manual/html_node/Efficiency-and-Malloc.html"&gt;appris&lt;/a&gt; plus tard que le &lt;code&gt;malloc()&lt;/code&gt; du GNU utilisait &lt;code&gt;mmap()&lt;/code&gt; pour les "grosses" allocations ("largement plus" d'une page, soit 4092 octets typiquement), et les régions &lt;code&gt;mmap()&lt;/code&gt;ées sont en fait ce qu'on appelle la mémoire &lt;code&gt;[anon]&lt;/code&gt;nyme.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;/proc/$PID/status&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Sous linux ce fichier contient une description de l'état d'un processus. Les champs qui nous intéressent sont: &lt;code&gt;VmSize&lt;/code&gt;, la totale de mémoire allouée au processus; et &lt;code&gt;VmRSS&lt;/code&gt;, l'espace actuellement occupé par le processus dans la mémoire physique. La première valeur peut excéder la quantité de mémoire disponible, la mémoire allouée mais non accédée n'a en effet pas besoin d'être effectivement présente physiquement.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/3187/1644/1600/296689/m.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/3187/1644/320/811451/m.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Mon erreur ici a été de tracer &lt;code&gt;VmRSS&lt;/code&gt;, je crois. On obtient un graphe qui grimpe doucement, se stabilise progressivement, puis explose subitement. Je me suis conforté dans l'idée d'un défaut dans le tas Caml en interprétant cela comme un dérapage du &lt;em&gt;garbage collector&lt;/em&gt; sur un tas corrompu. On s'aperçoit plus loin que le tas Caml n'a rien à voir là dedans, que le tas C croit progressivement sans raison. L'explosion du &lt;code&gt;VmRSS&lt;/code&gt; est peut être dû à un rapatriement en mémoire physique d'un paquet de pages dû à un passage du GC, je ne sais toujours pas vraiment.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ocaml-memprof&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Nous avons commencé par chercher un outil pour analyser le contenu du tas Caml. Quelques recherches m'ont mené à ce patch du compilateur initialement écrit par Fabrice Lefessant il y a bien longtemps, adapté et amélioré par &lt;em&gt;je-sais-pas-qui&lt;/em&gt; pour &lt;code&gt;ocaml-3.08.3&lt;/code&gt; depuis, et enfin mis-à-jour pour la version &lt;code&gt;3.09&lt;/code&gt; par Sam. Le patch se trouve donc maintenant &lt;a href="http://www.pps.jussieu.fr/~smimram/docs/ocaml-3.09.3-memprof.patch"&gt;ici&lt;/a&gt; et la doc &lt;a href="http://www.pps.jussieu.fr/~smimram/docs/README.memprof"&gt;là&lt;/a&gt;. Il y a peut-être encore quelques erreurs &lt;em&gt;unused variable&lt;/em&gt; simples à corriger. La vraie difficulté est de comprendre comment utiliser la bête, la doc n'étant que très minimale.&lt;br /&gt;&lt;br /&gt;D'abord, &lt;b&gt;cela ne marche que pour le code natif&lt;/b&gt;. C'est marqué dans le &lt;code&gt;README&lt;/code&gt;, mais il ne faut pas le rater car du &lt;em&gt;bytecode&lt;/em&gt; tournera sans problème, dumpera ses images du tas, mais l'analyseur plantera avec une erreur des moins explicites.&lt;br /&gt;&lt;br /&gt;Une fois le compilateur compilé, il faut l'installer. S'il n'est pas installé il ne trouvera pas ses librairies. Pour m'a part j'ai configuré avec &lt;code&gt;--prefix /home/dbaelde/local&lt;/code&gt;. Ensuite j'ai écrit une config alternative &lt;code&gt;~/local/ocamlfind.conf&lt;/code&gt;, car j'utilise ocamlfind pour compiler liquidsoap:&lt;br /&gt;&lt;div class="code"&gt;ocamlc="/home/dbaelde/local/bin/ocamlc.opt"&lt;br /&gt;stdlib="/home/dbaelde/local/lib/ocaml"&lt;br /&gt;destdir="/dev/null"&lt;br /&gt;path="/usr/lib/ocaml/3.09.2/METAS"&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Pour l'utiliser il suffit d'exporter les bonnes variables d'environnement:&lt;br /&gt;&lt;div class="code"&gt;export OCAMLFIND_CONF=~dbaelde/local/ocamlfind.conf&lt;br /&gt;export PATH=~dbaelde/local/bin:$PATH&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Avec ça la version patchée de caml sera détectée pour les projets n'utilisant pas ocamlfind (toutes les libs de savonet), et ocamlfind l'utilisera aussi (pour liquidsoap).&lt;br /&gt;&lt;br /&gt;Il ne reste qu'à lancer le programme Caml, qui fera appel régulièrement à &lt;code&gt;Gc.dump_heap&lt;/code&gt; pour écrire un image du tas Caml sur le disque. Attention à ce que l'utilisateur qui lance le programme ait les droits d'écriture dans le répertoire courant, sinon ça plante violemment. Attention aussi à ne pas trop dumper, ça prend de la place. On obtient normalement des fichiers &lt;code&gt;heap.dump.PID.N&lt;/code&gt;. On les compile en exécutant &lt;code&gt;heapstats -heaps PID&lt;/code&gt;. Et on trace un joli graphe de tout ça avec &lt;code&gt;hp2ps blocks_per_type.PID.hp&lt;/code&gt; et &lt;code&gt;hp2ps sizes_per_type.PID.hp&lt;/code&gt;. On obtient deux postscript avec les graphes de l'évolution du nombre et de la taille cumulée des valeurs Caml, classées par type.&lt;br /&gt;&lt;br /&gt;Pour liquidsoap, le graphe était très stable, aucune trace d'explosion.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/3187/1644/1600/765549/a.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/3187/1644/320/726919/a.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;GNU malloc&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;J'ai cherché des outils pointus pour avoir des statistiques sur l'allocation sur le tas C. J'ai trouvé des machins compliqués et d'autres qui ne marchent pas. Pour finalement me rendre compte que le malloc du GNU que j'utilisais déja avait tout ce qu'il me fallait!&lt;br /&gt;&lt;br /&gt;Pour les statistiques &lt;a href="http://www.gnu.org/software/libc/manual/html_node/Statistics-of-Malloc.html"&gt;mallinfo()&lt;/a&gt; donne plein d'information intéressante. La mémoire allouée au programme, la partie de cette mémoire qui est encore libre, la mémoire &lt;code&gt;mmap()&lt;/code&gt;ée, etc. Ca m'a permis de rayer l'hypothèse de la fragmentation mémoire: en fait GNU malloc se comporte bien malgré l'utilisation frénétique qu'on en fait dans les bindings de Shout et Vorbis. Pour la petite histoire j'ai appellé &lt;code&gt;mallinfo()&lt;/code&gt; depuis gcc, à l'aveuglette. Les champs de la structure &lt;code&gt;mallinfo&lt;/code&gt; sont documentés dans &lt;code&gt;/usr/include/malloc.h&lt;/code&gt;, ce sont tous des &lt;code&gt;int&lt;/code&gt;, on peut donc y accéder sur une archi 32bits comme suit:&lt;br /&gt;&lt;div class="code"&gt;call mallinfo()&lt;br /&gt;x/1dw $1       # Total space allocated from system&lt;br /&gt;x/1dw ($1+16)  # Mmap()ed space&lt;br /&gt;x/1dw ($1+28)  # Total allocated&lt;br /&gt;x/1dw ($1+32)  # Total free&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Autant dire qu'à ce stade d'emmerdements je me sentais mériter d'en finir vite.&lt;br /&gt;&lt;br /&gt;Mais la réponse est venue d'une analyse plus fine des allocations, permettant de remonter assez efficacement les fuites, toujours avec le GNU malloc standard. La fonction &lt;a href="http://www.gnu.org/software/libc/manual/html_node/Allocation-Debugging.html"&gt;mtrace()&lt;/a&gt; permet en effet de stocker dans un fichier une trace de toutes les opérations mémoire effectuées. Un appel suffit et provoque l'ouverture du fichier indiqué dans la variable d'environnement &lt;code&gt;MALLOC_TRACE&lt;/code&gt;, qui est mis à jour à chaque opération. Il prend rapidement beaucoup de place, attention donc.&lt;br /&gt;&lt;br /&gt;Ensuite le programme &lt;code&gt;mtrace&lt;/code&gt; analyse tout cela, et affiche à la fin les blocs non libérés. Si on lui donne le binaire responsable de la trace, compilé avec &lt;code&gt;-g&lt;/code&gt; il associe un numéro de ligne aux allocations, ce qui permet de remonter aux allocations non nettoyées. Dans liquidsoap j'ai ainsi vu que de trop nombreux descripteurs de décodeurs Vorbis étaient alloués, alors que deux tout au plus devraient pouvoir exister à un instant donné. L'info était en fait même un peu plus précise que ça, en tout cas ça a permis d'en finir avec toutes ces histoires!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116492165241896304?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116492165241896304/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116492165241896304' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116492165241896304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116492165241896304'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/12/debugging-mmoire-quatre-jours-pour-une.html' title='Debugging mémoire: quatre jours pour une ligne'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116445779700428374</id><published>2006-11-25T13:28:00.000+01:00</published><updated>2006-11-25T13:29:57.016+01:00</updated><title type='text'>Pâques en avance..</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/3187/1644/1600/23833/carte-paques.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/x/blogger/3187/1644/320/574699/carte-paques.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Merci Ameline...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116445779700428374?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116445779700428374/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116445779700428374' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116445779700428374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116445779700428374'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/pques-en-avance.html' title='Pâques en avance..'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116429000553933546</id><published>2006-11-23T14:21:00.000+01:00</published><updated>2006-11-23T14:54:18.343+01:00</updated><title type='text'>Doutes et dégouts</title><content type='html'>En ce moment à l'école, des affiches JP Morgan fleurissent. Après les avoir longtemps ignorées, je me suis laissé intriguer et ai lu le message: "Tu vas kiffer spéculer pour nous, tu ne penseras plus qu'à ça, t'en auras les mains qui tremblent. On a un sacré gros paquet de fric à jouer, mais souviens-toi, c'est qu'un jeu, pas vrai ?" Tant d'idéaux m'ont subjugué, j'ai embarqué l'affiche, direction poubelle. A la même époque l'an dernier j'ai déja écrit mon incompréhension et mon rejet des boîtes de finance. Je ne les comprends pas plus qu'avant, je ne les accepte pas plus non plus, ma seule pensée nouvelle est un souvenir de ce que ma maman me disait: &lt;em&gt;On ne joue pas avec la nourriture, pense à ceux qui ont faim&lt;/em&gt;...&lt;br /&gt;&lt;br /&gt;Je ne comprends pas plus qu'avant. Est-ce bien ou mal&amp;nbsp;? &amp;Ccedil;a me parait injuste, mais il n'y a rien d'illégal, pas de vol. Tout le monde consent à rentrer dans ce petit jeu. Pourtant il doit bien y avoir des perdants. Et je ne vois pas qui peut profiter de la spéculation rapide, si ce n'est les spéculateurs. Est-ce mieux de se faire payer à &lt;strike&gt;bloguer et geeker&lt;/strike&gt; faire de la recherche fondamentale en logique&amp;nbsp;? C'est quand même un investissement à plus long terme, ça a plus de chances de profiter...&lt;br /&gt;&lt;br /&gt;Après la seconde guerre mondiale il était établi que tout valait mieux que cette horreur, et un certain nombre de gens ont commencé à construire notre monde, autour du capitalisme, du commerce, de la finance. Certains pays en souffrent, en sont apauvris, mais cela vaut mieux que des guerres et des massacres, non&amp;nbsp;? J'ai tendance à dire oui, aussi, mais je ne m'étonnerai pas quand les pauvres changeront d'avis si le monde ne change pas assez bien.&lt;br /&gt;&lt;br /&gt;Dans ces domaines j'ai des sentiments, mais pas de certitudes, et je ne comprends pas les gens qui en ont.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116429000553933546?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116429000553933546/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116429000553933546' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116429000553933546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116429000553933546'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/doutes-et-dgouts.html' title='Doutes et dégouts'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116428792406039778</id><published>2006-11-23T14:02:00.000+01:00</published><updated>2006-11-23T14:20:22.816+01:00</updated><title type='text'>Qu'est ce qu'un Geek ?</title><content type='html'>Comme &lt;a href="http://gelnior.free.fr/dotclear/index.php/2006/11/19/112-la-revancha-del-geeko"&gt;Gelnior&lt;/a&gt; ou &lt;a href="http://www.ecrans.fr/spip.php?article490"&gt;ecrans.fr&lt;/a&gt; le font remarquer, le &lt;em&gt;geek&lt;/em&gt; est à la mode. Je porte pour ma part un tee-shirt &lt;em&gt;#geek&lt;/em&gt; de temps à autres mais je n'ai pas l'impression d'être à la mode pour autant: il me semble que le mot change de sens, encore.&lt;br /&gt;&lt;br /&gt;Un petit coup d'oeil dans &lt;a href="http://www.urbandictionary.com/define.php?term=geek"&gt;urbandictionary&lt;/a&gt; confirme la définition que je connaissais il y a quelques années. Le sens premier désigne des gens décalés qui font un boulot ou se passionnent pour un sujet que le commun des mortels trouve bizarre. Le mot est cependant particulièrement utilisé chez les programmeurs, qui sont bien souvent des &lt;em&gt;geeks&lt;/em&gt; par excellence au sens premier du terme. &lt;em&gt;Geek&lt;/em&gt; est aussi un synonyme de &lt;em&gt;nerd&lt;/em&gt; mais ce dernier terme est plutôt utilisé péjorativement, tandis que le premier est employé comme un terme positif par ceux qui se considèrent &lt;em&gt;geeks&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Actuellement une autre forme de &lt;em&gt;geeks&lt;/em&gt; est en train de s'accaparer l'appellation: l'ultra-fan de BD/science-fiction/jeu-vidéo, le mec qui passe aimerait avoir un sabre laser ou des pouvoirs psychiques. Bien souvent il aura aussi la tête fourrée dans son écran d'ordinateur, discutant avec ses compères sur forums ou échangeant des jeux/figurines/BD-collectors, mais il ne s'agit en aucun cas d'un codeur.&lt;br /&gt;&lt;br /&gt;Conclusion ? Etre un codeur n'est toujours pas à la mode, et donc &lt;em&gt;vraiment geek&lt;/em&gt;. On est des larves obnubilées par des systèmes austères, mais on va pas se laisser piquer nos appellations, bordel!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116428792406039778?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116428792406039778/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116428792406039778' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116428792406039778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116428792406039778'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/quest-ce-quun-geek.html' title='Qu&apos;est ce qu&apos;un Geek ?'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116199716117863710</id><published>2006-11-12T02:56:00.000+01:00</published><updated>2007-08-24T04:27:16.300+02:00</updated><title type='text'>Debian on Dell D420 laptop</title><content type='html'>I recently got a new laptop from the lab. It's a Dell D420, and it came with a Dell flat panel 20" WXGA UltraSharp. Bored with Gentoo, I decided to install a Debian on it.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;The Debian CD I had was too old and didn't detect the wifi card, which is bad for a netinstall. So I booted a Ubuntu CD, and everything was detected. But I still wanted a Debian. So I followed &lt;a href="http://www.debian.org/releases/stable/i386/apcs04.html.fr"&gt;this guide&lt;/a&gt; to install Debian from the LiveCD. That made the move from Gentoo less sad, looked familiar...&lt;br /&gt;&lt;br /&gt;Although I didn't do an usual install, the next steps might be valuable for others, or me later. I installed Debian etch, got a kernel 2.6.17.&lt;br /&gt;&lt;br /&gt;Nothing to say about &lt;b&gt;wired network&lt;/b&gt;. It worked out of the box.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sound&lt;/b&gt; worked fine as soon as I installed and &lt;b&gt;dpkg-reconfigure&lt;/b&gt;d &lt;b&gt;alsa-base&lt;/b&gt;, ran &lt;b&gt;alsaconf&lt;/b&gt;. Related useful packages here were &lt;b&gt;alsa-tools&lt;/b&gt; and &lt;b&gt;vorbis-tools&lt;/b&gt;. But I guess this is useless for a normal Debian install.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Video&lt;/b&gt; was a bit tricky. The video BIOS is broken on these machines. Just install &lt;b&gt;915resolution&lt;/b&gt; and reboot. This tools detects the actual screen resolution at startup and patches the BIOS so that X detects it fine. Problems arise when you plug the external screen: its  resolution isn't detected either. The solution I found, which works with or without the external screen, is a bit dirty. Just add the following line at the end of &lt;code&gt;/etc/defaults/915resolution&lt;/code&gt;: &lt;code&gt;915resolution 54 1680 1050&lt;/code&gt; -- assuming you've got a 1680x1050 external screen.&lt;br /&gt;&lt;br /&gt;One trouble with wide screens is that mplayer will stretch the videos. To fix this, edit &lt;code&gt;/etc/mplayer/mplayer.conf&lt;/code&gt; to set &lt;code&gt;monitoraspect=16:10&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;wifi&lt;/b&gt; is the hardest bit. First it depends on whether or not you have a dual core. With a single core you usually get a Broadcom card which requires ndiswrapper.. see other install-notes for that. With a dual core you can't get this card, and you usually get an Intel Pro Wireless: ipw3945. Unfortunately the driver is not free. I followed &lt;a href="http://javier.rodriguez.org.mx/index.php/linux/debian-gnulinux-on-dell-d620/"&gt;these notes&lt;/a&gt; for the installation of the &lt;code&gt;ipw3945&lt;/code&gt; module and &lt;code&gt;ipw3945d&lt;/code&gt; daemon, including the edition of &lt;code&gt;/etc/modprobe.d/ipw3945&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The problem, then, is that when the module is launched during boot, these magic lines are not used, so the daemon isn't started, and the wireless doesn't work. What I did is add a service to reload the module, and wait a bit for the server to initialize correctly. Edit &lt;code&gt;/etc/init.d/ipw3945&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;#! /bin/sh&lt;br /&gt;&lt;br /&gt;set -e&lt;br /&gt;&lt;br /&gt;PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin&lt;br /&gt;DESC="Intel PRO/Wireless 3945"&lt;br /&gt;NAME=ipw3945&lt;br /&gt;SCRIPTNAME=/etc/init.d/$NAME&lt;br /&gt;&lt;br /&gt;# Exit if not root&lt;br /&gt;if [ $(id -u) -gt 0 ]&lt;br /&gt;then&lt;br /&gt;        echo "This script must be run as root."&lt;br /&gt;        exit 99&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;# Gracefully exit if the package has been removed.&lt;br /&gt;test -x $SCRIPTNAME || exit 0&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;  start|restart)&lt;br /&gt;        echo -n "Starting $DESC: $NAME"&lt;br /&gt;        rmmod ipw3945&lt;br /&gt;        modprobe ipw3945&lt;br /&gt;        sleep 3&lt;br /&gt;        echo "."&lt;br /&gt;        ;;&lt;br /&gt;  stop)&lt;br /&gt;        echo "Stopping $DESC: $NAME"&lt;br /&gt;        ;;&lt;br /&gt;  *)&lt;br /&gt;        echo "Usage: $SCRIPTNAME {start|stop|restart}" &amp;gt;&amp;2&lt;br /&gt;        exit 1&lt;br /&gt;        ;;&lt;br /&gt;esac&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then add a link so that it starts before networking: &lt;code&gt;ln -s /etc/init.d/ipw3945 /etc/rcS.d/S38ipw3945&lt;/code&gt;. Configure &lt;code&gt;eth2&lt;/code&gt;, reboot, that's ready.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116199716117863710?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116199716117863710/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116199716117863710' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116199716117863710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116199716117863710'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/debian-on-dell-d420-laptop.html' title='Debian on Dell D420 laptop'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116301890402202414</id><published>2006-11-08T21:39:00.000+01:00</published><updated>2006-11-09T17:34:26.920+01:00</updated><title type='text'>Pierre blanche</title><content type='html'>Un jour à marquer d'une pierre blanche. Je suis en train de gagner ce qui est probablement la dernière bataille de la campagne dans &lt;em&gt;Advance Wars&lt;/em&gt;. J'ai fixé un défaut de récursion terminale dans le code de &lt;em&gt;Bedwyr&lt;/em&gt;, ce qui nous a enfin permis de calculer notre exemple le plus complexe. Le boulot théorique avance moins mais n'est pas tout à fait au point mort. Mais surtout...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/index-graph.php.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/index-graph.php.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;J'ai proposé une depêche linuxfr centrée sur &lt;a href="http://savonet.sf.net/wiki/Liquidsoap"&gt;Liquidsoap&lt;/a&gt;, présentant &lt;a href="http://dolebrai.net"&gt;Dolebraï&lt;/a&gt; et &lt;a href="http://www.radiopi.org"&gt;RadioPi&lt;/a&gt;. Elle est passée &lt;a href="http://linuxfr.org/2006/11/08/21594.html"&gt;en première page&lt;/a&gt; en début d'après-midi, causant un afflux de visiteurs pour les trois projets.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit:&lt;/b&gt; &lt;em&gt;geotraffic&lt;/em&gt; très français sur le wiki de Savonet pendant les 24 heures qui ont suivi le post...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/fr.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/fr.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116301890402202414?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116301890402202414/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116301890402202414' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116301890402202414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116301890402202414'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/pierre-blanche.html' title='Pierre blanche'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116237861122079565</id><published>2006-11-01T11:48:00.000+01:00</published><updated>2006-11-01T19:31:15.556+01:00</updated><title type='text'>Photos d'Australie</title><content type='html'>J'ai enfin uploadé &lt;a href="http://www.flickr.com/photos/deuxpingouins/sets/72157594355237127/"&gt;mes photos d'Australie&lt;/a&gt; sur Flickr. Vous y trouverez des morceaux de Canberra, en particulier les photos de ma chasse aux kangourous.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img style="width:100%" alt="kangourous" src="http://static.flickr.com/102/285577356_af4a044970.jpg?v=0" /&gt;&lt;/center&gt;&lt;br /&gt;Mais la plupart des images sont celles de mon dernier week-end, passé à Sydney: ville, plage, jungle, il y a de tout.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img style="width:100%" alt="opera&amp;sydney" src="http://static.flickr.com/104/285576927_bfd9e0b17d.jpg?v=0" /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116237861122079565?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116237861122079565/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116237861122079565' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116237861122079565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116237861122079565'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/11/photos-daustralie.html' title='Photos d&apos;Australie'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116142486252424691</id><published>2006-10-21T11:36:00.000+02:00</published><updated>2006-10-21T12:03:49.483+02:00</updated><title type='text'>Solutions pour la France</title><content type='html'>Hier j'ai été au ciné avec Estelle. On a vu &lt;em&gt;Little Miss Sunshine&lt;/em&gt; que je recommande très fort. C'est beau et drôle, un peu dans le genre du &lt;em&gt;C.R.A.Z.Y&lt;/em&gt;, très bon aussi mais plus à l'affiche. La première pub m'a fait un choc: crainte, puis grand éclat de rire. Je vous laisse juger...&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="335"&gt;&lt;param name="movie" value="http://www.dailymotion.com/swf/7o3q0TZQFvenI3lYL" /&gt;&lt;embed width="425" height="334" src="http://www.dailymotion.com/swf/7o3q0TZQFvenI3lYL" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Pour ceux qui n'ont pas vu les clips UMP &lt;em&gt;starring Sarkozy&lt;/em&gt;, je vous laisse chercher. Même format &lt;em&gt;pub&lt;/em&gt;, même discours qu'IKEA sur la France, mais le mouvement populiste propose clairement moins de solutions. Pour une France heureuse et dynamique, ne vous trompez pas, votez IKEA.&lt;br /&gt;&lt;br /&gt;Au passage on remarquera que les divers clips de l'UMP qu'on peut trouver sur Google Video sont postés fréquemment, ils datent de moins de 5 minutes à l'heure actuelle. L'équipe comm' du parti ne chôme pas, et profite bien des faiblesses de ces systèmes de publication.&lt;br /&gt;&lt;br /&gt;J'ai observé le même phénomène sur &lt;a href="http://swik.net"&gt;swik&lt;/a&gt;. Il s'agit d'un site qui répertorie des projets open-source, où chacun peut ajouter un projet. J'ai ajouté &lt;a href="http://swik.net/liquidsoap"&gt;Liquidsoap&lt;/a&gt; en passant, puis constaté avec plaisir qu'il s'afficherait pendant quelques temps en tête de liste sur la page d'accueil, dans la liste des nouveaux projets. Ensuite je remarque que comme par hasard, plusieurs projets connus sont aussi dans cette liste: VLC, Muse, Dynebolic... J'ai vérifié, ces projets sont re-postés sur le site chaque jour. Je ne sais pas qui a commencé cette petite guerre, mais cela pourrit complètement le principe de ce genre de site.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116142486252424691?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116142486252424691/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116142486252424691' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116142486252424691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116142486252424691'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/10/solutions-pour-la-france.html' title='Solutions pour la France'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-116124838042379257</id><published>2006-10-19T09:37:00.000+02:00</published><updated>2006-10-19T18:31:09.496+02:00</updated><title type='text'>Langages</title><content type='html'>Il y a quelques semaines je tombais sur un os en Javascript, et je postais &lt;a href="http://misterpingouin.blogspot.com/2006/09/portes-de-variables.html"&gt;ici-même&lt;/a&gt; mon étonnement et ma déception. J'en ai depuis appris un peu plus, et en ai surtout discuté avec mon père, et sur &lt;a href="http://lambda-the-ultimate.org/node/1775"&gt;LtU&lt;/a&gt; où j'essaie de justifier ma déception... Tout cela appelle à une longue suite, sur JavaScript en particulier et les langages de programmation en général.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Tout d'abord un exemple plus simple révélant le problème dans son ensemble avec Javascript:&lt;br /&gt;&lt;div class="code"&gt;var a = 0;&lt;br /&gt;function f() {&lt;br /&gt;  // La variable locale "a"&lt;br /&gt;  // est déclarée pour le corps de la fonction,&lt;br /&gt;  // dès lors qu'une déclaration de "a" a lieu où&lt;br /&gt;  // que ce soit dans la fonction, 5 lignes plus bas ici.&lt;br /&gt;  a = 1 ;&lt;br /&gt;  // Ce n'est donc pas le "a" global qui a été modifié ici.&lt;br /&gt;  // Mais pour le savoir il faut lire deux lignes plus bas.&lt;br /&gt;  if (false) {&lt;br /&gt;    var a = 2 ;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;// Ici, "a" vaut toujours 0.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Les concepteurs de JavaScript avaient des priorités et ont préféré ne pas s'embêter avec des portées plus fines que la fonction. C'est un choix qui a aussi été fait dans les premières standardisations du C, mais dans ce cas la déclaration d'une variable ailleurs qu'en début de fonction est tout bonnement interdite, rejetée à la compilation. Dans des versions récentes du C, en C++ ou Java, les déclarations de variable sont autorisées n'importe où et leur portée est restreinte au bloc englobant. En OCaml ou SML, la déclaration de variable &lt;code&gt;let VAR = EXPR in BODY&lt;/code&gt; forme un bloc à elle seule, et la portée de &lt;code&gt;VAR&lt;/code&gt; est restreinte à &lt;code&gt;BODY&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;En gros, j'ai commencer à coder en C, puis ai passé des années avec OCaml. Dans les deux cas j'ai été habituée à des portées de bloc. Avec OCaml on en fait un usage intensif, par exemple en émulant les variables &lt;code&gt;static&lt;/code&gt; de C en déclarant une variable locale visible uniquement depuis une certaine fonction:&lt;br /&gt;&lt;div class="code"&gt;let compteur =&lt;br /&gt;  let n = ref 0 in&lt;br /&gt;    fun () -&gt; incr n ; !n&lt;br /&gt;(* "n" invisible après la définition de "compteur" *)&lt;/div&gt;&lt;br /&gt;J'ai aussi passé un été à programmer en &lt;a href="http://en.wikipedia.org/wiki/Emacs_Lisp"&gt;Emacs Lisp&lt;/a&gt;. Dans ce langage la liaison des variables est &lt;em&gt;dynamique&lt;/em&gt;. Cela signifie que si une fonction fait référence à une variable &lt;code&gt;n&lt;/code&gt;, elle fait référence à la variable &lt;code&gt;n&lt;/code&gt; dans le contexte de son exécution (dynamique) et non pas dans le contexte de sa définition (statique). Cela permet certains bricolages mais la plupart du temps cela amène à de mauvaises surprises. Avec l'habitude on évite les mauvaises surprises en évitant de construire des fonctions dans un contexte pour les exécuter dans un autre (c'est dommage), ou on force l'évaluation des variables en question lors de la construction de la fonction (c'est pénible).&lt;br /&gt;&lt;br /&gt;De temps en temps j'ai été amené à pratiquer JavaScript, car il n'y a pas le choix pour scripter côté client sur le web. Il m'a aussi parfois été utile d'utiliser Python, pour développer rapidement un petit outil grâce aux innombrables librairies disponibles. Dans les deux cas j'ai été heureux de constater que les fonctions sont des valeurs comme les autres et que la liaison des variables est statique -- on dit aussi que la portée est statique/lexicale. Je me suis réjoui à l'idée que les langages de script se modernisaient, et que j'allais pouvoir m'exprimer librement et richement. J'ai dit autour de moi que JavaScript c'est bien. Et je connais un mec qui utilise JavaScript comme son langage de tous les jours, et qui a voulu participer au concours de prog de l'ICFP avec, parce que en gros c'est statique, propre, fonctionnel.&lt;br /&gt;&lt;br /&gt;Eh bien aujourd'hui je modère ce jugement. JavaScript n'est pas si riche, il ne me plait pas tant que ça. Et en plus il autorise des déclarations de variable n'importe où, ce qui induit en erreur les habitués d'autres langages -- et nous sommes nombreux.&lt;br /&gt;&lt;br /&gt;Pourquoi poster ce genre de notes ? J'espère sensibiliser autour de moi ceux qui ne le sont pas encore: Il y a de nombreuses subtilités dans la conception d'un langage, et les langages les plus populaires ne sont pas ceux qui ont résolu ces subtilités au mieux. Sur la question de la portée des variables, de nombreux langages offrent une portée statique, plus expressive et moins surprenante d'utilisation. D'un point de vue technique c'est donc possible, et depuis longtemps. Le léger coût que cela a me semble être le genre de chose qu'on oublie volontiers aujourd'hui, dans la mouvance des langages haut-niveau. Le typage est une autre caractéristique importante des langages, et beaucoup de gens n'ont pas idée de ce qui est possible, par exemple en Caml où le typage est statique mais toujours inféré et généralisé automatiquement -- cf mon &lt;a href="http://misterpingouin.blogspot.com/2006/09/strong-typing-doesnt-have-to-suck.html"&gt;post récent&lt;/a&gt;. Tant que de nouveaux langages, au demeurant attractifs et aux nombreuses qualités, seront développés en ignorant/rejettant ces solutions, elles resteront méconnues. C'est dommage, car les développeurs passent à côté d'une sémantique plus claire, de plus d'erreurs détectées automatiquement dès la compilation, et d'une exécution plus rapide. A défaut de créer moi-même un langage simple et riche, j'aimerais essayer de pousser les autres à aller dans cette direction, dans la mesure de mes possibilités très limitées.&lt;br /&gt;&lt;br /&gt;Je conclus sur l'exemple du compteur en Javascript, qu'il nous faut modifier ainsi:&lt;br /&gt;&lt;div class="code"&gt;function cree_compteur() {&lt;br /&gt;  var n = 0 ;&lt;br /&gt;  return (function () { return ++n }) ;&lt;br /&gt;}&lt;br /&gt;var compteur = cree_compteur() ;&lt;/div&gt;&lt;br /&gt;C'est pas si dur, mais il vaut mieux le savoir. Fini pour aujourd'hui, je ne traite pas de l'absence de portée de bloc en Python...&lt;br /&gt;&lt;br /&gt;PS: J'oubliais de pointer la &lt;a href="http://developer.mozilla.org/es4/proposals/block_expressions.html"&gt;proposition&lt;/a&gt; d'ajouter à JavaScript 2 un nouvel opérateur de déclaration de variables à la portée plus stricte. Pour des raisons de compatibilité, le nouveau &lt;code&gt;let&lt;/code&gt; ne remplacera pas l'ancien &lt;code&gt;var&lt;/code&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-116124838042379257?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/116124838042379257/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=116124838042379257' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116124838042379257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/116124838042379257'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/10/langages.html' title='Langages'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115916595974579112</id><published>2006-09-25T08:14:00.000+02:00</published><updated>2006-09-25T08:32:39.760+02:00</updated><title type='text'>69j 04h 09m 09s</title><content type='html'>Je me suis dit que 69 jours était un uptime satisfaisant pour relancer &lt;a href="http://dolebrai.net"&gt;Dolebraï&lt;/a&gt; après quelques modifications mineures dans le traitement des metadatas et la description du flux auprès d'icecast.&lt;br /&gt;&lt;br /&gt;Le développement de liquidsoap n'a pas avancé depuis des semaines, autant du côté des bugfixes que des nouvelles features qu'on a en tête. J'ai tenté d'attirer de nouveaux utilisateurs sur notre nouvelle release, mais malgré quelques pics de traffic/downloads je crois que c'est plutôt un échec.  Trop compliqué pour les besoins simples de la plupart des gens? Ou alors faut attendre, on est pas pressé..&lt;br /&gt;&lt;br /&gt;Mes annonces sur &lt;a href="http://caml.inria.fr/pub/ml-archives/caml-list/2006/08/42f2f7db21eb311e39c063a16fa3f6c3.en.html"&gt;la Caml-list&lt;/a&gt;, la liste &lt;a href="http://www.nabble.com/-ANN--Liquidsoap-0.3.0-tf2289188.html"&gt;Icecast&lt;/a&gt; (mais on n'est toujours pas dans la liste des &lt;a href="http://icecast.org/3rdparty.php"&gt;clients&lt;/a&gt;), et &lt;a href="http://freshmeat.net/projects/liquidsoap"&gt;Freshmeat&lt;/a&gt;. Visiblement ça s'est répercuté sur un truc inconnu, &lt;a href="http://linux.softpedia.com/get/Multimedia/Audio/Liquidsoap-16858.shtml"&gt;Softpedia/Linux&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115916595974579112?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115916595974579112/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115916595974579112' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115916595974579112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115916595974579112'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/69j-04h-09m-09s.html' title='69j 04h 09m 09s'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115865575177280384</id><published>2006-09-19T10:48:00.000+02:00</published><updated>2006-09-20T02:27:44.196+02:00</updated><title type='text'>Générateurs</title><content type='html'>&amp;Ccedil;a faisait longtemps que je voulais m'essayer à &lt;code&gt;camlp4&lt;/code&gt;, je me suis donné pour exercice d'implémenter des générateurs à la Python -- ce n'est pas nouveau, il me semble avoir déja vu passer ça sur la liste Caml. Le résultat final fait plaisir.&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;let c = mkseq [-102;1;5;10;33;42;77] ;;&lt;br /&gt;let s = mkseq [1;0;-1] ;;&lt;br /&gt;&lt;br /&gt;list_of s*x for x in c if x#even for s in s ;;&lt;br /&gt;= [-42;0;42;-10;0;10;102;0;-102]&lt;br /&gt;list_of x*s for s in s for x in c if x#even ;;&lt;br /&gt;= [-42;-10;102;0;0;0;42;10;-102]&lt;br /&gt;table_of (x,x#even) for x in c ;;&lt;br /&gt;= {77:false;42:true;33:false;10:true;&lt;br /&gt;   5:false;1:false;-102:true}&lt;br /&gt;&lt;br /&gt;are_all x#even for x in c ;;&lt;br /&gt;= false&lt;br /&gt;is_any  s#null for s in s ;;&lt;br /&gt;= true&lt;br /&gt;max_of  x#abs for x in c if x#even) ;;&lt;br /&gt;= 102&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Comme vous pouvez le voir j'ai orienté objet, car c'est un aspect de  Caml que j'essaie d'explorer plus à fond ces temps-ci.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Venons en directement aux conclusions avant de passer aux morceaux de code:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Camlp4 c'est puissant, mais faut tâtonner pour s'en sortir au début, avec un oeil sur &lt;a href="http://caml.inria.fr/pub/docs/tutorial-camlp4/index.html"&gt;le manuel&lt;/a&gt;. De façon générale je suis sympathique à l'idée d'un préprocesseur qui s'assume en tant qu'outil de meta-programmation, plutôt que des capacités vicieuses d'introspection.&lt;/li&gt;&lt;li&gt;Les générateurs sont facilement réalisés comme un sucre syntaxique à base de &lt;code&gt;fold&lt;/code&gt;. Je ne sais pas pourquoi Python utilise des itérateurs/coroutines, &lt;code&gt;yield&lt;/code&gt; &amp;amp; co., peut-être parce que l'utilisation de clôtures n'y est pas efficace. En Caml je ne vois aucun problème à mon approche, rien qui justifierait l'ajout du concept de coroutine ici. J'aime à voir ici une réponse à un post de Guido où il annonce la suppression de &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;iter&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt; (le &lt;code&gt;fold&lt;/code&gt; de Python) et &lt;code&gt;lambda&lt;/code&gt;: pour lui &lt;code&gt;reduce&lt;/code&gt; est incompréhensible et inutile, pour moi c'est habituel et fondamental. Là où Guido marque un point c'est qu'ayant cette syntaxe naturelle, je ne suis pas sûr de vouloir utiliser &lt;code&gt;map&lt;/code&gt; ou &lt;code&gt;iter&lt;/code&gt; directement si j'ai le sucre syntaxique à disposition.&lt;/li&gt;&lt;li&gt;Je suis fan du sous-typage structurel pour les objets dans Caml, mais l'inférence échoue et renvoie des erreurs cryptiques. C'est loin d'être intuitif et j'ai dû sévèrement annoter mes méthodes. C'est encore pire si on essaie d'exprimer le schéma &lt;code&gt;[.. for x in ..]&lt;/code&gt; comme une fonction. Il faut alors spécifier le type des objets itérables et générables, et effectuer des coercions explicites vers ces types, ce qui est piégeux à cause de la récursivité du type.&lt;/li&gt;&lt;li&gt;Les listes et autres types de base en OO, c'est moche, surtout quand on imagine ces valeurs omniprésentes se trimballer leur collection de méthodes triviales tout du long.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Pour vous avouer le fond de ma pensée, j'aimerais trouver/écrire un langage de script (au sens de la facilité d'utilisation, pas de l'absence de compilation) typé statiquement avec sous-typage structurel pour des objets et des variants polymorphes à la OCaml, avec une bonne inférence qui rende le tout utilisable par Monsieur Toulmonde. J'aimerais voir ce genre de concept se répandre. Je me doute que le problème de l'inférence n'est pas simple, j'essaierai d'étudier ça de plus près à l'occasion.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Le code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Mon fichier ML définit quelques classes qui pourraient faire partie de la lib standard OO s'il y en avait une -- même si ça fait peur, disons qu'on imagine. &amp;Agrave; la fin, j'y utilise la notation que je ne définis que plus bas, mais c'est pour présenter le type des méthodes &lt;br /&gt;&lt;code&gt;fold&lt;/code&gt;. La longueur vient uniquement du choix OO, et du fait que je définis plusieurs&lt;br /&gt;itérateurs (&lt;code&gt;seq&lt;/code&gt; et &lt;code&gt;table&lt;/code&gt;) et générateurs (&lt;code&gt;seq&lt;/code&gt;, &lt;code&gt;table&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;conjunction&lt;/code&gt; et &lt;code&gt;disjunction&lt;/code&gt; mais pas &lt;code&gt;iter&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;(* Fichier geno.ml *)&lt;br /&gt;&lt;br /&gt;class boolean (b:bool) =&lt;br /&gt;object&lt;br /&gt;  method in_val = b&lt;br /&gt;  method to_s = if b then "true" else "false"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class conjunction (b:bool) =&lt;br /&gt;object&lt;br /&gt;  inherit boolean b&lt;br /&gt;  method add (x:boolean) = new conjunction (x#in_val &amp;amp;&amp;amp; b)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class disjunction (b:bool) =&lt;br /&gt;object&lt;br /&gt;  inherit boolean b&lt;br /&gt;  method add (x:boolean) = new disjunction (x#in_val || b)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class integer (i:int) =&lt;br /&gt;object&lt;br /&gt;  method in_val = i&lt;br /&gt;  method to_s = string_of_int i&lt;br /&gt;  method times (y:integer) = new integer (i*y#in_val)&lt;br /&gt;  method abs = new integer (abs i)&lt;br /&gt;  method null = new boolean (i = 0)&lt;br /&gt;  method even = new boolean (i mod 2 = 0)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class max (i:int) =&lt;br /&gt;object&lt;br /&gt;  inherit integer i&lt;br /&gt;  method add (x:integer) = new max (max i x#in_val)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class ['a] seq (l:'a list) =&lt;br /&gt;object&lt;br /&gt;  method add x : 'a seq = new seq (x::l)&lt;br /&gt;  method fold : 'b. 'b -&amp;gt; ('b -&amp;gt; 'a -&amp;gt; 'b) -&amp;gt; 'b =&lt;br /&gt;    fun x0 f -&amp;gt; List.fold_left f x0 l&lt;br /&gt;  method to_s =&lt;br /&gt;    "[" ^ (String.concat ";" (List.map (fun s -&amp;gt; s#to_s) l)) ^ "]"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class ['k,'v] table (l:('k*'v)list) =&lt;br /&gt;object&lt;br /&gt;  method add x : ('k,'v) table = new table (x::l)&lt;br /&gt;  method get k = List.assoc k l&lt;br /&gt;  method fold : 'b. 'b -&amp;gt; ('b -&amp;gt; 'k -&amp;gt; 'b) -&amp;gt; 'b =&lt;br /&gt;    fun x0 f -&amp;gt; List.fold_left (fun acc (k,v) -&amp;gt; f acc k) x0 l&lt;br /&gt;  method to_s =&lt;br /&gt;    "{" ^&lt;br /&gt;    (String.concat ";" (List.map (fun (k,v) -&amp;gt; k#to_s^":"^v#to_s) l)) ^&lt;br /&gt;    "}"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;let mkseq  l = new seq (List.map (fun i -&amp;gt; new integer i) l)&lt;br /&gt;let print x = Printf.printf "%s\n%!" x#to_s&lt;br /&gt;let ( * ) x y = x#times y&lt;br /&gt;&lt;br /&gt;let _ =&lt;br /&gt;  let c = mkseq [-102;1;5;10;33;42;77] in&lt;br /&gt;  let s = mkseq [1;0;-1] in&lt;br /&gt;&lt;br /&gt;    print (list_of s*x for x in c if x#even for s in s) ;&lt;br /&gt;    print (list_of x*s for s in s for x in c if x#even) ;&lt;br /&gt;    print (table_of (x,x#even) for x in c) ;&lt;br /&gt;&lt;br /&gt;    print (are_all x#even for x in c if x#even) ;&lt;br /&gt;    print (is_any  s#null for s in s) ;&lt;br /&gt;    print (max_of  x#abs for x in c if x#even)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Maintenant je définis l'extension de syntaxe qui traduit les constructions type générateurs vers la bonne recette à base de &lt;code&gt;fold&lt;/code&gt; (ce qu'on parcourt) et &lt;code&gt;add&lt;/code&gt; (ce qu'on construit).&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;(* Fichier pa_geno.ml *)&lt;br /&gt;&lt;br /&gt;open Pcaml&lt;br /&gt;&lt;br /&gt;let genseq = Grammar.Entry.create gram "genseq" ;;&lt;br /&gt;&lt;br /&gt;EXTEND&lt;br /&gt;  genseq: [&lt;br /&gt;    [ "for" ; x=patt ; "in" ; c=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        fun body -&amp;gt; let g = gs body in &amp;lt;:expr&amp;lt;&lt;br /&gt;          (fun acc -&amp;gt; $c$#fold acc (fun acc $x$ -&amp;gt; $g$ acc))&lt;br /&gt;        &amp;gt;&amp;gt;&lt;br /&gt;    | "if" ; test=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        fun body -&amp;gt; let g = gs body in &amp;lt;:expr&amp;lt;&lt;br /&gt;          (fun acc -&amp;gt; if $test$#in_val then $g$ acc else acc)&lt;br /&gt;        &amp;gt;&amp;gt;&lt;br /&gt;    | -&amp;gt; fun body -&amp;gt; &amp;lt;:expr&amp;lt; (fun acc -&amp;gt; acc#add $body$) &amp;gt;&amp;gt; ]&lt;br /&gt;  ] ;&lt;br /&gt;END ;;&lt;br /&gt;&lt;br /&gt;EXTEND&lt;br /&gt;  expr: BEFORE "expr1" [ "genexpr" NONA&lt;br /&gt;    [ "list_of" ; fx=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        let g = gs fx in &amp;lt;:expr&amp;lt; $g$ (new seq []) &amp;gt;&amp;gt;&lt;br /&gt;    | "table_of" ; fx=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        let g = gs fx in &amp;lt;:expr&amp;lt; $g$ (new table []) &amp;gt;&amp;gt;&lt;br /&gt;    | "are_all" ; fx=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        let g = gs fx in &amp;lt;:expr&amp;lt; $g$ (new conjunction True) &amp;gt;&amp;gt;&lt;br /&gt;    | "is_any" ; fx=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        let g = gs fx in &amp;lt;:expr&amp;lt; $g$ (new disjunction False) &amp;gt;&amp;gt;&lt;br /&gt;    | "max_of" ; fx=expr ; gs=genseq -&amp;gt;&lt;br /&gt;        let g = gs fx in &amp;lt;:expr&amp;lt; $g$ (new max 0) &amp;gt;&amp;gt;&lt;br /&gt;    ]&lt;br /&gt;  ] ;&lt;br /&gt;END ;;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Enfin pour compiler le tout:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&lt;br /&gt;  &gt;camlp4o pa_extend.cmo q_MLast.cmo pa_geno.ml -o pa_geno.ppo&lt;br /&gt;ocamlc -I `camlp4 -where` -c -impl pa_geno.ppo&lt;br /&gt;camlp4o ./pa_geno.cmo geno.ml -o geno.ppo&lt;br /&gt;ocamlc -I `camlp4 -where` -c -impl geno.ppo&lt;br /&gt;ocamlc geno.cmo -o gen&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Pour afficher la traduction du fichier ML par le préprocesseur, c'est &lt;code&gt;camlp4o ./pa_geno.cmo pr_o.cmo geno.ml&lt;/code&gt; et on y lit que &lt;code&gt;max_of x#abs for x in c if x#even&lt;/code&gt; devient:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;c#fold (new max 0)          (* for x in c *)&lt;br /&gt;  (fun acc x -&amp;gt;&lt;br /&gt;     if x#even#in_val then  (* if x#even  *)&lt;br /&gt;       acc#add x#abs        (* x#abs      *)&lt;br /&gt;     else acc)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Je suis sûr que ça change vos perspectives pour la journée :p&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115865575177280384?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115865575177280384/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115865575177280384' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115865575177280384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115865575177280384'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/gnrateurs.html' title='Générateurs'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115828430903725251</id><published>2006-09-15T03:30:00.000+02:00</published><updated>2006-09-15T03:39:25.100+02:00</updated><title type='text'>Netvibes</title><content type='html'>Toutes mes données ne sont pas chez Google, mes flux RSS préférés ainsi que quelques notes et TODO list sont sur ma page d'accueil &lt;a href="http://netvibes.com"&gt;Netvibes&lt;/a&gt;, la startup française à la mode. Et quand je décide de trainer sur MSN c'est désormais dans mon browser via Netvibes, grâce au module Meebo.. Oublions les problèmes de vie privée que tout cela pose, en tout cas c'est &lt;em&gt;cool&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Récemment j'ai ajouté le module &lt;a href="http://eco.netvibes.com/modules/91/daily-cartoons"&gt;Daily Cartoons&lt;/a&gt;, je découvre Dilbert, Reality Check, ou encore Pearls Before Swine. Je ris, parfois jaune:&lt;br /&gt;&lt;img style="width:100%" alt="pearls before swine" src="http://www.comics.com/comics/pearls/archive/images/pearls2006203590914.gif" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115828430903725251?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115828430903725251/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115828430903725251' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115828430903725251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115828430903725251'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/netvibes.html' title='Netvibes'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115802739585101822</id><published>2006-09-12T03:58:00.000+02:00</published><updated>2006-10-19T11:02:40.843+02:00</updated><title type='text'>Portées de variables</title><content type='html'>Encore un post de geek: devinerez-vous le résultat du petit bout de code suivant?&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;var bla = ["oof","rab"] ;&lt;br /&gt;var fun = [] ;&lt;br /&gt;for (var i in bla) {&lt;br /&gt;  // i varie de 0 à 1&lt;br /&gt;  var inside = 2*i ;&lt;br /&gt;  fun[i] = function () {&lt;br /&gt;   return (inside+"-"+bla[i]) ;&lt;br /&gt;  } ;&lt;br /&gt;  // (2*3)+"-"+"a" == "6-a"&lt;br /&gt;}&lt;br /&gt;alert("La reponse est: "+fun[0]()+"...") ;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Et le résultat du suivant?&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;var bla = ["oof","rab"] ;&lt;br /&gt;var fun = [] ;&lt;br /&gt;function fill(i) {&lt;br /&gt;  var inside = 2*i ;&lt;br /&gt;  fun[i] = function () {&lt;br /&gt;    return (inside+"-"+bla[i]) ;&lt;br /&gt;  } ;&lt;br /&gt;}&lt;br /&gt;for (var i in bla) { fill(i) }&lt;br /&gt;alert("La reponse est: "+fun[0]()+"...") ;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;function test() {  var bla = ['oof','rab'] ;  var fun = [] ;  function fill(i) {    var inside = 2*i ;    fun[i] = function () { return (inside+'-'+bla[i]) } ; }  for (var i in bla) fill(i) ;  alert('Avec une fonction auxiliaire la reponse est: '+fun[0]()+'...') ;  fun = [] ;  for (var i in bla) {    var inside = 2*i ;    fun[i] = function () { return (inside+'-'+bla[i]) } ;  }  alert('Avec la boucle la reponse est: '+fun[0]()+'...') ; alert('Sortis de la boucle (i,inside) vaut ('+i+','+inside+')') ; }&lt;/script&gt;&lt;a href="javascript:test()"&gt;Lancer le test?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A priori vous vous êtes trompés, et ce n'est pas votre faute mais celle du langage.&lt;br /&gt;&lt;br /&gt;L'expérience fonctionne aussi en Python, ça me déçoit de ces deux langages, je pensais que les problèmes de liaison de variables y étaient joliment résolus, comme l'exemple avec une fonction le montre.&lt;br /&gt;&lt;br /&gt;Mais qu'est-ce qui se passe, en fait ? Avec une boucle, une seule instance des variables "i" et "inside" est crée, elle persiste d'une étape de l'itération à l'autre. Du coup au moment où on évalue la fonction fun[0],  "i" et "inside" ont leur dernière valeur, respectivement 2 et "rab". A la limite pour "i" on dira que c'est spécifié comme cela, mais pour "inside"? La variable est déclarée dans la boucle! Si on veut avoir une variable persistant d'une itération à l'autre, on la déclare hors de la boucle. De même si on veut pouvoir accéder à "i" après la fin de la boucle. Si ce n'est pas l'effet voulu il est naturel de déclarer dans la corps de la boucle, et on voudrait bien que cela change quelquechose!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit&lt;/b&gt;: la "suite" de cette note est &lt;a href="http://misterpingouin.blogspot.com/2006/10/langages.html"&gt;ici&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115802739585101822?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115802739585101822/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115802739585101822' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115802739585101822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115802739585101822'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/portes-de-variables.html' title='Portées de variables'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115793956701816160</id><published>2006-09-11T03:52:00.000+02:00</published><updated>2006-09-11T04:09:34.906+02:00</updated><title type='text'>Strong typing doesn't have to suck</title><content type='html'>Au détour de conversations je suis tombé aujourd'hui sur &lt;a href="http://perl.plover.com/yak/typing"&gt;cet article&lt;/a&gt;. L'article dresse une très brève histoire des langages de programmation, et des systèmes de type. Les programmeurs des débuts s'arrachent les cheveux, confondant les adresses de nombres avec celles de chaînes. Ils inventent les systèmes de type de C/Pascal/etc: statiques (vérification à la compilation, plus d'information de type à l'exécution) et forts (une variable d'un certain type ne peut contenir de valeurs d'un autre type). Ces systèmes sont peu expressifs et somme toute mal foutus, ce qui mène à deux nouvelles évolutions. La puissance des machines aidant, on invente d'un côté les langages interprétés avec leurs systèmes de type dynamiques (le contenu d'une variable peut changer de type) très en vogue de nos jours. Mais le typage statique n'est pas mort, il a évolué dans les ML et Haskell: plus expressif, il relève de vraies erreur de programmation, et ne requiert pas d'annotations de la part de l'utilisateur. Conclusion: le typage fort ne suce pas forcément des ours.&lt;br /&gt;&lt;br /&gt;L'intéret de la présentation est qu'elle s'adresse à un large public de programmeurs, et non pas à des gens qui connaissent déja un ML. Des exemples simples de code sont donnés pour expliquer et motiver. Bref, je pense que ça peut intéresser un paquet de gens: ceux qui ne connaissent pas ML, et peut-être ceux qui en sont dégoutés; ceux qui en ont marre du typage dynamique, ou des annotations de type, et ceux qui ne le savent pas encore.&lt;br /&gt;&lt;br /&gt;Malheureusement ce n'est pas un guide introductif à ML, et je n'en connais pas que je puisse recommander. Si seulement OCaml était simple à apprendre, le monde saurait..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115793956701816160?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115793956701816160/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115793956701816160' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115793956701816160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115793956701816160'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/strong-typing-doesnt-have-to-suck.html' title='Strong typing doesn&apos;t have to suck'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115750510564695319</id><published>2006-09-06T02:48:00.000+02:00</published><updated>2006-09-19T10:43:27.770+02:00</updated><title type='text'>Voyage en Australie, en chiffres</title><content type='html'>Je suis bien arrivé en Australie. Parti dimanche à 23h15 de Paris, je suis arrivé à Singapour à 17h45 heure locale. Pour la première fois j'ai eu droit à des turbulences, mais j'ai même pas eu peur, fort de la statistique d'Estelle: &lt;em&gt;un homme qui passerait toute sa vie en avion aurait plus de chance de mourir de vieillesse que d'un accident&lt;/em&gt; -- pour les problèmes de santé liés à la bouffe et aux nuits dans un fauteuil, on sait pas.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/singapore.jpg"&gt;&lt;img style="display:block; margin:0 auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/singapore.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Quand je suis reparti à 19h50 pour Sydney, il faisait déja bien nuit. Après un second vol à 10000m d'altitude et 1000km/h, notre avion est descendu vers l'Océanie et une vitesse d'aterissage de 300km/h. Je suis arrivé à 05h10 sur le sol Australien, et mon passage aux douanes n'a pris que 10 secondes. La température extérieure est de 11°C, contre 30°C à Singapour: de ce côté là de l'équateur on se refroidit en descendant au Sud, et c'est la fin de l'hiver.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/fan.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/fan.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A 7h00 je quitte Sydney (4 200 000 hab) pour Canberra (325 000 hab, capitale de l'Australie, 20 000 000 hab) à bord d'un tout petit avion mu par ses hélices, et peuplé de costards et tailleurs. Je ne lis pas le journal Australien qu'on m'a proposé, la couverture me suffit pour bien rigoler quand je pense à la remarque du Lonely Planet: contrairement au cliché les Australiens ne sont pas des aventuriers chasseurs de crocodiles, etc.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/la_une.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/la_une.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La fin du premier épisode de cette histoire se termine à mon arrivée à Canberra à 7h50 heure locale, mardi matin. A ce moment là il est 23h50, mardi soir en France. Cela fait donc 24 heures que je suis parti, et pas beaucoup moins d'heures en vol, ce qui fait mal à mon &lt;a href="http://myfootprint.org/"&gt;karma&lt;/a&gt; par rapport à &lt;a href="http://misterpingouin.blogspot.com/2006/06/moi.html"&gt;la dernière fois&lt;/a&gt; où je l'ai calculé.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;PAR CATÉGORIE   HECTARES GLOBAUX&lt;br /&gt;ALIMENTATION  1.4&lt;br /&gt;TRANSPORTS  0.8&lt;br /&gt;LOGEMENT  0.6&lt;br /&gt;BIENS ET SERVICES  1.5&lt;br /&gt;VOTRE EMPREINTE TOTALE  4.3&lt;br /&gt; &lt;br /&gt;EN COMPARAISON, L'EMPREINTE ECOLOGIQUE MOYENNE&lt;br /&gt;DANS VOTRE PAYS EST 5.3 HECTARES GLOBAUX&lt;br /&gt;PAR PERSONNE.&lt;br /&gt;&lt;br /&gt;IL Y A 1.8 HECTARES GLOBAUX PRODUCTIFS PAR PERSONNE&lt;br /&gt;DANS LE MONDE. SI TOUT LE MONDE VIVAIT COMME VOUS&lt;br /&gt;ON AURAIT BESOIN DE 2.4 PLANETES&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Ah.. vous vouliez des photos d'où j'habite, des paysages et tout ? Patientez.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115750510564695319?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115750510564695319/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115750510564695319' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115750510564695319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115750510564695319'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/09/voyage-en-australie-en-chiffres.html' title='Voyage en Australie, en chiffres'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115697430597416081</id><published>2006-08-30T23:27:00.000+02:00</published><updated>2006-09-19T10:47:33.026+02:00</updated><title type='text'>Photos de Norvège</title><content type='html'>&lt;img style="float:left; margin:0 10px 10px 0;" src="http://static.flickr.com/72/227410335_286a70e719_m.jpg" border="0" alt="" /&gt;Estelle a mis en ligne une &lt;a href="http://edesarna.free.fr/norvege"&gt;galerie de photos&lt;/a&gt; sur notre voyage en Norvège. Dans le même temps nous avons commencé à uploader les mêmes photos sur &lt;a href="http://www.flickr.com/photos/94507150@N00/"&gt;Flickr&lt;/a&gt;. Mais la limitation à 20Mo/mois nous a vite calmés. Sinon Nico a pris de très belles photos aussi, mais il les a pas encore mises en ligne. Voici une petite sélection et un bref résumé.&lt;br /&gt;&lt;br /&gt;Nous sommes partis de Bergen, en bus, pour rejoindre Lavik, d'où nous avons voyagé en bateau vers Balestrand puis Flåm, profitant bien du paysage dans un fjord: en gros collez au dessus de la mer toutes sortes de trucs sans rapport, alpages helvètes, flancs escarpés pyrénéens, etc. Ensuite, cinq jours de rando jusqu'à Finnse puis Fossli, qui nous ont révélé des paysages encore très changeants, avec un glacier et ses alentours désolés à notre point culminant, 1700m... Prenant l'alibi de la blessure de l'un de nous, nous avons coupé court à la rando, et sommes retournés en bateau de Kinsarvik à Utne, puis bus pour Bergen, visitant au passage un autre fjord magnifique par un temps magnifique lui aussi.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;Pour finir, trois-quatre jours à visiter Bergen n'ont pas été de trop. Deuxième ville de Norvège, cela reste petit, et très mignon. Balades dans les rues et parcs, chouette musée notamment pour l'art moderne, pique-niques au poisson et autres curiosités culinaires, pintes dans un bar blindé d'étudiants fraîchement rentrés, points de vues et nombreuses pauses café.. Pour finir, visite à l'aquarium: ils ont des pingouins Gentoo!&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;img alt="Rue tordue de Bergen" src="http://static.flickr.com/67/227406621_e623e29da4_m.jpg" /&gt;&lt;br /&gt;&lt;img alt="Pingouin Gentoo" src="http://static.flickr.com/81/227397209_1817248200_m.jpg" /&gt;&lt;br /&gt;&lt;/center&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115697430597416081?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115697430597416081/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115697430597416081' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115697430597416081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115697430597416081'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/08/photos-de-norvge.html' title='Photos de Norvège'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115675751432046157</id><published>2006-08-28T11:07:00.000+02:00</published><updated>2006-08-28T11:33:47.730+02:00</updated><title type='text'>Malheureux lapin</title><content type='html'>Un post pour se plaindre un peu du &lt;a href="http://nabaztag.com"&gt;Nabaztag&lt;/a&gt;, un lapin Wifi conçu par la boîte française Violet. Pour noël dernier j'ai offert pino à ma copine, et nous avons joyeusement accueilli ce lapin-sapin multicolore. Pendant des mois il nous a réveillés, dit la météo, quelques messages occasionnels, puis quelques nabazcasts, entre deux séances de tai-chi.&lt;br /&gt;&lt;br /&gt;Au bout d'un moment une de ses oreilles s'est mise à grincer. Estelle a contacté Violet, on lui a gentillement proposé un échange, sans formalités, directement à leur siège. L'endroit est rigolo, petit, plein de lapins partout.. arrivés là-bas pino ne grince plus, mais on nous propose quand même un nouveau lapin dans une nouvelle boîte. Jusque là, super. Arrivés à la maison on branche le nouveau pino, et peu après il se fige, une oreille bloquée, grognant. Régulièrement, l'oreille se bloquera, bloquant tout le programme avec. Nous l'avions donc l'éteint.&lt;br /&gt;&lt;br /&gt;Un ami m'a dit qu'il avait eu le même problème, que Violet lui avait expliqué que c'était devenu fréquent pendant la grosse chaleur, et que c'était en effet passé depuis que le temps s'est rafraichi. Du coup nous avons rallumé le nouveau pino, et n'avont plus constaté le problème pendant deux jours. Mais hier, il était éteint. On le débranche, rebranche, rien n'y fait, pino est mort. Peut-être que ce n'est qu'un problème d'alim, mais ça commence à faire beaucoup pour un joujou de 100€ à moins de 10 mois de vie. &amp;Agrave; suivre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115675751432046157?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115675751432046157/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115675751432046157' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115675751432046157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115675751432046157'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/08/malheureux-lapin.html' title='Malheureux lapin'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115669764853937027</id><published>2006-08-27T18:46:00.000+02:00</published><updated>2006-08-27T18:56:59.920+02:00</updated><title type='text'>Liquidsoap 0.3.0</title><content type='html'>Je sors touuut doucement du rythme vacances. J'ai enfin publié la &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=89802&amp;package_id=150493"&gt;version 0.3.0&lt;/a&gt; de liquidsoap, qui était prête depuis presque un mois. J'attendais la fin des vacances pour pouvoir répondre aux questions d'éventuels utilisateurs. Pour commencer, j'ai annoncé la nouvelle sur la caml-list. Pour la suite, freshmeat, icecast, linuxfr, etc.&lt;br /&gt;&lt;br /&gt;Avec cette version riche en nouveautés et longuement peaufinée, j'espère voir arriver une belle vague de curieux. Dans tous les cas, je ne vais pas coder dans liquidsoap pendant un moment, ce qui est parfait pour ma rentrée. En Australie, ce sera boulot &lt;span style="font-size:70%"&gt;...et Nintendo DS -- oui j'ai craqué -- &lt;em&gt;New Super Mario&lt;/em&gt; et &lt;em&gt;Advance Wars&lt;/em&gt; ne me décoivent pas -- non j'ai pas encore testé DSLinux&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115669764853937027?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115669764853937027/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115669764853937027' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115669764853937027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115669764853937027'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/08/liquidsoap-030.html' title='Liquidsoap 0.3.0'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115623262592885298</id><published>2006-08-22T08:51:00.000+02:00</published><updated>2006-08-23T10:27:48.003+02:00</updated><title type='text'>Retour de våcånces</title><content type='html'>Retour définitif de vacances après deux semaines en Norvège. Pays magnifique, même si on se lasse après deux autres semaines de camping, et une nourriture un peu morne et carrément sucrée. Pour les photos de notre randonnée et visite de Bergen, vous attendrez encore un peu..&lt;br /&gt;&lt;br /&gt;Je me remets doucement dans le bain de la vie quotidienne, avec quelques tâches administratives à boucler avant mon départ à Canberra pour le mois de Septembre. Pour se consoler de la fin des vacances on est allé faire un petit saut à République, et je me suis enfin offert Viewtiful Joe 2. Ca fait un moment que je le reluque, et je suis pas déçu pas le super style cartoon et le gameplay déjanté.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img alt="Viewtiful Joe" src="http://ps2media.gamespy.com/ps2/image/article/551/551724/viewtiful-joe-2-20040927015520511.jpg" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;En réalité je suis encore plus atteint que ça, et je pense être dans une vraie période d'addiction au jeu, à moins que ce ne soient juste les gadgets.. Toujours est-il que je bave (de nouveau) sur la DS. Une des raisons est que Nicolas m'a rejoint et poussé dans ce penchant, et que je justifie l'idée de ce caprice de plus par tous les temps de transport que j'ai, en RER et aussi très bientôt en avion avec 24h aller pour l'Australie -- quoi de mieux pour tester la légendaire durée de vie des batteries de la DS.&lt;br /&gt;&lt;br /&gt;Pour me venger, j'y rajoute une dose, avec un petit tour des jeux qui me branchent. Evidemment il y a le nouveau &lt;em&gt;Super Mario Bros&lt;/em&gt;, et l'inévitable &lt;em&gt;Mario Kart&lt;/em&gt;. Forcément, je lorgne aussi l'opus DS de &lt;em&gt;Viewtiful Joe&lt;/em&gt;, qui exploite complètement le stylet. Une bonne valeur pour le solo dans les transports semble être &lt;em&gt;Advance Wars&lt;/em&gt;, ou &lt;em&gt;Age of Empires&lt;/em&gt;. La DS n'étant pas zonée, on peut tranquillement tenter l'import, avec notamment &lt;em&gt;Jump Superstars&lt;/em&gt;, un jeu de baston où les héros des grands mangas (One Piece, DBZ, Naruto, etc.) s'affrontent, dans un style &lt;em&gt;Smash Bros&lt;/em&gt;. Les captures sont alléchantes, mais c'est en japonais.&lt;br /&gt;&lt;br /&gt;Par contre, Metroid me botte pas tant que ça, malgré sa grosse utilisation du stylet, surtout depuis que j'ai vu une vidéo d'une DS Lite avec le deuxième écran niqué après trop de jouage brutal à ce jeu. Je me passerait probablement des programmes d'entrainement cérébral et autres. Et bof sur les genre de RPG mignons comme &lt;em&gt;Animal Crossing&lt;/em&gt; et &lt;em&gt;Harvest Moon&lt;/em&gt;. Mais je me laisserai surement tenter par Zelda, quand il sortira.&lt;br /&gt;&lt;br /&gt;Niveau bidouille, pas grand chose. Malgré la possibilité d'upload de code via Wifi, cela semble compliqué de lancer son petit code fait maison. Je n'espère pas hacker comme c'était le cas avec le Palm, mais c'est peut-être dommage de ne pas pouvoir avoir de developpement par des particuliers ou petites teams indépendantes. Par contre, une bidouille qui a l'air de marcher (ya pas de raison) c'est tunneler le traffic Wifi de l'engin pour jouer à plusieurs avec des DS distantes. En effet beaucoup de jeux ont un mode Wifi local, mais tous ne sont pas supportés par le service Nintendo sur Internet. Enfin, &lt;a href="http://www.opera.com/products/devices/nintendo"&gt;Opera&lt;/a&gt; devrait sortir en Octobre son browser pour la DS. Mais toujours aucune application type organizer sous le soleil.&lt;br /&gt;&lt;br /&gt;Voila, &lt;b&gt;dans ta gueule&lt;/b&gt; Nico.&lt;br /&gt;&lt;br /&gt;Petite note pour finir. Quelques problèmes récents m'ont amené à découvrir le nouveau Blogger beta. On n'y fait plus son template HTML à la mano, un cliquodrome est disponible. Du coup, j'ai peur de devoir bosser pas mal pour récupérer mon template actuel, si c'est possible. Mais la bonne raison de migrer c'est l'ajout des catégories, enfin! A suivre.&lt;br /&gt;&lt;br /&gt;Sinon cette année je vais donner deux TPs, l'un en Caml sur un sujet cool, l'autre en Java, plus bateau. Toujours est-il que j'ai donc enfin "appris" Java. Entendez par là que j'ai fait un HelloWorld et deux trois broutilles de plus en me basant sur ma connaissance du C++. Comme prévu je trouve ça verbeux et pas sexy du tout. J'ai été surpris par la faiblesse du &lt;code&gt;null&lt;/code&gt; qui a n'importe quel type. Unique pensée positive, je vais pouvoir bricoler un peu avec les API Google en Java: Blogger, Calendar, Map...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115623262592885298?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115623262592885298/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115623262592885298' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115623262592885298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115623262592885298'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/08/retour-de-vcnces.html' title='Retour de våcånces'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115412336246969043</id><published>2006-07-28T23:36:00.000+02:00</published><updated>2006-07-28T23:55:10.340+02:00</updated><title type='text'>[AO]mbre</title><content type='html'>Commencé peu avant la semaine en Bretagne, j'ai désormais fini le premier cycle des Princes d'Ambre, de Roger Zelazny. Je vous laisse trouver un résumé décent &lt;a href="http://livres.krinein.com/Princes-d-Ambre-Tomes-1-a-10-314.html"&gt;ailleurs&lt;/a&gt;. Mon appréciation: c'est bien. Le style m'a fait tiquer par moments, d'autant plus que le traducteur change d'un des cinq tomes à l'autre. Classé SF, ce n'en est pas complètement, et heureusement ce n'est pas complètement non plus de l'Heroic Fantasy, j'aurais pas aimé.&lt;br /&gt;&lt;br /&gt;J'ai aimé la façon avec laquelle on rentre dans l'histoire, en suivant le héros, terrien amnésique, découvrant progressivement la réalité fantastique. Ensuite, l'intrigue est bien conçue, ça complote dans tous les sens, ça rebondit et le suspens est captivant.&lt;br /&gt;&lt;br /&gt;L'élément SF, ce sont les univers parallèles, les Ombres, entre lesquelles les personnages principaux savent évoluer. Ils forcent les probabilités pour modifier leur environnement au fur et à mesure de leur voyage, glissant petit à petit d'un monde à l'autre, transformant au détour d'une route de montagne la végétation pour se retrouver quelques lacets plus loin sur un sentier côtier. Ils ne peuvent aller vers ce qu'ils ne connaissent pas, et vont d'autant plus vite d'une ombre à l'autre qu'ils connaissent d'intermédiaires. Tout ça devient trop simple et faux quand on avance dans la série, mais cela m'a séduit et je me suis démandé si l'on pourrait créer un jeu autour de ce principe. Mais que faire quand deux personnages font glisser différemment leur environnement? Tout ça, tout ça.&lt;br /&gt;&lt;br /&gt;Pour revenir aux bouquins, après les cinq tomes du cycle de Corwin, j'entame le cycle de Merlin. On m'a dit que c'est lassant, je verrai.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115412336246969043?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115412336246969043/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115412336246969043' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115412336246969043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115412336246969043'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/07/aombre.html' title='[AO]mbre'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115412110886032377</id><published>2006-07-28T22:38:00.000+02:00</published><updated>2006-07-29T23:12:40.846+02:00</updated><title type='text'>KerCycloTour</title><content type='html'>De toute évidence, j'avais besoin de vacances -- cf. mon dernier post par exemple. Pour commencer, je suis parti une semaine à vélo en Bretagne avec Estelle. Bref récit sans photos pour l'instant.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 1&lt;/b&gt;. Train annoncé en retard à la gare, nous n'avons pas le temps de démonter les vélos sur le quai. Jouer au mécano dans un couloir de TGV se révèle être assez pénible. Quelques heures plus tard on remonte tout à Brest, et on prend la route, sur des pistes cyclables qui font plaisir. Le camping visé est plein, mais on trouve de la place à celui de Portez. Par rapport à l'Irlande c'est pas cher, et le terrain et les équipements sont tip-top.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 2&lt;/b&gt;. On longe toujours la côte vers l'Ouest, en passant par la pointe St Mathieu. On remonte ensuite au Nord en se perdant au passage en essayant de prendre des petites routes. Par la suite on deviendra meilleurs à ce jeu là, ou apprendra à se contenter des départementales, assez calmes finalement. Le trajet se termine très près de la côte, en passant par Porspoder, c'est très joli. Pour la nuit le camping de Landunvez nous accueille. Il fait chaud et le dénivellé pénible se confirme: ça monte et ça descend sans arrêt. Les noms des bleds sont distrayants: Kergollo, Kerdéniel, Kervoulou, Kerourien, etc.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 3&lt;/b&gt;. Toujours par les petites routes on rejoint Lampaul-Ploudalmézeau, le mignon St-Pabu puis Lannilis. A ce niveau nous avons le malheur d'emprunter la grosse D13 pour rejoindre Plouguerneau. Nous arrivons stressés et fatigués au Camping de la grève blanche, à St Michel, Plouguerneau. Un office du tourisme sur la route nous a fourni le guide très utile des campingséde Bretagne. Il y en a vraiment beaucoup, ce qui nous a tout du long évité le camping sauvage, auquel la Bretagne semble peu propice. On a sûrement été plutôt chanceux de ne pas trouver trop de campings complets sur la route.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 4&lt;/b&gt;. On boucle la boucle d'un coup en redescendant droit au Sud vers Brest. Après avoir longé agréablement l'Aber Wrach, on repasse à Lannilis, Coat Meal, les Trois Curés. Route tranquille. L'entrée dans Brest est pénible, surtout qu'en suivant les panneaux "Brest Ports" on se retrouve embarqués sur une grosse artère et super déportés à l'Est vers Guipavas. La route est soit-disant amménagée pour les vélos: en fait on nous laisse le trottoir dont personne ne voudrait, caillouteux et irréguliers, puis carrément le maigre espace entre la glissière de sécurité et les taillis mal taillés. On descend finalement sur le port pour se consoler avec une bière et embarquer dans la navette pour Camaret. On se fixe au Camping municipal, spacieux sympa et bon marché, pour quatre nuits.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 5&lt;/b&gt;. Enfin posés, on se repose ? Non, on part pour une petite boucle vers la pointe des Espagnols. La route est jolie, le point de vue final pas si formidable, mais le tout est carrément sportif. Le soir nous nous offrons un plateau de fruits de mer pour bonne conduite spartiate. C'est cher mais délicieux, il y en a plein, du bon crabe, de belles huitres, miam. Deux ombres: pas de coquillages ce jour-ci, comblés par un excès de langoustines, et un pain moyen en quantité insuffisante. On découvre le lendemain à l'office du tourisme l'existence d'un label de qualité pour les plateaux de fruits de mer qui aurait garanti contre ces deux inconvénients. Deux restaurants du port, à peine plus chers, l'avaient. Le prochain plateau sera encore meilleur!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 6&lt;/b&gt;. Notre navette pour Ouessant est annulée, on part vers le Cap de la Chèvre à la place. Encore une fois, de belles côtes, il y en a marre! Mais c'est joli, surtout la plage de l'Ile Vierge qu'Estelle me fait découvrir. Splendide et bien cachée, donc pas trop peuplée.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 7&lt;/b&gt;. Mauvais temps annoncé, nous n'avions rien prévu. En fait il fait beau, et on part tester la plage du Veryarch. Courte baignade, petites piqures de vive pour tous les deux. On suit le GR à pied pour aller à Camaret. La navette pour Ouessant n'est toujours pas réparée, on décide de rentrer un jour plus tôt, dès le lendemain. Dîner à la bonne creperie Rocamadour, un rhum intéressant à la rhumerie, et une petite stout au pub d'à côté, à écouter des musiciens probablement trop expérimentaux pour leur public en vacances.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jour 8&lt;/b&gt;. On met les vélos dans le bateau. Arrivés à la gare nous sommes agréablement surpris d'être autorisés à rentrer en avance sur le quai pour démonter les vélos. Mais on nous envoie au bout du train où on ne trouve pas notre voiture. En fait elle était en queue, à l'autre bout. On perd notre avance pour démonter les vélos, ce qui se fait dans l'urgence. Le contrôleur refuse ensuite qu'on les case dans un fourgon vide dont nous avait parlé le conducteur du train. Le fourgon reste vide tandis que nos deux vélos, rejoints par un autre en cours de route, encombre le passage. Nous devons les déplacer dans les gares où le quai est à droite pour laisser les gens circuler. Arrivés à Paris on remonte une dernière fois les vélos, affronte la circulation. Une douce froide plus tard, posés sur un vrai lit, ça va mieux :p&lt;br /&gt;&lt;br /&gt;La morale. Le vélo en Bretagne, c'est chouette. Mais pas encore idéal, avec un gros point noir au niveau du train. Apparemment les nouvelles rames en cours de construction devraient être équipées pour transporter des vélos non démontés. Ce serait déja le cas des Thalys, qu'on testera peut-être l'an prochain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115412110886032377?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115412110886032377/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115412110886032377' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115412110886032377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115412110886032377'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/07/kercyclotour.html' title='KerCycloTour'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115203860824435528</id><published>2006-07-04T20:15:00.000+02:00</published><updated>2006-07-04T20:43:28.263+02:00</updated><title type='text'>LICS submission</title><content type='html'>Dr. Simon, assisted by PhD students David and Andrew recently submitted a paper at the Lazy Idle Computer Scientist 2006 Conference: &lt;em&gt;Balloons considered harmless&lt;/em&gt;. Here is a short abstract.&lt;br /&gt;&lt;br /&gt;We study the categorical structure of balloons and the container behaviour they get when blown. This structure implies some simple observations, which however haven't been explored yet as far as we know: ballons can be nested in several ways. See below the representation of &lt;code&gt;f(g,h)&lt;/code&gt; and the triple nesting &lt;code&gt;f(g(h))&lt;/code&gt; -- a spectacular performance by Dr. Simon.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00032.jpg"&gt;&lt;img style="display:block;margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00032.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00042.jpg"&gt;&lt;img style="display:block;margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00042.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then we point out that the notion of blowing a balloon is self-dual, as demonstrated on the picture of Andrew "blowing" a balloon from the outside, and can be generalized smoothly to the filling of a balloon with anything, as demonstrated by Andrew blowing ballons with his crazy ideas.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00037.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00037.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00038.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00038.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00033.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00033.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;More trivial uses of the balloons-as-containers paradigm include storage of useful items, like whiteout, money, water, ice tea cans, mobile phones, pens, and so on -- we let the reader guess in which balloon is which item.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00039.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00039.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00034.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00034.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;More serious applications shall be explored. For example a balloon can be used as a security device allowing one to know that nobody has used his mouse -- however, some details need to be worked out as limited interactions with the mouse are still possible.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00031.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00031.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Another interesting application is the levitation of balloons. By embedding an magnetic device instead of the usual Helium in a balloon, we've been able to have it fly. Two efficient techniques to initiate the process have been developped. This involves a new theory of which the basic principles and properties are sketched below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00040.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00040.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/dsc00041.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/dsc00041.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115203860824435528?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115203860824435528/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115203860824435528' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115203860824435528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115203860824435528'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/07/lics-submission.html' title='LICS submission'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115169204530134168</id><published>2006-06-30T20:17:00.000+02:00</published><updated>2006-06-30T20:29:44.313+02:00</updated><title type='text'>DADVSI (suite..)</title><content type='html'>Aujourd'hui a été votée la loi sur le Droit d'Auteur et les Droits Voisins dans la Société de l'Information, telle qu'écrite par la CMP. EUCD.info a &lt;a href="http://eucd.info/index.php?2006/06/30/334-l-ump-vote-la-pire-loi-sur-le-droit-d-auteur-en-europe"&gt;réagi&lt;/a&gt; immédiatemment, et fournit aussi un résumé des péripéties &lt;a href="http://eucd.info/index.php?2006/06/30/333-french-parliament-approves-the-worst-copyright-law-in-europe"&gt;en anglais&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;On peut aussi lire le long &lt;a href="http://www.assemblee-nationale.fr/12/cra/2005-2006/257.asp"&gt;compte-rendu&lt;/a&gt; de la journée à l'Assemblée Nationale pour un rappel des principaux problèmes -- et pour voir les auteurs de la loi s'auto-glorifier. Pour ma part j'y remarque un passage sur la procédure d'urgence:&lt;em&gt;&lt;br /&gt;M. le Ministre - [...] Dois-je rappeler que si le Gouvernement, ces derniers dix-huit mois, a déclaré six fois l’urgence, le gouvernement de Lionel Jospin, dans le même laps de temps, l’avait déclarée dix-huit fois ? Que ceux qui nous font ce reproche aient donc un peu de mémoire ! (Applaudissements sur les bancs du groupe UMP)&lt;br /&gt;M. Patrick Bloche - Il n’y avait pas de ministre parjure dans le gouvernement Jospin !&lt;/em&gt;&lt;br /&gt;A mon avis la procédure était avant utilisée pour ce pour quoi elle est faite: quand une loi doit  passer vite mais ne fait pas débat. L'opposition critique plusieurs fois par la suite la procédure en ce sens, et ne sont pas contredits.&lt;br /&gt;&lt;br /&gt;Je n'ai pas grand chose à rajouter, c'est triste sur le fond et la forme. Mais tout ça n'est probablement pas fini. En attendant, la &lt;a href="http://blog.outer-court.com/prejudice/"&gt;Prejudice Map&lt;/a&gt; va devoir changer ce pour quoi les français sont connus: politique de bas-étage soumise aux lobbys, lois absurdes et répressives.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115169204530134168?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115169204530134168/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115169204530134168' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115169204530134168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115169204530134168'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/dadvsi-suite.html' title='DADVSI (suite..)'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115153502587697160</id><published>2006-06-29T00:45:00.000+02:00</published><updated>2006-06-29T00:50:25.900+02:00</updated><title type='text'>Moi</title><content type='html'>Finalement je suis pas si mal comme mec. D'après &lt;a href="http://myfootprint.org/"&gt;Earth Day Footprint&lt;/a&gt; je suis un gros parasite mais moins que les autres:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;CATÉGORIE             HECTARES&lt;br /&gt;ALIMENTATION            1.3&lt;br /&gt;TRANSPORTS              0.5&lt;br /&gt;LOGEMENT                0.6&lt;br /&gt;BIENS ET SERVICES       1.2&lt;br /&gt;VOTRE EMPREINTE TOTALE  3.6&lt;br /&gt;&lt;br /&gt;EN COMPARAISON, L'EMPREINTE ECOLOGIQUE MOYENNE DANS VOTRE PAYS&lt;br /&gt;EST 5.3 HECTARES GLOBAUX PAR PERSONNE.&lt;br /&gt;&lt;br /&gt;IL Y A 1.8 HECTARES GLOBAUX PRODUCTIFS PAR PERSONNE DANS LE MONDE. &lt;br /&gt;SI TOUT LE MONDE VIVAIT COMME VOUS ON AURAIT BESOIN DE 2 PLANETES.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Sinon je me suis rendu compte que dans la recherche, yavait pas que les étudiants pour procastiner -- comme nous l'apprend si bien &lt;a href="http://www.phdcomics.com"&gt;PhD Comics&lt;/a&gt; (que je ne lis malheureusement plus régulièrement depuis qu'ils ont supprimé leur flux RSS). Aujourd'hui on a discuté à quatre pendant trois heures, je peux vous dire qu'on a caressé un paquet d'idées impressionant, et vous garantir que le quart sera exploité au maximum. Cela dit ça me parait normal. On pourrait faire ça, ouais mais est-ce que c'est vraiment intéressant, tiens au fait vous avez vu que ça ressemble à ça, et dis donc comment t'expliques ça, heu avec tout ça on se décide pas sur la question initiale, ouais bon, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115153502587697160?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115153502587697160/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115153502587697160' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115153502587697160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115153502587697160'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/moi.html' title='Moi'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115140142707436835</id><published>2006-06-27T11:41:00.000+02:00</published><updated>2006-06-27T11:43:47.086+02:00</updated><title type='text'>Icelandair</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://static.flickr.com/47/175894782_1f97d2bd38.jpg?v=0"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="http://static.flickr.com/47/175894782_1f97d2bd38.jpg?v=0" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;J'ai trouvé cette photo sur &lt;a href="http://www.flickr.com/photos/qxz/175894782/"&gt;Flickr&lt;/a&gt; qui montre bien un genre de paysage bizarre qu'on peut voir défiler depuis un vol Icelandair vers le Nord des Etats-Unis -- yen a toute une variété.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115140142707436835?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115140142707436835/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115140142707436835' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115140142707436835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115140142707436835'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/icelandair.html' title='Icelandair'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115135503963125503</id><published>2006-06-26T22:23:00.000+02:00</published><updated>2006-06-26T22:54:46.410+02:00</updated><title type='text'>Des cadences</title><content type='html'>Une semaine chargée s'annonce avec un invité et un afflux de boulot conséquent. Parfois il faut s'y mettre, mais j'en ai marre de bosser par ci par là sans publier. Je veux pas faire l'obsédé de la publi, mais il m'en faudra tôt ou tard, et c'est embêtant de regarder en arrière ce qu'on a fait sur un an et de ne voir que des brouillons éparpillés. Bon j'exagère, on a significativement avancé sur &lt;a href="http://slimmer.gforge.inria.fr/bedwyr"&gt;Bedwyr&lt;/a&gt;, c'est déja ça.&lt;br /&gt;&lt;br /&gt;Sans Geek Radio, liquidsoap se fait la main sur Dolebraï la radio libre. Quelques segfaults bizarres restent à étudier, c'est nouveau et peut-être lié aux metadatas crados de la playlist -- il faut toujours un coupable. Toujours est-il que Savonet va bientôt publier un paquet de paquets, ça va faire du bien de sanctionner tout ce boulot aussi.&lt;br /&gt;&lt;br /&gt;En dehors de ça, Dolebraï n'avance pas beaucoup. Pas de nouvelle musique, pas de système de gestion des playlists à l'horizon.. Comme j'ai dit j'ai largement de quoi m'occuper, je vais pas m'investir corps et âme pour mettre le tout en place, et voir un peu comment les choses évoluent. Le temps n'est pas élastique, dit mon papa, et j'en ai marre d'avoir l'impression de passer mes journées à geeker.&lt;br /&gt;&lt;br /&gt;Par contre j'écoute beaucoup de musique ces temps-ci, en vue d'enrichir les playlists. En particulier je m'essaie à la conso de podcasts. Je teste &lt;a href="http://www.peapodpy.org/"&gt;PeaPod&lt;/a&gt; pour télécharger les nouveautés sur mon Palm. J'avais d'abord envisagé de faire un script Ruby minimal mais &lt;code style="font-size:x-small"&gt;in `_parse'.../format.rb:253: [BUG] Segmentation fault&lt;/code&gt;... Agacé par cette nouvelle démonstration violente d'instabilité je me suis tourné vers Python et le module feedparser qu'a l'air assez nickel. Pour finalement découvrir PeaPod qui est construit sur ces outils. J'ai dû fixer un petit problème avec les URLs mal encodées de certains feeds et j'en ai profité pour noter que le code est pas tout joli joli.. menfin si ça marche je serai content. J'attends de voir comment ça marche à long terme.&lt;br /&gt;&lt;br /&gt;J'ai été étonné de la facilité avec laquelle on trouve des podcasts qui diffusent de la musique Creative Commons. Pour ce que j'ai écouté ce matin la qualité est au rendez-vous, en particulier Revolution (pas ratable sur google) avec en prime une vraie voix de speaker à passer la nuit avec. Tout ça contraste avec l'absence manifeste de webradios diffusant de la musique libre. Peur des problèmes légaux, difficulté technique, ou préférence des auditeurs pour le podcast ? Je pense que les deux premiers points sont vrais, mais le second me taraude quand même... reste-t-il beaucoup de gens pour bosser/glander en écoutant la radio ? Dans les transports on écoute la FM, ou des podcasts. Au bureau, on écoute rien. Le soir, on regarde la télé, joue, regarde un film, aucun intérêt pour un fond sonore discret pendant que la tête travaille.&lt;br /&gt;&lt;br /&gt;Au final, le podcast et la webradio sont sûrement complémentaires. Enfin, j'espère. Pistes pour Dolebrai: avoir un podcast des nouveautés dans la playlist, et diffuser les émissions des bons podcasts comme Revolution ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115135503963125503?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115135503963125503/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115135503963125503' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115135503963125503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115135503963125503'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/des-cadences.html' title='Des cadences'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115115135343701827</id><published>2006-06-24T13:32:00.000+02:00</published><updated>2006-06-24T14:15:53.456+02:00</updated><title type='text'>DADVSI et démocratie</title><content type='html'>Je rappelle ici brièvement l'histoire du projet de loi DADVSI, je recommande la lecture des articles d'&lt;a href="http://eucd.info"&gt;EUCD.info&lt;/a&gt; pour plus de détails, et la suite des évenements.&lt;br /&gt;&lt;br /&gt;Il y a quelques mois le ministre de la culture RDDV propose le projet de loi DADVSI (Droit d'Auteur et Droits Voisins dans la Société de l'Information), et le fait passer en procédure d'urgence, dans le style musclé de notre gouvernement de merde. Le sujet fait moderne mais le contenu est assez conservateur: grosse peur du téléchargement libre, du piratage, volonté de contrôle des internautes, et grosse peur des puissantes maisons de disque qui tentent de réfréner un mouvement qui les force plus ou moins à changer de modèle commercial..&lt;br /&gt;&lt;br /&gt;Plus précisemment le texte propose: de nouveaux moyens de sanctionner le piratage, une modification du droit d'auteur enlevant notamment au client le droit à la copie privée, une obligation pour les logiciels d'échange de données (appréciez le flou de l'appelation) de se doter de DRM (Digital Rights Management, verrou logiciel sur les données), des sanctions plus lourdes pour le cassage de ces verrous... Les consommateurs sont effrayés, les auteurs et utilisateurs de logiciels libres aussi. Les DRM sont par essence des procédés non publiés, ils seraient inopérants sans ça -- dans le monde du logiciel, on peut tout copier, c'est comme ça. Du coup les fichiers achetés en ligne ne fonctionnent que sur un nombre restreint de balladeurs. Exemple type: la musique achetée sur l'iTune Music Store ne peut être écoutée que sur un iPod. Evidemment, tout le monde casse les DRM pour écouter sa musique comme bon lui semble, la FNAC a même diffusé à une époque des instructions dans cette direction.&lt;br /&gt;&lt;br /&gt;Bonne surprise lors de la lecture à l'Assemblée Nationale. Bon nombre de députés se sont emparés du sujet, dans l'opposition mais aussi à l'UMP, et se sont informés des risques des DRM pour la concurrence, l'interopérabilité, ainsi que des risques pour les logiciels libres. Les débats sont électriques, et au final la loi ne ressemble plus vraiment au projet initial, avec notamment une brêche laissant la porte ouverte au projet de licence globale du PS, et un amendement imposant l'interopérabilité des DRM, ce qui a fait très peur à Apple.&lt;br /&gt;&lt;br /&gt;A ce stade le ministre est déja fustigé par bon nombre de députés, la procédure étant douteuse en plusieurs points -- je passe les détails. Il promet de lever la procédure d'urgence en cas de désaccord majeur entre les deux chambres. Malheureusement, la lecture au Sénat inverse la tendance, supprime l'exigence d'interopérabilité et met en danger les auteurs de logiciels libres. Surprise, c'est même un amendement PS.&lt;br /&gt;&lt;br /&gt;On appelle le ministre a lever l'urgence comme promis, il n'en fait rien. On passe donc à la case CMP (Commission Mixte Parlementaire): douze députés et sénateurs doivent régler le différent. Les députés et sénateurs sont triés sur le volet, les dissidents écartés. Et ils arrivent carrément avec 55 nouveaux amendements sous le bras. Les membres de l'opposition voient rouge, demandent un délai pour étudier ces amendements, et quittent la réunion face au refus du président. Inutile de dire que le texte est désormais &lt;a href="http://eucd.info/index.php?2006/06/23/324-que-fait-le-dadvsi"&gt;alarmant&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Petite lueur d'espoir, tout n'est pas fini. Les deux chambres doivent encore voter le texte, mais ne peuvent plus le modifier. J'espère vraiment que l'Assemblé va nous montrer encore une fois que la démocratie en France a son mot à dire, que les députés UMP vont voter en leur âme et conscience au lieu de suivre le groupe et le gouvernement.&lt;br /&gt;&lt;br /&gt;Je suis complètement atterré par cette histoire, le manque de sérieux du gouvernement, la prévalence des lobbys sur la démocratie. Il faut voir comment le ministre, en bon élève de notre premier ministre, s'obstinait dans ses magouilles malgré l'indignation des députés. En premier lieu, la procédure d'urgence est une aberration, complètement injustifiée pour un sujet comme celui-ci. La raison invoquée était la nécessité de modifier la loi avant la fin 2005 pour s'aligner sur la loi européenne. Mais j'ai lu récemment que la commission européenne envisageait maintenant de remettre en cause la loi autour des DRM, constatant les risques pour la concurrence. Enfin je suis désolé du manque de couverture du sujet. Rien de visible dans les journaux aujourd'hui au sujet des récents évenements.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115115135343701827?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115115135343701827/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115115135343701827' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115115135343701827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115115135343701827'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/dadvsi-et-dmocratie.html' title='DADVSI et démocratie'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115102014071754835</id><published>2006-06-23T01:46:00.000+02:00</published><updated>2006-06-23T02:06:26.740+02:00</updated><title type='text'>Mon monde</title><content type='html'>Après avoir cherché à recueillir des infos sur certains endroits que j'ai parfois besoin d'indiquer/recommander aux gens, essayé quelques services décevants, j'ai finalement regardé comment on utilise la Google Maps API.. et c'est facile. Voici donc &lt;a href="http://mrpingouin.free.fr/stuff/endroits.html"&gt;mon monde&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Autre hack de la soirée: récupérer les nouveautés Jamendo sous forme de playlist. Jamendo propose des &lt;a href="http://www.jamendo.com/fr/?p=rss"&gt;flux RSS&lt;/a&gt; des nouveaux albums. On préferera un podcast, ou une simple playlist au format texte.. pas de problème:&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'xml/libxml'&lt;br /&gt;&lt;br /&gt;rss = 'http://www.jamendo.com/fr/?archive_encoding=ogg3&amp;audio_encoding=ogg2'+&lt;br /&gt;      '&amp;format=rss2&amp;g=poprock&amp;linkto=playlist&amp;m=backend&amp;num=20&amp;type=albums'&lt;br /&gt;&lt;br /&gt;XML::Document.file(rss).find('//rss/channel/item').each do |node|&lt;br /&gt;  node.find('link').each do |node|&lt;br /&gt;    puts `wget '#{node.content}' -O - 2&gt; /dev/null`&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Compact non ? C'est ma façon de prospecter pour Dolebrai, qui se monte plus que jamais..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115102014071754835?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115102014071754835/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115102014071754835' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115102014071754835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115102014071754835'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/mon-monde.html' title='Mon monde'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-115062457883025266</id><published>2006-06-18T11:55:00.000+02:00</published><updated>2006-06-22T08:59:17.013+02:00</updated><title type='text'>Anarchie</title><content type='html'>Quelques trucs qui ont retenu mon attention ces derniers temps...&lt;br /&gt;&lt;br /&gt;D'abord je recommande à tous de se tenir au courant des évolutions du projet de loi DADVSI, le coup final pourrait se jouer demain et c'est pas joli joli.. Certes ça déprime encore plus sur la politique en France de nos jours et notre gouvernement actuel. Le site &lt;a href="http://eucd.info"&gt;EUCD.info&lt;/a&gt;, impliqué dans la lutte contre certains aspects préoccupants du projet de loi, est une très bonne source d'information -- et ya un flux RSS dispo pour ne rien rater.&lt;br /&gt;&lt;br /&gt;Sinon Geek Radio a été coupée pour cause de grosse chaleur dans la salle des machines. Après 8 jours d'uptime, on sentait bien qu'un pas de plus vers un liquidsoap stable avait été franchi, mais on aurait aimé voir l'uptime monter encore un peu..&lt;br /&gt;&lt;br /&gt;En échange une version de test de Dolebraï la radio 100% libre est &lt;a href="http://radiopi.org:8080/dolebrai.ogg"&gt;en place&lt;/a&gt; grâce aux serveurs de radio Pi. Compte-rendu de la bièréunion d'avant-hier à propos de cette radio:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Rassembler de la musique, beaucoup plus que maintenant.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Dès qu'on sera sur un serveur où on a de la place, fonctionner en local, en téléchargeant les fichiers, retagués avec des infos de provenance afin de promouvoir la donation à l'artiste original. Ainsi on pourra utiliser l'indexeur bubble de savonet pour créer la BDD.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Site web: strict minimum pour l'instant, puis afficher les morceaux passés, peut-être les playlists, puis permettre le feedback des utilisateurs. Le site sera en Python/Django ou PHP. Sam a proposé Ocsigen..&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Liquidsoap: le script sera articulé par plages thématiques identifiées par des jingles de transition, on utilisera aussi des jingles horaires en superposition sur le son, et la coupure de blancs... faut justifier l'outil, quoi :)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;On met en place une version de test de la radio sur les serveurs de radio Pi, et du site sur le serveur de Nico.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;On migre sur dedibox dès que c'est décent, avec un objectif de rentrer dans les frais de location du serveur sous 5 mois, par donations ou sponsoring.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Finalement obtenir un nom de domaine, installer un serveur mail..&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Autres liens en vrac.. &lt;a href="http://hop.inria.fr"&gt;HOP&lt;/a&gt;, un framework de webdev en Scheme, développé par l'INRIA. &lt;a href="http://lulu.com"&gt;LULU&lt;/a&gt; un site d'auto-édition: chacun peut s'éditer et y mettre en vente ses livres (et autres) et garder 80% du bénéfice. On y trouve de tout.&lt;br /&gt;&lt;br /&gt;Sinon, j'ai lu la morale anarchiste de Kropotkine. J'adhère à la morale, très athée et rationnelle. En gros l'homme a une notion de bien et de mal, naturellement, et les notions imposées par la religion ou la loi masquent la vérité au profit de certains. L'auteur souhaite effacer cette source d'inégalités. Bien sûr il y a une super dose d'utopie derrière ça. D'ailleurs l'auteur ne répond pas à une question. S'il dit bien que l'homme, comme tout animal, a une notion de bien/mal fondée sur la survie de l'espèce, il n'explique pas pourquoi l'homme, il me semble, dérive plus facilement que les autres animaux du chemin du bien. C'est court et ça se lit bien, et j'apprécie beaucoup de voir une morale se dégager malgré l'absence d'élement transcendant. Finalement c'est comme une bonne logique, il suffit d'observer les règles du système pour le comprendre, pas besoin de sémantique :p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-115062457883025266?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/115062457883025266/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=115062457883025266' title='4 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115062457883025266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/115062457883025266'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/anarchie.html' title='Anarchie'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114977956720365170</id><published>2006-06-08T17:12:00.000+02:00</published><updated>2006-06-09T10:42:48.206+02:00</updated><title type='text'>Temps de cerveau disponible</title><content type='html'>On m'a raconté aujourd'hui comment certaines personnes mal intentionnées réquisitionnent les cerveaux des internautes de façon assez amusante, et moins passive que TF1.&lt;br /&gt;&lt;br /&gt;Certains sites, fournisseurs de service mail ou d'espace de stockage en général, ont récemment mis en place des procédures d'enregistrement plus compliquées censées éviter les enregistrements massifs par robots. Le truc du moment c'est les textes déformés, que les humains reconnaissent plutôt bien, et les ordinateurs assez mal. Qu'à cela ne tienne, il existe une parade: plutôt que de s'acharner sur ce difficile problème, on exploite les humains si doués. Voici le système qu'on m'a décrit: le robot commence une inscription, récupère l'image à reconnaitre, attend un gogo sur un site porno, lui réclame une inscription avec la même image à reconnaitre, et utilise sa réponse pour terminer la première inscription. Visiblement ya assez de gogos pour que cela fonctionne.&lt;br /&gt;&lt;br /&gt;Même genre d'histoire &lt;a href="http://it.slashdot.org/it/06/06/08/2151222.shtml"&gt;sur Slashdot&lt;/a&gt;, où l'on attaque une entreprise par social engineering totalement passif: rien besoin de savoir, sauf que les employés sont curieux -- et ne font pas la différence entre une image et un exécutable.&lt;br /&gt;&lt;br /&gt;Puisqu'on parle de temps de cerveau, je (re-)lis à l'instant comment l'Education Nationale vend celui des petits français à Microsoft: &lt;a href="http://www.april.org/articles/communiques/pr-20060609.html"&gt;dénonciation&lt;/a&gt; de l'APRIL.&lt;br /&gt;&lt;br /&gt;Sinon, si vous avez &lt;a href="http://www.yarukinoki.net/flash/pendulumeca/"&gt;du temps à perdre&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114977956720365170?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114977956720365170/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114977956720365170' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114977956720365170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114977956720365170'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/06/temps-de-cerveau-disponible.html' title='Temps de cerveau disponible'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114891564041957327</id><published>2006-05-29T17:13:00.000+02:00</published><updated>2006-06-02T09:11:16.543+02:00</updated><title type='text'>Tes lacets sont des fées</title><content type='html'>Café à la main et FIP dans les oreilles, je vais enfin écrire un paquet de trucs accumulés.&lt;br /&gt;&lt;br /&gt;D'abord je suis rentré de Minneapolis. J'ai écrit un post sur mon Palm mais je ne sais toujours pas comment le rapatrier sur l'ordi, pas envie de bidouiller. Je vous passe donc le récit d'un voyage plutôt banal, et mon second émerveillement au dessus du Groenland.&lt;br /&gt;&lt;br /&gt;Sur le retour j'ai lu &lt;em&gt;Farenheit 451&lt;/em&gt; de Ray Bradbury, et je le recommande chaudement. Roman d'anticipation bien sûr visionnaire, décrivant un monde où les gens ne prennent plus le temps de se parler, de penser, de rêver, mais s'abrutissent à coups d'images, de sons, de vitesse. Le protagoniste est un pompier, chargé de bruler les livres, fauteurs de troubles, de questionnement et de tristesse. Le bouquin ne sombre pas dans une critique trop longue et rabat-joie de cette caricature de notre monde pressé. Il nous appelle au rêve et à l'émerveillement, à une réflexion sur l'homme, tout cela dans ce roman court et bien écrit. Enfin, Bradbury finit sur un note positive, un espoir en l'homme dont on a parfois bien besoin.&lt;br /&gt;&lt;br /&gt;Ces deux dernières semaines nous avons amélioré &lt;a href="http://savonet.sf.net/wiki/Liquidsoap"&gt;liquidsoap&lt;/a&gt;. L'observation des plantages d'une Geek Radio plus stressée nous a permis de corriger plusieurs bugs. On s'approche encore de la stabilité. Le programmation de Geek Radio a aussi gagné en variété, avec des programmes thématiques agréables et bien fournis. Comme je commence à écouter quelques podcasts je me suis dit qu'on pourrait utiliser ces sources de nouveautés sur Geek Radio, passer tous les jours à 22h les dernières nouveautés de tel netlabel ou de tel DJ. Il suffirait d'un petit script à interfacer avec liquidsoap à coups de protocole et callback de diffusion. A l'occasion je ferai ça vite fait en Ruby, &lt;a href="http://libxml.rubyforge.org/doc/"&gt;les&lt;/a&gt; &lt;a href="http://raa.ruby-lang.org/project/ruby-sqlite/"&gt;outils&lt;/a&gt; sont tout prêts pour un petit frère de &lt;a href="http://svn.sourceforge.net/viewcvs.cgi/savonet/trunk/bubble/src"&gt;bubble&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pour finir sur liquidsoap, il est encore tôt pour promettre un release proche, d'autant que je ne manque pas de boulot ces jours-ci. Mais on s'approche d'un produit utilisable de qualité. J'ai eu vent via linuxfr du &lt;a href="http://barcamp.org/TheRulesOfBarCamp"&gt;BarCamp&lt;/a&gt; &lt;a href="http://barcamp.org/BarCampParisSiliconSentier"&gt;Paris&lt;/a&gt; du 10 juin. Le concept de non-conférence sans spectateurs (que des acteurs) me plait bien, et je suis tenté de présenter le projet Savonet là bas. Mais ça risque d'être un peu short à préparer.&lt;br /&gt;&lt;br /&gt;Enfin je voulais de nouveau pointer le blog des langages de programmation, &lt;a href="http://lambda-the-ultimate.org"&gt;Lambda The Ultimate&lt;/a&gt;. C'est une bonne source de news, regroupant points de vue "académiques" et "pragmatiques". Ces jours-ci on voit un regain d'activité longtemps attendu, avec l'arrivée de nouveaux éditeurs. Aujourd'hui j'ai lu un &lt;a href="http://developer.mozilla.org/presentations/xtech2006/javascript/"&gt;slideshow&lt;/a&gt; (HTML+Javascript) présentant Javascript 2. &amp;Ccedil;a fait plaisir: tout en restant bien sûr un langage pragmatique, il évolue vers plus de structure, empruntant à Python mais aussi à la programmation fonctionnelle statiquement typée. Cela semble plus que raisonnable pour favoriser l'utilisation de Javascript sur de gros projets.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114891564041957327?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114891564041957327/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114891564041957327' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114891564041957327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114891564041957327'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/tes-lacets-sont-des-fes.html' title='Tes lacets sont des fées'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114824498106395587</id><published>2006-05-21T22:41:00.000+02:00</published><updated>2007-08-24T04:23:51.947+02:00</updated><title type='text'>Un serveur très select..</title><content type='html'>Le retour du post geekesque !&lt;br /&gt;&lt;br /&gt;Il y a quelques années il me semble avoir lu dans Linux Magazine un article expliquant comment programmer en C un serveur léger et rapide sans threads. Jusque récemment, &lt;a href="http://savonet.sf.net/wiki/Liquidsoap"&gt;liquidsoap&lt;/a&gt; (qui offre quelques interactions via une interface telnet) utilisait un serveur à base de threads: un thread écoute sur le serveur et accepte les clients, lance un nouveau thread par client pour traiter ses requêtes. C'est mauvais: au bout de 30 clients on a 30 threads, ce qui plombe l'application; et en plus les clients ne sont pas vite servis, la création de leur thread étant coûteuse. J'ai enfin changé ça, en utilisant l'appel système &lt;code&gt;select&lt;/code&gt; pour attendre un ensemble d'évenements sur des sockets. C'est ultra simple et ça marche impeccable.&lt;br /&gt;&lt;br /&gt;L'article de Linux Mag aurait pu être écrit en Caml au lieu de C: au lieu de fournir un exemple de serveur, on peut en programmation fonctionnelle implémenter un serveur générique se chargeant d'ordonnancer des pseudo-threads représentés par des fonctions. Je vous le livre ici. Accessoirement, j'ai cherché à trouver ce genre de code tout prêt sur le net avant de l'écrire. Peut être que j'épargnerai du boulot à quelqun.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;type task =&lt;br /&gt;  | Read    of (Unix.file_descr * (unit -&gt; unit))&lt;br /&gt;  | Write   of (Unix.file_descr * (unit -&gt; unit))&lt;br /&gt;  | Special of (Unix.file_descr * (unit -&gt; unit))&lt;br /&gt;&lt;br /&gt;let scheduler init =&lt;br /&gt;  let read    = ref [] in&lt;br /&gt;  let write   = ref [] in&lt;br /&gt;  let special = ref [] in&lt;br /&gt;  let add set a = set := a :: !set in&lt;br /&gt;  let add = function&lt;br /&gt;    | Read    (s,f) -&gt; add read    (s,f)&lt;br /&gt;    | Write   (s,f) -&gt; add write   (s,f)&lt;br /&gt;    | Special (s,f) -&gt; add special (s,f)&lt;br /&gt;  in&lt;br /&gt;  let process set sockets =&lt;br /&gt;    (* Events are triggered on a list of sockets.&lt;br /&gt;     * Execute the corresponding handlers, and remove them from the set. *)&lt;br /&gt;    let f = List.map (fun s -&gt; List.assoc s !set) sockets in&lt;br /&gt;      set := List.filter (fun (s,_) -&gt; not (List.mem s sockets)) !set ;&lt;br /&gt;      List.iter (fun f -&gt; f ()) f&lt;br /&gt;  in&lt;br /&gt;    init add ;&lt;br /&gt;    while true do&lt;br /&gt;      let r,w,x =&lt;br /&gt;        Unix.select&lt;br /&gt;          (List.map fst !read) (List.map fst !write) (List.map fst !special)&lt;br /&gt;          (-1.)&lt;br /&gt;      in&lt;br /&gt;        process read r ;&lt;br /&gt;        process write w ;&lt;br /&gt;        process special x&lt;br /&gt;    done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pour les curieux le code complet est &lt;a href="http://svn.sourceforge.net/viewcvs.cgi/*checkout*/savonet/trunk/liquidsoap/src/tools/server.ml?rev=2463"&gt;sur le SVN&lt;/a&gt; de Savonet, avec enregistrement et traitement des clients..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114824498106395587?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114824498106395587/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114824498106395587' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114824498106395587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114824498106395587'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/un-serveur-trs-select.html' title='Un serveur très select..'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114817751442660006</id><published>2006-05-21T03:57:00.000+02:00</published><updated>2006-05-21T04:18:12.630+02:00</updated><title type='text'>Mall of America</title><content type='html'>Je cherche des petits cadeaux pour Lucie et Cyrille. Mon maître de thèse m'a signalé qu'une des attractions du coin est &lt;em&gt;Mall of America&lt;/em&gt;, le plus grand centre commercial des Etats-Unis. Je me dis que c'est l'occasion de bouger un peu. En plus, pour y aller je visite aussi le tramway, c'est folklo. Sur le retour j'ai même eu droit à un trajet en bus, encore plus folklo avec un conducteur un peu foldingue qui me donnait pas trop confiance sur la destination, et comme compagnons ceux qui n'ont pas assez de pognon pour se payer une caisse.&lt;br /&gt;&lt;br /&gt;Mall of America, c'est grand. Trois ou quatre étages de galeries, et au centre un parc d'attraction. Mais putain qu'est-ce que c'est nul. Des magasins de merde, des magasins de pouf... pas l'ombre d'un souvenir ou d'un truc potable à acheter, pas l'ombre d'une librairie décente, une honte vu les proportions de l'endroit. Au bout de deux heures je me casse, me jurant de ne plus écouter mon maître de thèse pour les questions touristiques.&lt;br /&gt;&lt;br /&gt;Descendant du tram je décide de trainer en ville, ce qui ne me remonte pas vraiment le moral: le business center est mort comme tout un samedi soir. Au bout de quelques blocs, j'arrive quand même à viser un coin animé et là miracle, je trouve une grande librairie. Des livres, des comics, des DVD, miam. Elle est encore ouverte. Peu après que je rentre une annonce prie les client jeunes de sortir, et demande à ceux qui restent d'être en mesure de justifier leurs 21 ans. Je me dis qu'ils vont ptêtre ramener de la bière et des filles.. Finalement non, et pour me consoler je me suis acheté &lt;em&gt;Jackie Brown&lt;/em&gt;. L'ambiance loose de mon séjour, l'hôtel un peu glauque, le centre commercial, les gens mornes, tout ça me fait trop penser à ce film. Et à &lt;em&gt;The Big Lebowski&lt;/em&gt; aussi, mais cui-là je l'ai vu ya pas longtemps.&lt;br /&gt;&lt;br /&gt;Descendant du bus fou qui me ramène dans mon quartier, je décide aussi d'enfin visiter le &lt;em&gt;liquor shop&lt;/em&gt;. Je choisis un simple pack de Corona parmi tout l'alcool qu'on y trouve. A la caisse je saute au plafond devant le prix, doit y avoir au moins 70% de taxes. Et pour faire couleur locale, on me demande ma carte d'identité et m'emballe le pack de bières dans un sac en carton marron. Dernière péripétie: ouvrir les bières sans outil approprié. Je sais que certains font ça avec leurs clés. J'y arrive aussi, mais je me suis salement coupé le doigt au passage...&lt;br /&gt;&lt;br /&gt;Quelle aventure, ce voyage.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114817751442660006?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114817751442660006/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114817751442660006' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114817751442660006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114817751442660006'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/mall-of-america.html' title='Mall of America'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114805088760396373</id><published>2006-05-19T16:58:00.000+02:00</published><updated>2006-05-19T17:01:27.616+02:00</updated><title type='text'>Trio</title><content type='html'>Le créneau chanson française est en place sur Geek Radio. Du coup j'entends "Je me tire" de Tryo. J'ai toujours eu un problème avec cette chanson:&lt;br /&gt;&lt;em style="white-space:pre"&gt;Tire-lui une balle,&lt;br /&gt;ce mec-là t'a fait du mal,&lt;br /&gt;ta vengeance est normale,&lt;br /&gt;l'Etat ne peut pas l'accomplir..&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114805088760396373?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114805088760396373/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114805088760396373' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114805088760396373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114805088760396373'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/trio.html' title='Trio'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114792771034502558</id><published>2006-05-18T04:32:00.000+02:00</published><updated>2006-05-19T05:20:42.613+02:00</updated><title type='text'>Moi</title><content type='html'>Cher lecteur, tu te demandes comment je vais, ce que je mange et si mes selles sont bien formées ? Encore une fois, tu seras servi...&lt;br /&gt;&lt;br /&gt;L'applet météo de Minneapolis bat celle de Paris depuis deux jours. Il fait grand soleil ici, c'est très agréable. Je suis de fort bonne humeur, etc. J'ai mangé un bo-bun pas mauvais, des sushis pas super bons, un plat de pâtes délicieux à midi et une pizza chère (pour ici) mais fort bonne aussi ce soir. Je ne vous ferai pas de critique culinaire du genre de sandwich grec au rosbiff qu'ils vendent pas loin d'ici, et je suis sûr que vous me comprendrez même sans avoir vu la photo choquante du truc.&lt;br /&gt;&lt;br /&gt;Récemment, j'ai acheté un pot de glace Ben&amp;Jerry's au café. En vrai, le café n'est que le goût de la crème, mais ce serait trop léger de s'arrêter à la crème glacée, trop simple. La glace cache en fait de bons gros morceaux de caramel.. pouah. Mon frigo débloque et a de toute façon laissé fondre le pot de glace dans le compartiment congélo; dans le même temps il glace mes bouteilles d'infâme &lt;em&gt;root beer&lt;/em&gt; dans le compartiment normal. Au fait, à ma troisième bouteille de cette boisson (faut bien les finir) j'identifie enfin le goût: Hextril, le bain de bouche...&lt;br /&gt;&lt;br /&gt;Dans ma chambre j'ai la télé, pub à gogo en général, et pour le film Da Vinci Code en particulier. J'ai aussi vu un reportage pourri sur l'Opus Dei, et des croyants qui s'insurgent de ce que le livre raconte, mélangeant réalité et fiction en faisant croire aux gens que l'Eglise se fout d'eux... en guise de réponse j'aime bien un truc que j'ai dû lire sur le net: il devrait y avoir un avertissement au début de la Bible comme quoi c'est une fiction. Plus sérieux, j'ai vu Bush raconter qu'il va fliquer plus aux frontières, et j'ai appris qu'un Etat interdit maintenant aux couples non mariés la garde de plus d'un enfant.&lt;br /&gt;&lt;br /&gt;J'allais oublier la nouvelle du jour: Gopalan m'a emmené dans un magasin de bouffe assez grand. J'y ai trouvé du beurre de cacahète, des cookies.. et surtout des fruits qu'ont l'air bons ! Mais ce soir je crois que je vais opter pour le microwave pop-corn, plus couleur locale. Parlant de beurre de cacahuète j'ai entendu dans une série télé de fou (mix de &lt;em&gt;Starsky et Hutch&lt;/em&gt; et de &lt;em&gt;Laurel et Hardy&lt;/em&gt;) un dicton qui me plait beaucoup: life is like peanut butter, some like it chunky, some don't...&lt;br /&gt;&lt;br /&gt;Pendant ce temps là, ça bosphore.. C'est super productif de discuter les choses à fond. Quand on creuse des trucs qui paraissent évidents on s'aperçoit qu'il y a des détails délicats à prouver... des détails peut-être un peu chiants, mais à prouver quand même. A force de discussions je me retrouve donc avec une preuve à écrire, une optimisation à programmer, une autre optimisation délicate à concevoir... Ce voyage me fait décidemment bien bosser. Mais afin de me remettre en question comme il se doit, je m'astreins avec regret à bidouiller la radio le soir dans ma chambre ;p&lt;br /&gt;&lt;br /&gt;Le temps passe plutôt vite. Déja cinq jours sur dix. Prévoyant mon retour, je me laisse pousser la barbe. Ce week-end je vais faire des UV, m'acheter un turban et apprendre l'arabe, histoire d'avoir des péripéties douanières à raconter sur mon retour, qui sera sinon probablement bien monotone par rapport à l'aller.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114792771034502558?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114792771034502558/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114792771034502558' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114792771034502558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114792771034502558'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/moi.html' title='Moi'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114789132664619395</id><published>2006-05-17T20:32:00.000+02:00</published><updated>2006-05-17T20:42:06.663+02:00</updated><title type='text'>Spicy Thai &amp; Dark Apple</title><content type='html'>Hier j'ai bouffé dans un petit restau thai. C'était très bon mais très épicé. A part ça j'ai découvert un quartier super sympa. Beaucoup de verdure, des écureuils qui courent et même un petit lapin... des maisons d'étudiant, nommées genre &amp;delta;&amp;nu;&amp;epsilon;, faudra que je pige un jour. Notes folkloriques du jour: à l'entrée de l'opéra on lit "no guns"... en couverture du botin une pub pour un cabinet d'avocats "call 1-888-NOT GUILTY"...&lt;br /&gt;&lt;br /&gt;Dans un registre complètement différent, je suis assez sidéré de la rapidité avec laquelle Apple sombre du côté obscur aux yeux de la foule, son image de marque devenant de plus en plus floue.. En partie la rançon du succès, mais aussi pour de vraies raisons, notamment leur pratiques de vente liée avec les Mac, l'iPod et l'iTunes Music Store, ainsi que leur pression sur les politiques français pour l'impunité des DRMs. Je lis récemment un &lt;a href="http://arstechnica.com/news.ars/post/20060517-6852.html"&gt;post&lt;/a&gt; super alarmant: ils ferment le source du noyau sous OSX. Le genre de truc qui te fait aimer la GPL, pour sa contamination aux forks. En plus ils envisageraient d'utiliser Trusted Computing, le nouveau nom de Palladium si j'ai bien suivi... Ca pue sévère.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114789132664619395?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114789132664619395/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114789132664619395' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114789132664619395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114789132664619395'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/spicy-thai-dark-apple.html' title='Spicy Thai &amp; Dark Apple'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114780721814352153</id><published>2006-05-16T21:08:00.000+02:00</published><updated>2006-05-16T21:22:04.563+02:00</updated><title type='text'>Newline-sensitive parser</title><content type='html'>Pour préserver le côté geek de ce blog il faut que je vous parle d'une petite trouvaille qui me plait bien. Les langages comme Python ou Ruby ont réussi à abolir le point virgule. Pour cela leur syntaxe se doit de tenir compte des retours à la ligne, au moins: il faut différencier les deux bouts de code suivants.&lt;br /&gt;&lt;code style="white-space:pre"&gt;&lt;br /&gt;# Exemple 1&lt;br /&gt;objet.methode&lt;br /&gt;(1,2)&lt;br /&gt;# Exemple 2&lt;br /&gt;objet.methode(1,2)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Le parser de Python est compliqué par la prise en compte de l'indentation comme délimiteur de blocs. Celui de Ruby devrait être plus simple, mais je peux pas vous dire j'y pige rien. Toujours est-il que jusqu'à hier j'avais pas de solution acceptable pour Liquidsoap, car je voulais coller à l'architecture classique à base de lex/yacc -- simple et donc compréhensible, pour le codeur comme l'utilisateur. Voici la recette pour alléger votre langage sans introduire d'ingrédient dangereux pour la santé.&lt;br /&gt;&lt;br /&gt;Au niveau du lexer, on distingue le token VAR (symbole de variable) de VARPAR qui fusionne une variable avec une parenthèse ouvrante séparée par des espaces. Ce sera le seul endroit où un retour à la ligne est distingué d'un autre espacement. Grâce à ce nouveau token on distingue proprement les deux exemples cités plus haut. Mon premier exemple de code apparait au parser comme VAR PAROPEN EXPR COMMA EXPR PARCLOSE, le second comme VARPAR EXPR COMMA EXPR PARCLOSE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114780721814352153?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114780721814352153/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114780721814352153' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114780721814352153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114780721814352153'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/newline-sensitive-parser.html' title='Newline-sensitive parser'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114780542998286112</id><published>2006-05-16T20:28:00.000+02:00</published><updated>2006-05-16T20:50:30.040+02:00</updated><title type='text'>Root Beer &amp; Indian Music</title><content type='html'>Je commence pas très bien ma journée d'hier. Petit dejeuner pas super, salle petite et crasseuse, café lavasse et beignets trop lourds. Au lunch, pâtes trop lourdes, trop de fromage, trop de crème. Autour de 17h je décide de me faire un apéro en solo, chips et bière, pour me réconforter avant d'aller voir un concert de musique indienne.&lt;br /&gt;&lt;br /&gt;Je connais qu'un magasin de bouffe par ici. Facile de trouver des chips, les paquets sont géants par contre, ainsi que la dip sauce. J'en profite pour embarquer du pop-corn micro-onde, c'est pas mauvais et rien que le regarder gonfler est un plaisir. Et deux pommes, qui s'avèrent par la suite être assez mauvaises. Par contre je trouve pas grand chose niveau bière, juste un pack d'un machin appelé &lt;em&gt;root beer&lt;/em&gt;, avec un packaging à l'ancienne. J'ai vite réalisé mon erreur. La &lt;em&gt;root beer&lt;/em&gt; n'est PAS de la bière, n'en achetez JAMAIS. Ca ressemble plus à du sirop pour la toux pétillant, ou du dentrifice liquide qui fait roter. Pouah.&lt;br /&gt;&lt;br /&gt;Gopalan m'explique dans la voiture, en route pour le concert, que la vente d'alcool suppose l'obtention d'une license, et que la loi du Minnesota interdit de plus la présence de deux points de vente d'alcool à moins de quelques centaines de mètres l'un de l'autre. Faudra que je fasse un tour au &lt;em&gt;liquor shop&lt;/em&gt; du coin.&lt;br /&gt;&lt;br /&gt;Le concert était super par contre. Ca commence assez traditionnel, mais ça dérape assez vite sur du très inattendu. La musique nord indienne est traditionnellement portée sur l'impro, les mecs en profitent à mort. Le show est axé sur les percussions, qui sont exploitées de façon impressionante, c'en est presque mélodique. Je peux pas en dire beaucoup plus, vous aviez qu'à écouter. Le genre de spectacle capable de bouleverser un point de vue sur les percus... mais moi j'avais déja vu un solo de batterie au parc floral qui reste quand même complètement mythique dans ma tête. A part ça c'était rigolo, la salle était forcément pas mal remplie d'indiens, dont pas mal étaient habillé plus ou moins traditionellement. Je n'ai qu'un aperçu biaisé, mais il me semble que les US c'est quand même pas mal niveau intégration. Bon ils sont en train d'augmenter encore le fliquage à leurs frontières, les causasiens flippent de la montée des hispaniques, parait-il.. mais le jour où on diagnostiquera ça en France, ce sera déja un progrès.&lt;br /&gt;&lt;br /&gt;Après j'ai mangé une pizza même pas mauvaise. Ce matin il faisait super beau. Je me suis aperçu que je pouvais prendre mon petit dej sur une terrasse. C'est au dessus du parking, mais c'est le paradis à côté de la salle. Le &lt;em&gt;jet lag&lt;/em&gt; s'atténue, je commence à me lever tôt, j'ai plus besoin de me gaver de donuts pourris le matin et je me fais au café dilué. La journée commence bien. Au lunch je me rattrape avec un vrai &lt;em&gt;espresso&lt;/em&gt;, qui en plus est pas du tout cher par rapport à Paris, $1.4 soit moins de $2 après les taxes et le pourboire. Bref, je commence à me plaire ici. Mais vivement la cuisine française quand même.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114780542998286112?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114780542998286112/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114780542998286112' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114780542998286112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114780542998286112'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/root-beer-indian-music.html' title='Root Beer &amp; Indian Music'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114766722580124108</id><published>2006-05-15T05:59:00.000+02:00</published><updated>2006-05-15T06:27:05.813+02:00</updated><title type='text'>The Next 700 Programming Languages</title><content type='html'>J'ai lu récemment &lt;em&gt;The Next 700 Programming Languages&lt;/em&gt;, un article de Landin, datant de 1966. Parce que le titre me plaisait bien, et qu'on m'a dit que c'était une référence dans le domain de la conception des langages de programmation. Vu de 2006 ça parait un peu simpliste, mais l'auteur ébauche en réalité des idées très nouvelles et très importantes. Ca me fait réaliser que l'informatique (j'ose pas dire la science, mais je le pense à moitié) avance plutôt par des déplacements lents de perspective que par des découvertes brutales et techniques. Dans cet article, Landin inspire de nombreux langages de programmation modernes, dont Haskell et la famille ML. Il développe un langage abstrait (&lt;em&gt;ISWIM&lt;/em&gt; pour &lt;em&gt;If you See What I Mean&lt;/em&gt;) réellement de haut niveau, dont le sens est clairement défini. Pour preuve de cela il exhibe des équations exprimant des propriétés simples des programmes, essentiellement des règles de substitution. Je n'en connais pas assez pour l'affirmer vraiment, mais il a tout l'air de lancer l'idée de la sémantique des langages de programmation. Lisez le vous même, voici quelques morceaux choisis.&lt;br /&gt;&lt;br /&gt;Landin a l'idée d'isoler l'impératif du fonctionnel, ce qui donnera plus tard les monades de Haskell: &lt;em&gt;The author thinks that the fruitful development to encompass all ISWIM will depend on establishing "safe" areas of an ISWIM expression, in which imperative features can be disregarded.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Il propose d'ailleurs une dénomination que je préfère à "fonctionnel": &lt;em&gt;The word "denotative" seems more appropriate than nonprocedural, declarative or functional. The antithesis of denotative is "imperative".&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Moins frappant, mais à mon sens une bonne description des qualités de ML: &lt;em&gt;The special claim of ISWIM is that it grafts procedural notions onto a purely functional base without disturbing many of the desirable properties.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Je trouve qu'il y a beaucoup d'idées là dedans, et en général un bel effort de conception rigoureuse des langages de programmation. Le genre de chose qu'on voudrait voir plus souvent. Perl c'est rigolo, mais je trouve ça de plus en plus tristement antique. Les Perleux diront bien sûr que Perl cherche à être un langage naturel, favorisant la créativité, que c'est de l'art, bla bla. Je dis que la programmation n'est pas un art, mais un artisanat, ce qui n'exclut pas le plaisir du travail bien fait, mais met en avant la finalité. C'est pas de la peinture, c'est plus proche de l'horlogerie.&lt;br /&gt;&lt;br /&gt;Les langages &lt;em&gt;pop&lt;/em&gt; plus récents (Ruby,Python,Javascript,..) semblent cependant évoluer dans la bonne direction. Ils deviennent plus fonctionnels, et ont une notion de portée lexicale plus claire. Côté Ruby et Python on remarque que la (re-)définition remplace souvent implicitement l'assignation, à l'opposé des variables globales bordéliques de la génération Perl. Cela dit, je suis pas complètement heureux avec ça non plus, je trouve qu'on se fait vite piéger par les définition-par-défaut et on n'arrive plus à faire des assignations là où on le veut.&lt;br /&gt;&lt;br /&gt;Voila.. j'avais deux trois trucs à cracher sur la prog :p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114766722580124108?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114766722580124108/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114766722580124108' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114766722580124108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114766722580124108'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/next-700-programming-languages.html' title='The Next 700 Programming Languages'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114766337495985201</id><published>2006-05-15T04:41:00.000+02:00</published><updated>2006-05-15T06:50:37.663+02:00</updated><title type='text'>En voyage</title><content type='html'>Finalement j'abandonne l'idée de trouver un adaptateur SDCard-USB ou une carte wifi pour mon Palm, et je recopie simplement la tartine écrite dans l'avion..&lt;br /&gt;&lt;br /&gt;L'aventure commence plus tôt que prévu, dès l'enregistrement à l'aéroport Charles de Gaulle. Je signale que je n'ai pas de visa, étant un simple visiteur de courte durée. L'hôtesse sait que cela suppose aussi que mon passeport ait été émis dans le bon intervalle de temps, mais ne se souvient pas des conditions. De mon côté pas de panique, j'ai vérifié sur le site de l'ambassade et auprès de l'agence de voyage de l'INRIA: il n'est ni trop vieux pour ne pas être optique, ni trop récent pour devoir être biométrique -- ce qui est encore impossible en France de toute façon. L'hôtesse demande à sa chef, qui appelle quelque, qui sait pas. On appelle ensuite la police. Verdict de la PAF: il me faut un visa, je ne peux donc pas embarquer. Je l'ai quand même un peu mauvaise et j'insiste pour qu'ils vérifient, je suis sûr de mon coup, je peux pas sortir un visa de mon chapeau, l'INRIA va l'avoir mauvaise, etc. Coup de bol la police répond plus et un pilote de passage souffle à mon interlocutrice d'aller demander au guichet d'United Airlines. Après poireautage, on m'annonce enfin que je suis en règle. Sans blague. Je procède à l'enregistrement bon dernier. Comment les hôtesses ET les flics peuvent ne pas savoir ce genre de truc, je sais pas..&lt;br /&gt;&lt;br /&gt;Je finis les formalités pas particulièrement joyeux, j'ai pas droit à beaucoup d'excuses ou de sourires. Le plus sympa dans l'affaire ça reste le mec qui m'a fouillé, me signifiant d'une mimique que j'avais beau faire sonner la porte, il ferait pas de zèle.&lt;br /&gt;&lt;br /&gt;Dans l'avion je commence la lecture de "Da Vinci Code". Je ne trouve pas ça foudroyant niveau suspens, mais ça reste assez efficace. L'intrigue générale est sympa. Dans les détails, c'est agaçant, l'auteur nous propose son interprétation de mythomane du sens de.. tout. C'est douteux au possible, et souvent déja vu. En plus, c'est pas super bien écrit, remplit à coups de platitudes ridicules. J'en dirais pas plus, ça m'a occupé un long trajet d'avion pendant lequel j'aurais pas pu faire grand chose de plus intelligent, et ça ne vaut pas mieux que ça. Le traducteur écrit "bitte" avec deux "t" et ne se trompe peut-être pas, finalement. Faut que je vérifie, ça me bouleverse. Par contre je relève un "acquiT de conscience" bien moche et une traduction un peu trop litérale de &lt;em&gt;climbing&lt;/em&gt;: "Avez vous déja escaladé la tour Eiffel ?"&lt;br /&gt;&lt;br /&gt;J'ai ensuite changé d'avion après une escale courte à Reykjavik. Malheureusement c'est encore un petit Boeing, assez bruyant donc. Mais le détour par l'Islande vaut le coup. Déja ça coupe le voyage en deux parties de longueur raisonnable. Surtout la vue est impressionante. Le morceau d'Islande que j'ai vu est super aride. Une terre sombre et sèche, de grandes fissures.. sans exagérer, on dirait une bouse de vache géante, séchée et bien plate. Une route et quelques groupes de batiments sur la côte. On doit pas rigoler tous les jours ici, et on doit s'inquiéter de la montée du niveau des océans.&lt;br /&gt;&lt;br /&gt;Bon, ça n'est qu'un petit morceau de l'Islance. D'ailleurs en repartant je vois au loin une chaîne de montagnes plutôt imposante. Et surtout, peu après, la banquise ! Plutôt un troupeau avancé d'icebergs pour être honnête. Mais tout de même énormes, à en juger par notre altitude. On croirait presque des nuages, mais c'est bien de la glace.. Iki ikii kik !!! Par la suite j'ai droit à une étonnante variété de mélanges de glace, terre sombre et océan. On survole le Groenland, en fait.&lt;br /&gt;&lt;br /&gt;Arrivé à Minneapolis j'ai eu droit à la mythique procédure d'admission aux US. Questionnaire: suis-je un terroriste ? anarchiste ? ai-je collaboré avec les nazis ? Non Monsieur, rien de tout ça. Très bien. Pourquoi je viens aux US ? Je suis thésard en informatique, en visite à l'Université du Minnesota, aux frais de l'INRIA. Bizarrement, ils trouvent ça plus douteux. Il trouvent bizarre que je vende pas de logiciel et ne sollicite aucun financement de la part des US. Ils me le demandent trois fois, et font aussi mine de vérifier que j'étudie bien l'informatique, mais sont vite perdus dans mes explications sur la logique, la vérification de spécifications formelles.. Finalement, je leur propose de demander confirmation au thésard américain qui m'attend à la sortie, ce qui me sauve. Après une attente pas si courte (pendant laquelle les douaniers se demandent s'ils peuvent pas trouver un "crazy test" à me faire passer pour vérifier que suis bien un thésard) on me file mon visa de simple visiteur, après avoir relevé mes empreintes digitales et pris ma photo.&lt;br /&gt;&lt;br /&gt;La suite est beaucoup plus monotone. Des voitures partout, hôtel moyen, énorme petit dej à coups de donuts, café dilué à mort, les rues ressemblent à ce qu'on imagine des rues américaines, la nuit les flics et les pompiers jouent avec leur sirène, ya pas beaucoup de restos ou de magasins de bouffe potable dans le coin, on me conseille d'y filer au moins 15% en pourboire aux pauvres serveurs esclavagisés, il y a une bible sur la table de ma chambre d'hôtel... Voila. Peu de compagnie le soir, pour l'instant en tout cas, mais il y a le wifi dans ma chambre :p&lt;br /&gt;&lt;br /&gt;Dans la suite de mes aventures, j'essaierai de visiter le plus grand supermarché des Etats Unis, de trouver les transports en commun dans cette grande ville, et surtout d'acheter des fruits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114766337495985201?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114766337495985201/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114766337495985201' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114766337495985201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114766337495985201'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/en-voyage.html' title='En voyage'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114757343869354242</id><published>2006-05-14T04:21:00.000+02:00</published><updated>2006-05-14T04:23:58.703+02:00</updated><title type='text'>Loin</title><content type='html'>Je suis à Minneapolis. J'ai eu un peu de mal mais ça y est. Par contre j'ai oublié trois trucs. Mon appareil photo, donc pas d'images; mon cable Palm-PC, donc pas moyen d'envoyer le post rédigé dans l'avion; un adaptateur pour prises US, donc pas moyen de m'attarder faute de batterie... une grande aventure &amp;agrave; suivre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114757343869354242?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114757343869354242/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114757343869354242' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114757343869354242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114757343869354242'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/05/loin.html' title='Loin'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114604319609666016</id><published>2006-04-26T11:19:00.000+02:00</published><updated>2006-04-26T11:53:18.000+02:00</updated><title type='text'>The Knight who says Yi</title><content type='html'>Heimdall me parle du SummerOfCode Haskell, et me fait ainsi découvrir &lt;a href="http://www.cse.unsw.edu.au/~dons/yi.html"&gt;Yi&lt;/a&gt;, un éditeur de texte écrit en Haskell qui prétend être plus dynamique qu'Emacs. L'auteur explique dans &lt;a href="http://www.cse.unsw.edu.au/~dons/papers/yi.ps.gz"&gt;un article&lt;/a&gt; comment concevoir des applications complètement dynamiques, dans un langage compilé et statiquement typé comme Haskell -- il a aussi conçu le &lt;a href="http://www.cse.unsw.edu.au/~dons/lambdabot.html"&gt;&amp;lambda;bot&lt;/a&gt; IRC de #haskell selon la même méthode.&lt;br /&gt;&lt;br /&gt;L'article ne présente pas un nouveau langage ni même un nouveau compilo, mais une méthodologie de développement qui permet de faire une application reconfigurable à chaud, dans laquelle on peut même changer des morceaux de code à chaud. C'est un peu gros d'affirmer que le résultat est plus dynamique qu'Emacs, on voit sur la fin les limites du modèle quand il aborde les commandes type &lt;code&gt;:map&lt;/code&gt;, autant dire qu'il y a pas de jolie solution pour le &lt;code&gt;M-x&lt;/code&gt; d'Emacs. Mais au fond, on peut peut-être se passer de ces choses là. Malgré ces excès, l'article est très intéressant et élégant, et surtout casse des idées reçues sur les langages dynamiques. Avoir un langage statique compilé permet aussi de faire plein de trucs "dynamiques".&lt;br /&gt;&lt;br /&gt;Tout ça nous ramène à &lt;a href="http://home.gna.org/bed"&gt;bed&lt;/a&gt;, un éditeur écrit en OCaml qu'on avait commencé avec comme idée centrale de faire le procédé de colorisation/indentation de façon plus jolie en adaptant les techniques bien connues de lexing/parsing de façon plus maline que d'hab. Le développement avait bloqué au moment de faire l'éditeur lui-même pour des problèmes de design, et ce genre de lecture est peut-être un pas vers une solution, un jour. C'est plus raisonnable que mon autre scénario de reprise, qui passait par la création d'un langage de prog plus adapté, que la killer-app bed aurait ainsi popularisé en retour comme le premier langage statique dynamique.&lt;br /&gt;&lt;br /&gt;En attendant, la fondation Haskell propose un projet Summer of Code sur l'éditeur Yi, il s'agit d'&lt;a href="http://hackage.haskell.org/trac/summer-of-code/ticket/21"&gt;ajouter la colorisation et l'indentation&lt;/a&gt;... Je suis curieux de voir ce que ça donne.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114604319609666016?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114604319609666016/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114604319609666016' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114604319609666016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114604319609666016'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/knight-who-says-yi.html' title='The Knight who says Yi'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114600450730551667</id><published>2006-04-26T00:19:00.000+02:00</published><updated>2006-04-26T01:08:23.080+02:00</updated><title type='text'>XFesse</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/MASToK.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/320/MASToK.png" border="0" alt="" /&gt;&lt;/a&gt;&amp;Agrave; ma gauche le logo d'un vieux projet mort et enterré que je compte pas du tout déterrer. L'ours en slip a même une histoire qui remonte à &lt;a href="http://mrpingouin.free.fr"&gt;avant&lt;/a&gt; mes premières lignes de code. Et ce n'est pas fini pour lui, puisque sur idée de Romain, il pourrait devenir la mascotte de &lt;a href="http://savonet.sf.net/wiki/Liquidsoap"&gt;liquidsoap&lt;/a&gt;. &amp;Agrave; venir...&lt;br /&gt;&lt;br /&gt;Un à-venir vraiment proche c'est Xfce 4.4, puisque la beta-1 est sortie il y a quelques jours. J'ai pu goûter au nouveau filemanager Thunar, dont j'avais déja vu les maquettes Python il y a un moment. Cela promettait, et je suis pas déçu du résultat. C'est simple et très efficace, ça fait penser au bon ROX avec quelques nouveautés, et une meilleure intégration aux standards freedesktop notamment pour le thème d'icône. Si j'utilise un filemanager graphique ce sera celui là. En attendant d'installer la totale de la 4.4 on peut jeter un oeil sur &lt;a href="http://xfce-diary.blogspot.com/"&gt;la liste de nouveautés d'Xfce&lt;/a&gt; et &lt;a href="http://thunar.xfce.org/news.html#2006-04-16"&gt;les dernières modifs de Thunar&lt;/a&gt;. Dans la foulée je donne aussi sa chance à &lt;a href="http://spuriousinterrupt.org/projects/xfmedia#screenies"&gt;Xfmedia&lt;/a&gt;. Plus délicat que "Google va-t-il réussir à rester &lt;em&gt;no evil&lt;/em&gt; ?", on se demandera aussi "Xfce va-t-il réussir à rester ergonomique et rapide au fil de ses évolution ?"... en ce moment, le mien démarre drôlement lentement, mais c'est ptêt de ma faute. Je conseille en tout cas vivement cet environnement de grande qualité, élégant de simplicité, bourré de bonnes idées et toujours en mouvement.&lt;br /&gt;&lt;br /&gt;Tant qu'on y est sur les nouveautés, j'ai quitté ma Google homepage pour la plus jolie et plus fonctionnelle page de &lt;a href="http://netvibes.com"&gt;NetVibes&lt;/a&gt;, qui remplit notamment un vrai rôle d'aggrégateur de flux, se souvient et affiche clairement ce que tu n'as pas encore lu.&lt;br /&gt;&lt;br /&gt;Autre nouvelle en vrac: ça se confirme, j'ai des visiteurs occasionnels à part vous trois à qui j'ai donné l'adresse de ce carnet, et pas que des visiteurs anodins, cf &lt;a href="http://misterpingouin.blogspot.com/2006/03/cduced.html"&gt;certains commentaires&lt;/a&gt;... J'ai le trac, faut que je me surveille un minimum sur la qualité :p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114600450730551667?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114600450730551667/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114600450730551667' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114600450730551667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114600450730551667'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/xfesse.html' title='XFesse'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114569846981847592</id><published>2006-04-22T11:24:00.000+02:00</published><updated>2006-04-23T13:39:52.143+02:00</updated><title type='text'>Retour de vacances</title><content type='html'>De retour de vacances, je pourrais vous faire un post sur une pizzeria de Bourg-St-Maurice, une critique du domaine skiable de Tignes/Val d'Isère, ou encore un comparatif crèmes solaires, ce serait encore plus branché que Gelnior. Mais non. Je pourrais aussi ne pas réussir à vous raconter comme le ski c'est bien, le surf encore mieux mais douloureux à en crier, la famille c'est chouette, surtout quand on l'a plus sur les pattes au quotidien mais seulement dans de bons moments comme ça.&lt;br /&gt;&lt;br /&gt;Mon appareil photo a accepté de s'allumer la veille du départ. Agréablement surpris je l'embarque. Mais au premier jour de ski il ne marche déja plus. Du coup pas de photo de ma gueule de kéké. Le soleil m'a cramé de façon alarmante. Maintenant je m'effrite comme une tête de beuh dans les mains de Romain.&lt;br /&gt;&lt;br /&gt;Voilà voilà, coupure quasi totale pendant une semaine, faut se remettre au rythme normal là. Ecrire un peu pour le labo deux trois pensées de télésiège. Lire toutes les news de geek qui sont tombées pendant mon absence, et chercher à synchroniser mon Palm avec le tout nouveau Google Calendar... La routine revient vite.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114569846981847592?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114569846981847592/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114569846981847592' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114569846981847592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114569846981847592'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/retour-de-vacances.html' title='Retour de vacances'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114493901413054043</id><published>2006-04-13T16:18:00.001+02:00</published><updated>2006-04-14T14:26:43.800+02:00</updated><title type='text'>Brisez les chaînes .. de caractères</title><content type='html'>Tout à l'heure je discutais avec mon père, il me reparle d'un problème qu'il a en Javascript, et me demande si j'y ai repensé. Je réponds légèrement que non j'y ai pas repensé, je vois pas le problème, etc. Il s'acharne. Alors je pose sur papier un schéma de ce que j'ai en tête. Et là tout s'éclaire...&lt;br /&gt;&lt;br /&gt;Vous faites du Javascript, en plein coeur de l'action vous avez quelques variables locales bien compliquées, genre une table de hachage, une fonction, des noeuds XML... Et vous voulez programmer une action à effectuer dans 42 secondes, qui devra utiliser ces données.&lt;br /&gt;&lt;br /&gt;On pense à setTimeout, qui prend une chaîne S et un entier N, et évalue S après N millisecondes. Problème: la chaîne est évaluée dans le contexte global, dans lequel on ne voit pas les merveilles qu'on a localement, et qu'on ne peut pas non plus facilement encoder dans la chaîne de caractères. Mon papa ne se décourage pas et programme un système permettant de réserver une place identifiée par un entier pour ranger les infos concernées dans une liste globale, et parle ainsi de ces objets en écrivant l'entier dans sa chaîne. Au bout d'un peu de code et de debug, on s'en sort. Et on est fier d'avoir implémenté un petit système d'allocation de mémoire.&lt;br /&gt;&lt;br /&gt;Pratiquant plutôt d'autres langages que je qualifierais de plus sains, j'avais en tête que setTimeout prend en paramètre une fonction F et un entier N, et appelle F() au bout de N millisecondes. Cela simplifie le problème, car Javascript lie les variables statiquement, c'est à dire que si dans ma F je parle de x et de n, il s'agit des x et n dans la portée de la définition de F. Du coup pas besoin d'aller faire des micmacs dans une variable globale ou à sérialiser des données complexes. On crée juste une fonction anonyme exécutant le boulot à faire dans 24 heures chrono, le plus naturellement du monde. Et ben figurez vous que le setTimeout de Javascript accepte aussi des fonctions comme je l'imaginais. Happy end.&lt;br /&gt;&lt;br /&gt;&lt;div style="width:60%;border:solid 1px black;background:#ccc;margin-left:auto;margin-right:auto;padding:15px"&gt;Morale: un bon design résout bien des problèmes. Vive le fonctionnel, mort à eval(), aux armes, etc.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;By the way, Python a relooké son site web. &lt;a href="http://python.org"&gt;Python.org&lt;/a&gt; fait très pro, voire trop. Par contre on ne sait trop que penser de la campagne de comm menée par &lt;a href="http://python.com"&gt;Python.com&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114493901413054043?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114493901413054043/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114493901413054043' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114493901413054043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114493901413054043'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/brisez-les-chanes-de-caractres_13.html' title='Brisez les chaînes .. de caractères'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114439762116482173</id><published>2006-04-07T10:07:00.000+02:00</published><updated>2006-04-13T16:17:34.526+02:00</updated><title type='text'>Radio time</title><content type='html'>J'ai passé beaucoup de temps ces derniers jours sur la préparation de mon &lt;a href="http://www.lix.polytechnique.fr/~dbaelde/productions/papers.html"&gt;séminaire thésard&lt;/a&gt;. C'est fini, et ça s'est plutôt bien passé. Maintenant je vais me faire plaisir pendant quelques jours en avançant liquidsoap. J'ai fixé des plus ou moins petits bugs, encore un peu changé la syntaxe, je vais finir par uniformiser les nommages dans l'API de scripts, stabiliser les transitions, etc. Deux nouvelles features:&lt;br /&gt;&lt;code style="white-space:pre"&gt;&lt;br /&gt;output.icecast(&lt;br /&gt;  mount="prout.ogg",&lt;br /&gt;  # La fonction suivante est appelée pour chaque paquet de metadata.&lt;br /&gt;  # Cela permet de loguer par exemple les fichiers diffusés, pour la SACEM.&lt;br /&gt;  on_metadata =&lt;br /&gt;    fun (m) -&gt; system("echo '"^assoc("initial_uri",m)^"' &gt;&gt; /tmp/appended"),&lt;br /&gt;  # Ici un exemple de requete dynamique assez débile,&lt;br /&gt;  # ça passe le premier fichier valide dans une playslist.&lt;br /&gt;  # Bien sûr chacun mettra ici son propre programme&lt;br /&gt;  # d'ordonnancement de playlist.&lt;br /&gt;  fallback([dyn_request(fun () -&gt;&lt;br /&gt;                          ("zob:ma playlist",&lt;br /&gt;                           get_process_lines("cat "^"/tmp/playlist"))),&lt;br /&gt;            one_file("/usr/share/mrpingouin/mp3/jingle/tue-sa-mort-sam.mp3")]))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;OK tout n'est pas clair mais avouez que vous sentez que ça rules :p Bon tout ça ne va pas sans mal et je ne prends pas toutes les précautions nécessaires. Du coup RadioPi était très malade hier soir (plusieurs évanouissements) et les jeunes qui voulaient faire un live ont dû être un peu déçus.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114439762116482173?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114439762116482173/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114439762116482173' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114439762116482173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114439762116482173'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/radio-time.html' title='Radio time'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114392297889291870</id><published>2006-04-01T22:20:00.000+02:00</published><updated>2006-04-05T08:53:07.206+02:00</updated><title type='text'>Misc</title><content type='html'>J'ai enchainé les petits post anodins et geeks ces temps-ci. Pour me réfréner j'ai décidé d'accumuler plusieurs autres liens dans un seul post, qui est désormais assez plein. Flush.&lt;br /&gt;&lt;br /&gt;Les prochaines applications à la mode seront mobiles ? Le Bluetooth offre des possibilités rigolotes, formant ce que certains appellent des Personal Area Networks.. Jouez à &lt;a href="http://www.age0.com/you-who/"&gt;Qui est-ce ?&lt;/a&gt; avec un inconnu dans le coin, ou partagez des fichiers de façon encore plus incontrôlable que le p2p avec &lt;a href="http://www.theregister.co.uk/2004/06/03/pocket_rendezvous/"&gt;Pocket RendezVous&lt;/a&gt;. Romain, la killer-app du futur que tu cherches est sûrement Bluetooth-enabled.&lt;br /&gt;&lt;br /&gt;Sinon, j'ai fait une émission très sympa sur &lt;a href="http://radiopi.org"&gt;RadioPi&lt;/a&gt; l'autre soir. On s'est dit qu'il faudrait se préparer pour la prochaine, que ce soit encore mieux. J'ai pas commencé à écrire les textes, mais j'ai trouvé des sites de sons. Allez vous immerger dans deux magnifiques sites de la communauté phonographiste, qui enregistre tout ce qui passe: &lt;a href="http://soundtransit.nl"&gt;SoundTransit&lt;/a&gt; et &lt;a href="http://soundscape-fm.net"&gt;SoundScape FM&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Enfin je suis retombé sur un dessin fait avec un nouveau design du blog en tête..&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/3187/1644/1600/truc.0.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/3187/1644/400/truc.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114392297889291870?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114392297889291870/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114392297889291870' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114392297889291870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114392297889291870'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/misc.html' title='Misc'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114389526450231836</id><published>2006-04-01T14:36:00.000+02:00</published><updated>2006-04-01T14:41:04.523+02:00</updated><title type='text'>Aha</title><content type='html'>Je suis tombé sur un scoop bien chaud ce matin, la sortie de &lt;a href="http://arstechnica.com/reviews/games/forever.ars"&gt;DukeNukem Forever&lt;/a&gt;!... J'ai vite réalisé qu'on est le 1er Avril. Drôle aussi: l'ajout de GOTO et COMEFROM dans &lt;a href="http://lambda-the-ultimate.org/node/1392"&gt;Php6&lt;/a&gt;. Ou encore une bonne &lt;a href="http://www.liberation.fr/page.php?Article=371691"&gt;blague&lt;/a&gt; à la française... qui &lt;a href="http://www.lemonde.fr/web/article/0,1-0@2-734511,36-756846,0.html?provenance=rss"&gt;fâche&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114389526450231836?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114389526450231836/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114389526450231836' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114389526450231836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114389526450231836'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/04/aha.html' title='Aha'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17133288.post-114381683654058745</id><published>2006-03-31T16:45:00.000+02:00</published><updated>2006-04-02T10:59:12.673+02:00</updated><title type='text'>Compilateur Scheme vers C</title><content type='html'>Je voudrais pas remplacer &lt;a href="http://lambda-the-ultimate.org/"&gt;Lambda the Ultimate&lt;/a&gt;, mais cette &lt;a href="http://www.iro.umontreal.ca/%7Eboucherd/mslug/meetings/20041020/minutes-en.html"&gt;présentation&lt;/a&gt; expliquant en 90 minutes comment réaliser un compilateur Scheme vers C de moins de 1000 lignes m'a impressioné... Ce n'est probablement pas la méthode de compilation la plus efficace mais ça me semble être une bonne solution pour les paresseux.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/17133288-114381683654058745?l=misterpingouin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://misterpingouin.blogspot.com/feeds/114381683654058745/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=17133288&amp;postID=114381683654058745' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114381683654058745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17133288/posts/default/114381683654058745'/><link rel='alternate' type='text/html' href='http://misterpingouin.blogspot.com/2006/03/compilateur-scheme-vers-c.html' title='Compilateur Scheme vers C'/><author><name>mrpingouin</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
