Da Asgeir's

« My MooWeb Blog with lots of Stuff` »

Mise à jour du site

Comme vous ne l'aurez sûrement pas remarqué, Da Asgeir's a été mis à jour. C'est dorénavant là que je placerai les articles de math, histoire de ne pas trop encombrer cette page.

Pour maintenir le site, j'utilise à présent le module Publish d'Org-Mode. Ainsi, le site et le blog sont maintenu via les mêmes outils, et c'est cool :)

Configuration

Si jamais ça intéresse quelqu'un-e, voici ma configuration pour org-publish.. J'utilise deux gros projets : dans mon dossier ~/a je place tous les articles en cours de rédaction. Lorsqu'un article est terminé, je le publie localement via org-publish-current-file. Cette publication a pour seul effet de copier le fichier .org dans mon dossier ~/w/asgeirs. J'entretiens ainsi une version locale du site, ne contenant que les fichiers .org (et les images, etc, mais pas les fichiers .html).

De là, j'appelle org-project sur asgeirs, qui exporte les fichiers org en fichiers html, et les envoie sur mon ftp.

(setq org-publish-project-alist
      '(("locarticles"
         :base-directory "~/a/"
         :recursive t
         :publishing-directory "~/w/asgeirs"
         :publishing-function org-publish-org-to-org
         :plain-source t)
        ("locimages"
         :base-directory "~/a/"
         :base-extension "jpg\\|png"
         :recursive t
         :publishing-directory "~/w/asgeirs"
         :publishing-function org-publish-attachment)
        ("articles"
         :base-directory "~/w/asgeirs/"
         :recursive t
         :publishing-directory "/ftp:asgeir@ftpperso.free.fr:/"
         :language "fr"
         :style "<link rel=\"stylesheet\"
href=\"http://asgeir.free.fr/style.css\" type=\"text/css\">"
         :section-numbers nil
         :table-of-contents nil
         :auto-sitemap t
         :sitemap-title "Ce qu'on y trouve"
         :html-preamble "<a href=\"http://asgeir.free.fr\"><img style=\"width:
636px; height: 122px;\" class=\"headerbanner\" alt=\"Da Asgeir's : My MoO
webpage with lots of cows -- mOoO\" title=\"da@asgeirs:~\"
src=\"http://asgeir.free.fr/images/banniere.png\"></a><br/>\n<br/>\n"
         :html-postamble "<p class=\"creator\">Generated by %c</p>")
        ("images"
         :base-directory "~/w/asgeirs/"
         :base-extension "jpg\\|png"
         :recursive t
         :publishing-directory "/ftp:asgeir@ftpperso.free.fr:/"
         :publishing-function org-publish-attachment)
        ("asgeirs" :components ("articles" "images"))))

Suites de Cauchy

L'article a été déplacé ici pour que les formules puissent être affichées correctement.

Une élégante boucle de jeu

Voilà quelques jours, sous le coup de l'ennui couplé à la fatigue des partiels, je me suis dit « tiens, pourquoi ne pas coder un petit jeu de morpion, là comme ça, vite fait ». Direct j'vais voir Emacs (Super-g emacsclient -c dans mon Dwm favori), je lance SLIME, et je commence à taper sans réfléchir.

Tout se passe bien, tout est facile et rapide à écrire, jusqu'à… la boucle principale. Et voilà le problème : cette boucle doit appliquer une fonction (play <state> <joueur>), qui demande au joueur son coup, et en prend note, aux deux joueurs du morpion jusqu'à ce que la partie soit terminée. C'est tout con me direz vous, un petit coup de

(loop with joueur = 'X
   and state = '()
   while (game-not-finished state) do
     (setf state (play joueur))
     (setf joueur (if (eq joueur 'X) 'O 'X)))

et le tour est joué.

Oui, sauf que… c'est… comment dire… ben c'est moche, quoi. Et à quoi ça sert de coder un morpion lorsqu'on sait déjà le faire, si c'est pas pour arriver à quelque chose de joli ? Y m'faut une solution… fonctionnelle.

Alors là, je demande leur avis aux copains de #sdz-unix@irc.epiknet.org, et on me répond trois choses :

  • qu'est-ce que tu te fais chier, la boucle impérative ça marche très bien

(lastsounet)

  • utilises les continuations (lasts aussi)
  • t'as qu'à foutre ça dans une Monade et rulz (ah, gnomnain)

S'en suivent deux jours d'intense activité neuronale, durant lesquels je tente inutilement de comprendre l'intérêt des monades (j'avais déjà tenté le coup pour les continuations, sans succès). Découragé, je reviens à mes considérations lispeuses : rien ne vaut une bonne petite récursion.

Alors alors, une boucle normalement ça se traduit comme l'application d'une fonction à chaque élément d'une liste. Ici notre fonction, c'est play, et notre liste, c'est… (X O X O X O X O …) jusqu'à ce que le jeu soit terminé. Alors soit on construit notre liste avant, ce qui n'est ici pas possible, soit on décide en « temps réel » du moment où l'on doit s'arrêter. En fait, ce dont on a besoin, c'est donc d'appliquer notre fonction play à chaque élément d'une liste cyclique (X O), en vérifiant à chaque fois que le jeu n'est pas terminé. On a donc besoin de connaître à chaque instant l'état de la partie. Hum…

En fait, ce dont on a besoin, c'est d'une espèce de mélange entre reduce — pour parcourir une liste, appliquer une fonction à chaque élément de cette liste, tout en gardant le résultat cumulé de tous les appels — et some — pour parcourir une liste jusqu'à ce qu'un prédicat devienne vrai.

Déjà pour commencer, prévenons SBCL que nous allons utiliser des listes cycliques (sinon, il n'est pas content et boucle comme un neuneu) :

(setf *print-circle* t)

Ensuite, une petite fonction bien utile :

(defun cyclic (lst)
  (let ((cyc (copy-list lst)))
    (setf (rest (last cyc)) cyc)))

qui visiblement, fonctionne comme il faut :

CL-USER> (cyclic '(a b))
#1=(A B . #1#)

et puis, notre mélange entre reduce et some :

(defun cyclic-reduce (function sequence pred &key (initial-value
                                                   nil initial-value-supplied))
  "Like reduce, but stops its computing when the predicate applied to the
   result of the computing becomes true."
  (labels ((g (seq result)
             (if (or (null seq) (funcall pred result))
                 result
                 (g (rest seq) (funcall function result (first seq))))))
    (if initial-value-supplied
        (g sequence initial-value)
        (g (rest sequence) (first sequence)))))

Et voilà ! Maintenant, pour notre boucle principale, il suffit de construire une liste cyclique à partir de la liste des joueurs/euses, et de la donner à manger avec notre fonction play à notre cyclic-reduce. Mattez-voir comme c'est mignon tout plein :

(reduce-with-end #'play (cyclic players) #'game-over :initial-value nil)

Je kiffe.

Blorg

Ça faisait longtemps que je cherchais une solution élégante pour générer un joli petit blog statique : sans commentaires, sans trackbacks, sans php ni sql. On en trouve à la pelle des générateurs de blogs : en python, en ruby, qui savent gèrer markdown, facebook, twitter, et autres conneries… mais pas moyen d'en chopper un qui s'intègre bien dans mon GNU Emacs favori.

Non, pour bloguer avec Emacs, y'a pas beaucoup de solutions correctes : faut utiliser Muse, une espèce d'usine à gaz qu'on rajoute à Emacs pour qu'il gère une espèce de syntaxe moisie et sache pondre des pages html correctes à partir de ça. Et là, y'à une extension muse-blog ou pas loin, qui apprend à notre Emacs chou comment exporter les fichiers muse en un joli blog.

Sauf que moi, muse, j'aime pas ça. J'aime pas sa syntaxe, sa lourdeur, et je n'y vois pas grand intérêt face à l'Org-Mode. Sauf que l'Org-Mode, ben il a pas l'air d'avoir grand chose pour bloguer…

Et c'est là que, sorti des entrailles de grosse-gueule, se pointa Blorg. C'est une magnifique extension des plus légères, qui n'a besoin pour fonctionner que d'un petit fichier org dans lequel on place nos articles sous forme d'une TODO List. C'est pas magnifique ?

Oui, mais… quelques petits problèmes se posent quand même :

  • Blorg exporte les dates en anglais ;
  • Blorg a quelques petits bugs d'export html ;
  • et sourtout, Blorg ne sait pas exporter de codes sources, et encore moins les

colorer.

Pour le problème des dates en anglais, quelques petites bidouilles (bon, bien 1 ou 2 heures de boulot quand même, hein), et c'est règlé. Par contre, pour l'histoire des bugs d'export et de la coloration des sources, le problème venait du fait que Blorg est apparu avant que l'Org-Mode soit doté de ses exceptionnelles fonctions d'exportations dans divers formats (dont HTML, LaTeX, DocBook, …). L'auteur de Blorg avait donc été contraint d'écrire à la main des fonctions d'exportation qui, au fil des lustres, étaient de moins en moins compatibles avec nos versions modernes d'Org et d'Emacs.

J'ai donc passé deux jours à bidouiller tout ça, pour remplacer toutes ces routines obsolètes par de beaux appels à org-export-as-html, et pouvoir enfin poster mon premier article.

Pour finir en beauté, voici donc le résultat de mes derniers bidouillages :

Bisouilles :*