La voix du secrétaire (Jean)Présents à la réunion :
Comme à l'accoutumée, il a été question de Perl, d'informatique, et de sujets divers.
#!/usr/bin/perl -p 11..exitTout d'abord, l'option -p a pour effet de prendre le morceau de source, et de l'encadrer par :
LINE: while (<>) { le script...; } continue { print or die "-p destination: $!\n" }Par conséquent, le script tel qu'il est compilé et exécuté est :
LINE: while (<>) { 11..exit; } continue { print or die "-p destination: $!\n" }et l'option -p ne compte que pour trois caractères (n'oubliez pas le blanc qui précède). Il y a également l'opérateur .. en contexte scalaire, déjà évoqué précédemment. On ne commence à tester la deuxième condition que lorsque la première est réalisée. Une particularité de l'opérateur .. est que lorsque l'un de ses opérandes est un nombre, ce nombre n'est pas converti comme d'habitude avec la convention 0 -> faux, autre -> vrai, mais au lieu de cela, ce nombre est comparé à la variable $. ou, si vous préférez, $INPUT_LINE_NUMBER. Cette condition est donc en réalité
$INPUT_LINE_NUMBER == 11Quant à la deuxième condition, elle ne renvoie jamais ni vrai ni faux, elle arrête le programme, purement et simplement.
#!/usr/bin/perl -p 11..&L'option -p transforme ce source en :
LINE: while (<>) { 11..&; } continue { print or die "-p destination: $!\n" }Et la deuxième condition est en fait constituée par : &;, c'est-à-dire l'appel à la routine "point-virgule". Et comme cette routine n'existe pas, le programme s'arrête en plantant. Mais il a affiché les dix premières lignes...
next if $_ eq '.' or $_ eq '..';Mais ce n'est pas performant, car cela fait effectuer un test pour chacune des N itérations, alors que le test n'est utile que pour deux itérations. Il a ensuite pensé à effectuer deux readdir « à vide » avant d'entrer dans la boucle, pour éliminer les deux entrées parasites, et coder une boucle compacte sur les fichiers du répertoire. En effet, le readdir renvoie les entrées du répertoire dans l'ordre où elles ont été créées, et « . » et « .. » sont nécessairement les deux premières. Randal lui a rétorqué que non. Il existe des cas rarissimes où « . » et « .. » ne sont pas les deux premières entrées du répertoire. S'il y a eu un plantage machine, que le système de fichiers est vérolé, et qu'il faut le réparer avec un fsck, alors rien ne garantit que fsck placera « . » et « .. » en première position. Donc, à cause de ce cas tordu et rarissime, les readdir à vide sont exclus. Il semble que les seules solutions applicables consistent à dupliquer le code de la boucle, ou à utiliser un sous-programme, ce qui implique un gaspillage de cycles machines lors de l'appel du sous-programme...
for (qw(foo bar)) { my $n = tr/o/o/; print "Dans $_ il y a $n o\n" }Et il s'est pris un message d'erreur « Modification of a read-only value ». En effet, la variable $_ est un alias de chaque élément de la liste, dans ce cas une liste de valeurs « en dur ». Il est donc impossible de modifier la valeur de $_ dans l'itération. C'est d'autant plus rageant que justement, l'opérateur tr laisse la variable $_ dans l'état où il l'a trouvée. En effet, il remplace chaque « o » par un « o », donc il n'y a au final aucun changement. Briac a voulu adapter son programme ainsi :
for my $ch (qw(foo bar)) { my $n = $ch =~ tr/o/o/; print "Dans $ch il y a $n o\n" }mais cela n'a rien changé, car dans ce cas aussi $ch est l'alias de chaque élément de la liste. Je signale que j'ai déjà rencontré ce problème, sous une forme légèrement différente. C'était dans le module Lingua::EN::Inflect, version 1.85, écrit par (excusez du peu) Damian Conway. Par exemple, pour le pluriel « pragmata » de « pragma », et autres mots du même genre, il construisait ainsi une expression régulière :
# CLASSICAL "..a" -> "..ata" my $PL_sb_C_a_ata = join "|", map { chop; $_; } ( "anathema", "bema", "carcinoma", "charisma", "diploma", "dogma", "drama", "edema", "enema", "enigma", "lemma", "lymphoma", "magma", "melisma", "miasma", "oedema", "sarcoma", "schema", "soma", "stigma", "stoma", "trauma", "gumma", "pragma", );(à noter l'utilisation de chop qui, pour une fois, ne peut pas être remplacée par chomp). Ce module plante en version 5.6 ! À la décharge de Damian, le module fonctionne très bien en 5.005, tout comme le programme de Briac. En 5.6, la solution consiste à utiliser une autre variable, qui, elle, ne sera plus un alias. D'ailleurs, quelques lignes plus loin, dans Lingua::EN::Inflect, version 1.85, on trouve :
# CLASSICAL "..o" -> "..i" (BUT NORMALLY -> "..os") my @PL_sb_C_o_i = ( "solo", "soprano", "basso", "alto", "contralto", "tempo", ); my $PL_sb_C_o_i = join "|", map { my $w=$_; chop $w; $w; } @PL_sb_C_o_i;
for (1..10) { my $n; print "Itération $_ : \$n vaut $n\n"; $n = $_; }affiche dix fois l'avertissement « use of uninitialized value ». Normal. Et il affiche dix lignes ressemblant à :
Itération 1 : $n vautNormal. Si l'on adapte légèrement ce programme, avec une condition toujours fausse appliquée au my :
for (1..10) { my $n if 0; print "Itération $_ : \$n vaut $n\n"; $n = $_; }on obtient une fois et une seule l'avertissement « use of uninitialized value », et une seule ligne qui semble tronquée :
Itération 1 : $n vautLes lignes suivantes, en revanche, donnent :
Itération 2 : $n vaut 1 Itération 3 : $n vaut 2et ainsi de suite. Malgré la sortie puis l'entrée dans la portée lexicale, la valeur de la variable est conservée !
RCL 7 RCL 3 /peuvent aisément être remplacés par :
set editing-mode viEt à ce moment-là, vous passez en mode édition avec ESC, vous vous déplacez dans l'historique avec j et k, vous vous déplacez dans la ligne en cours d'édition avec h, l, w, $ et autres commandes connues.
rm * .o(avec un blanc entre l'étoile et le point), et le système vous répond :
rm: cannot remove `.o': No such file or directoryEn Ada, c'est encore plus simple, si l'on peut dire. Un compilateur Ada ne vous permettra jamais de vous tirer une balle dans le pied. Dans un compte-rendu précédent, j'avais trouvé deux archives sur cette question. La première m'avait un peu déçu. Mais dans la deuxième, j'avais trouvé le paragraphe concernant Perl. Ce passage n'expliquait pas comment faire, mais il remarquait qu'une fois qu'un programmeur avait trouvé comment se tirer une balle dans le pied avec Perl, il passait tout l'après-midi à essayer de trouver d'autres façons de le faire, car TIMTOWTDI.
0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 1 0 0 1 1 1 0 1 0 1 0 1 0 0