Le remplaçant de Gilles Bernard pour programmation fonctionnelle est Otman Manad
ATTENTION: Les instructions ci-dessous supposent que vous utilisez Ubuntu.
Pour installer correctement Dia et l'utiliser pour le cours, il faut absolument procéder dans un certain ordre. Les commandes suivantes téléchargent les feuilles de doublets et d'arbres pour Dia, installent Dia puis décompressent les feuilles. Il est important de ne pas lancer Dia avant d'avoir téléchargé les feuilles.
wget https://wiki.paris8-ied.net/dia.tar.gz -O /tmp/dia.tar.gz
rm -rf ~/.dia || true
sudo apt install -y dia
tar -xf /tmp/dia.tar.gz -C ~
rm /tmp/dia.tar.gz
Si vous utilisez macOS plutôt que Linux, vous n'avez peut-être pas la commande wget
. Dans ce cas, il faut remplacer par la commande curl
(attention, l'option de la commande est avec un o
minuscule pour curl
, majuscule pour wget
):
curl https://wiki.paris8-ied.net/dia.tar.gz -o /tmp/dia.tar.gz
rm -rf ~/.dia || true
sudo apt install -y dia
tar -xf /tmp/dia.tar.gz -C ~
rm /tmp/dia.tar.gz
Lancer Dia (il y a une icône pour l'application):
Vous devez obtenir quelque chose comme cela:
Pour créer des doublets, sélectionner Lisp
dans la liste déroulante:
ATTENTION: Les instructions ci-dessous supposent que vous utilisez Ubuntu.
- Soit depuis un Terminal:
sudo apt install clisp
- Soit depuis un gestionnaire de paquets genre Synaptic: chercher clisp
et suivre les indications. Vous n'avez besoin que de clisp, rien d'autre.simple
- Assurez-vous que CLISP est bien installé en tapant dans un Terminal la commande:
clisp
Vous devez obtenir:
Pour quitter CLISP, entrer la commande:
(quit)
Par défaut, quand on lance clisp, on se retrouve avec une vue “archaïque” des symboles (i.e. ils sont en majuscules). Un alias permet de passer à une vue “moderne”. Il y a plusieurs manières de le faire, en voici une:
Ouvrir un Terminal et entrer la commande:
echo "alias lisp='clisp -q -modern -L french'" >> ~/.bash_aliases
Il faut ensuite rafraichir l’environnement. On peut fermer et ouvrir un autre Terminal ou taper :
. ~/.bashrc
Pour lancer Common Lisp avec les bonnes options, il suffit alors de taper (dans un Terminal):
lisp
Vous obtiendrez:
Pour quitter, taper:
(quit)
Si vous utilisez zsh plutôt que bash, il faut faire la même chose mais dans le fichier .zshrc
.
clisp est un outil en ligne de commande et se lance donc dans un Terminal. Mais il est tout à fait possible de créer une icône pour le lancer. Attention, je suppose que vous avez Gnome comme environnement (si vous êtes sous Ubuntu, c'est le cas). Tout d'abord, on va récupérer une icône (libre de droits), ce sera plus jolie, et la mettre dans “Documents”:
wget https://upload.wikimedia.org/wikipedia/commons/f/f4/Lisplogo.png -O ~/Documents/clisp.png
Ensuite, on créé un fichier pour démarrer notre programme clisp avec les bonnes options et la bonne icône:
cat >~/.local/share/applications/clisp.desktop <<EOF
[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=CLisp
Comment=Common Lisp
Exec=/usr/bin/clisp -q -modern -L french
Icon=${HOME}/Documents/clisp.png
Terminal=true
EOF
Vous obtiendrez le résultat suivant:
Cliquez sur l'icône CLisp, cela ouvre un terminal:
Pour quitter, taper:
(quit)
Le code indiqué par le prof dans la page “Présentation du code en Latex” est faux. Il faut corriger la première ligne par:
\usepackage[listings]{tcolorbox}
Tel qu'il est, le code est en noir sur fond blanc. Vous pouvez changer la couleur du fond mais là aussi, le code du prof est imprécis car il faut changer la couleur à deux endroits. Vous pouvez créer votre propre couleur avec le paquet xcolor. Cela donne alors (par exemple) le code complet suivant:
\documentclass{article}
\usepackage{xcolor}
\definecolor{mygray}{rgb}{0.9, 0.9, 0.9}
\usepackage[listings]{tcolorbox}
\newtcblisting{code}{%
colback=mygray, % remplacez par la couleur de fond souhaitée
boxrule=-1pt,
listing only,
top=-1pt,
bottom=-2pt,
left=-1pt,
right=0pt,
boxsep=0pt,
box align=center,
after={\par\smallskip\noindent\phantom{i}},
listing options={
language=Lisp,
backgroundcolor=\color{mygray}, % remplacez par la couleur de fond souhaitée
basicstyle=\sffamily\normalsize,
keywordstyle=\sffamily\normalsize,
upquote=true,
showstringspaces=false,
showspaces=false,
tabsize=2,
xleftmargin=15pt,
breaklines=true,
breakatwhitespace=true,
columns=fullflexible,
commentstyle=\sffamily\itshape,
escapeinside={\%/*}{*/},
}
}
\makeatletter
% tirets
\lst@CCPutMacro
\lst@ProcessOther {"2D}{\lst@ttfamily{-{}}{-}}
\@empty\z@\@empty
% guillemets
\lst@CCPutMacro
\lst@ProcessOther {"22}{\lst@ifupquote \textquotedbl%
\else \char34\relax \fi}
\@empty\z@\@empty
\makeatother
\begin{document}
\section{Introduction}
\begin{code}
Votre code ici
\end{code}
\end{document}
Le résultat sera:
( a b c ) ⇒ faux
(a b c) ⇒ correct
(a(b c)d) ⇒ faux
(a (b c) d) ⇒ correct
(cons
(car liste)
(cdr liste) )
(cons
(car liste)
(cons
(car liste2)
(cdr liste2) ) )
(defun fonction (arg1 arg2)
( ... ) )
Exemple : ((premier élément trop long pour une ligne) suite de la liste) s'indente ainsi :
((premier
élément
trop
long
pour
une
ligne )
suite
de
la
liste )
[https://www.youtube.com/watch?v=wdVp4jRs-Eg|Vidéo explications Pretty-print]
“Annexe-4 : Syntaxe et pretty-print” également disponible dans le cours de Gilles Bernard, version de Novembre 2015
Pour aider à formatter correctement le code (pretty-print), utilisez un éditeur qui colorie les parenthèses suivant à quel niveau elles se situent (des parenthèses au même niveau ont la même couleur). Vous pouvez par exemple utiliser Visual Studio Code.
Par défaut, Visual Studio Code ne comprend pas le LISP, il faut lui indiquer les règles de ce langage. Il y a une extension pour cela. Cliquez sur l'icônes des extensions dans la barre sur le côté à gauche:
Tapez “Common Lisp”:
La bonne extension est en principe celle qui vient en premier. C'est l'extension de Qingpeng Li. Cliquez sur “Install”. Maintenant, Visual Studio Code est capable de reconnaitre LISP et les fichiers avec l'extension .lisp.
Si vous ne voyez toujours pas de couleurs, c'est que l'option n'est pas activée dans Visual Studio. Allez dans Preferences / Settings et tapez “colorization”:
Assurez-vous que l'option “Bracket Pair Colorization” est bien cochée. Vous avez maintenant des parenthèses avec des couleurs.
L'exemple suppose que vous avez installé Visual Studio Code comme décrit précédemment. Dans l'éditeur, vous avez:
Cela peut sembler juste, mais avec les couleurs, on voit tout de suite que quelque chose ne va pas:
On a des couleurs différentes pour deux arguments du cons au dessus. Cela veut dire que ce ne sont en fait pas tous les deux des arguments de ce cons. On corrige cette erreur:
On corrige les autres erreurs. On se retrouve facilement dans ce type de situation:
Les nil vont avec quoi ? A quel niveau ? Pour le déterminer, il suffit de mettre son curseur sur la parenthèse après (violette):
L'éditeur indique la parenthèse ouvrante qui correspond et on peut donc formatter correctement:
On procède de même pour le reste:
Cela semble pas mal, non ? Sauf que c'est faux. Il n'y a effectivement pas de problème de parenthèses, les mêmes couleurs sont au même niveau. Mais il y a deux types d'erreurs: 1) certaines parenthèses sont décollées alors qu'elles ne le devraient pas (indiqué en orange). Certains arguments de cons sont mal placés (indiqué en rouge):
La règle est la suivante:
cons
sur une ligne, et chaque argument sur une autre ligne et indenté.On ne peut pas mélanger la première possibilité avec la deuxième. C'est l'un ou l'autre. Cela donne donc:
Parfait non ? Et là, c'est le drame. Votre pretty-print est refusé sèchement par le-la prof car trop indenté. Mais quelle est la règle du trop / pas assez ? Il n'y en a pas. Il faut se fier à son bon sens. Trop indenté, cela devient illisible, pas assez aussi. Il faut trouver le juste milieu. Par exemple:
Ou:
Une règle empirique semble être qu'il est raisonnable d'avoir 3 niveaux sur une seule ligne, mais pas plus. Il faut aussi éviter d'avoir des lignes trop longues. Si vous dépassez la 80ème colonne, il est préférable de découper la ligne.
Dans le cas d'une double parenthèse, il faut appliquer les mèmes règles mais comme on a deux parenthèses ouvertes, on fait une double indentation. Par exemple (exemple fictif):
(defun example (a b)
(cond
((or (eq a b) (eq a 0)) (cons 2 3))
(t (cons 4 5)) ) )
Comment indenter les arguments de or et le cons qui suit (indentation qui serait obligatoire si la fonction était plus compliquée ? Tout d'abord, on indente les arguments de or (les eq). Comme on a deux parenthèses ouvertes, on double l'indentation:
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0)
Puis en ferme une première parenthèse (avec un espace car elle a été ouverte sur une ligne précédente):
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0) )
On place maintenant le cons avec cette fois une seule indentation car on a fermé une parenthèse:
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0) )
(cons 2 3)
On ferme la deuxième parenthèse du or:
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0) )
(cons 2 3) )
Et on ajoute le reste:
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0) )
(cons 2 3) )
(t (cons 4 5)) ) )
De cette manière, on voit bien que:
Pour mieux voir, je remplace les espaces des indentations par des points:
(defun example (a b)
..(cond
....((or
........(eq a b)
........(eq a 0) )
......(cons 2 3) )
....(t (cons 4 5)) ) )
L'indentation doit toujours être un multiple du nombre d'espaces que vous avez choisi (ici, j'ai choisi deux espaces), depuis la marge de gauche. Ce n'est pas par rapport au parenthèses. Par exemple, l'example suivant est faux:
(defun example (a b)
(cond
((or (eq a b) (eq a 0))
(cons 2 3))
(t (cons 4 5)) ) )
Il manque un espace devant le (cons. La bonne manière est:
(defun example (a b)
(cond
((or (eq a b) (eq a 0))
(cons 2 3))
(t (cons 4 5)) ) )
On peut préférer indenter plus surtout si les expressions sont plus compliquées:
(defun example (a b)
(cond
((or
(eq a b)
(eq a 0) )
(cons 2 3) )
(t (cons 4 5)) ) )
Une autre manière de voir est de compter le nombre de parenthèses ouvertes et pas encore fermées. Cela donne le nombre d'indentations à faire depuis le bord de gauche. Dans l'exemple ci-dessous, le nombre de parenthèses ouvertes (et pas encore fermées) est en orange. A chaque nouvelle parenthèse ouvrante, on ajoute 1. A chaque parenthèse fermante, on enlève 1. Cela donne le nombre d'intentions (en bleu ci dessous). Si la ligne commence par une parenthèse ouvrante (ce qui est presque toujours le cas), on prend le nombre en orange moins 1 (car lors de l'indentation, la parenthèse n'est pas encore ouverte):
Pour un certain nombre d'exercice, vous devez passer d'une représentation textuelle à une représentation graphique ou le contraire. Pour vous aider, une élève a porté un programme écrit à l'origine en Scheme (un dialecte de LISP) en Common Lisp “à la GB” (avec pretty-print, pas de let, …). Cela permet d'afficher une représentation des doubles (cons) d'une liste. Pour cela, vous devez télécharger le programme draw-cons-tree.lisp. Pour ensuite l'utiliser, ouvrez un terminal, placez-vous (cd
) dans le répertoire où est sauvé le fichier draw-cons-tree.lisp, lancez LISP (clisp -q -modern -L french
ou simplement lisp
si vous avez défini un alias) et entrez:
(load "draw-cons-tree.lisp")
Vous pouvez maintenant afficher les doublets (cons) avec la fonction draw-tree
qui prend comme argument une liste. Par exemple:
(draw-tree '(a b (c) (d (e f) . g) h))
[o|o]---[o|o]---[o|o]---[o|o]---[o|/]
| | | | |
a b [o|/] | h
| |
c [o|o]---[o|o]--- g
| |
d [o|o]---[o|/]
| |
e f
Ne pas oublier le dernière parenthèse qui ferme l'appel à la fonction draw-tree
. Vous pouvez ainsi valider vos représentations graphiques ainsi que l'inverse (en vérifiant que la représentation est similaire à celle de l'énoncé).
Il y a une erreur dans l'explication du cours page 73:
A. (set (eval bar) (+ 3 foo))
• nom : 5
• valeur : obtenue par l’addition de 3 et de foo ;
• erreur provoquée par set parce que 5 n’est pas un symbole, c’est un nombre.
(eval bar)
va bien retourner 5 et on ne peut pas faire un set
avec un mombre. Mais il y a une autre erreur qui va apparaître avant à cause de (+ 3 foo)
. foo
est lié à bar
, un symbole et pas un nombre. Donc l'erreur est est fait:
*** - +: bar is not a number
Pour les exercices de Lsp 5 Eval, il y a plusieurs choses à prendre en compte:
ZORGLUB
(en majuscules donc) c'est faux. Cela veut dire que vous n'utilisez pas correctement clisp
. Vous ne devez pas juste lancer cette commande mais: clisp -q -modern -L french
(source: https://moodle.iedparis8.net/mod/wiki/view.php?pageid=37)Voici un exemple:
On note car
ou cdr
au-dessus des flèches. Pour arriver au doublet dont on veut modifier le cdr
, on passe par: car
, cdr
et encore cdr
. Pour la destination, c'est: cdr
et car
. Il suffit d'écrire ces deux suites dans l'expression (attendion, c'est dans l'autre sens):
(rplacd (cdr (cdr (car liste))) (car (cdr liste)))
Ce qui peut aussi s'écrire:
(rplacd (cddar liste) (cadr liste))
La série d'exercices pour Vraiprog1 commence à la page 148 (“Écrire un vrai programme : explorations”) et se termine au début de la page 154 (“Vrai programme : exploration”). Il y a quatre parties: Exercices A, B, C et la question D. Il faut rendre cette série d'exercices en une seule fois avec comme sujet “Exo Vrai- prog1”.
Après avoir validé la série d'exo vraiprog1, le prof envoit ce mail générique :
A partir de là, vous êtes supposé être devenu autonome, et n'avez plus besoin d'attendre mes réponses. Envoyez un seul mail pour Vraiprog2 mais avec en pièce jointe une archive contenant tous les fichiers utilisés et le pdf de réponse - pour que je puisse tester le programme. Pareil pour Vraiprog3.
Un conseil : ne vous arrêtez pas après Vraiprog3 (même si ça vous permet d'avoir plus ou moins la moyenne), allez jusqu'à la fin du cours (vous en aurez besoin ensuite, et les exercices sont plutôt plus faciles). Le pretty-print et la qualité du code compte dans la note finale.