Goto
Transcription
Goto
Ceci est un extrait électronique d'une publication de Diamond Editions : http://www.ed-diamond.com Retrouvez sur le site tous les anciens numéros en vente par correspondance ainsi que les tarifs d'abonnement. Pour vous tenir au courant de l'actualité du magazine, visitez : http://www.gnulinuxmag.com Ainsi que : http://www.linux-pratique.com et http://www.miscmag.com Ceci est un extrait électronique d'une publication de Diamond Editions http://www.ed-diamond.com Creative Commons Paternité - Pas d'Utilisation Commerciale - Pas de Modification 2.0 France Vous êtes libres : • de reproduire, distribuer et communiquer cette création au public. Paternité. Vous devez citer le nom de l'auteur original de la manière indiquée par l'auteur de l'oeuvre ou le titulaire des droits qui vous confère cette autorisation (mais pas d'une manière qui suggérerait qu'ils vous soutiennent ou approuvent votre utilisation de l'oeuvre). Pas d'Utilisation Commerciale. Vous n'avez pas le droit d'utiliser cette création à des fins commerciales. Pas de Modification. Vous n'avez pas le droit de modifier, de transformer ou d'adapter cette création. A chaque réutilisation ou distribution de cette création, vous devez faire apparaître clairement au public les conditions contractuelles de sa mise à disposition. • Chacune de ces conditions peut être levée si vous obtenez l'autorisation du titulaire des droits. • Rien dans ce contrat ne diminue ou ne restreint le droit moral de l'auteur ou des auteurs. Ceci est le Résumé Explicatif du Code Juridique. La version intégrale du contrat est attachée en fin de document et disponible sur : http://creativecommons.org/licenses/by-nc-nd/2.0/fr/legalcode code Par :: Philippe “BooK” Bruhat :: book@ mongueurs.net :: :: Jean Forget :: Goto en Perl Depuis vos premiers cours de programmation (en C ou en Pascal), on vous serine de ne pas utiliser goto. Mais connaissez-vous la raison de cet interdit dogmatique ? Cet article vous expliquera d’où vient le goto, pourquoi personne ne l’aime et comment l’utiliser. En Perl. L’histoire de goto 74 On trouve une commande goto dans presque tous les langages de programmation (FORTRAN, Algol, COBOL, SNOBOL, BASIC, C, C++, Perl...). Le principe de ces commandes est de faire sauter l’exécution du programme du point où se trouve le goto au point indiqué en paramètre. En BASIC, ce sera un numéro de ligne, mais dans la plupart des langages (qui n’ont pas de lignes numérotées) le pointeur de programme saute à un endroit indiqué par une étiquette (label en anglais). Le saut dans un flot d’instructions est une instruction tellement importante qu’elle existait déjà à l’âge de la programmation en langage machine. On la trouve encore dans tous les microprocesseurs. En assembleur, le mnémonique correspondant est généralement JMP (pour jump) ou BRA (pour branch). Les GO TO de FORTRAN En FORTRAN, il existe plusieurs formes de GO TO : le GO TO classique (unconditional GO TO), le GO TO calculé (computed GO TO) et le GO TO assigné (assigned GO TO). Les explications que je donne dans les paragraphes suivants sont valables pour FORTRAN 77. Les programmes d’exemple ont été testés avec F77, le compilateur FORTRAN 77 du projet GNU. GO TO label Comme prévu, l’instruction GO TO transfère le contrôle à l’instruction portant l’étiquette « label ». Pour mémoire, les étiquettes sont des nombres (situés dans les colonnes 1 à 5), qui doivent être uniques dans le programme. En guise d’exemple, un petit programme qui ajoute au total en cours un entier passé sur l’entrée standard. Le programme s’arrête quand on lui passe 0 (zéro). TOTAL=0 10 READ *, I IF (I.NE.0) THEN TOTAL=TOTAL+I PRINT *, TOTAL GO TO 10 END IF STOP END À l’exécution, on obtient : $ f77 goto01.f ; ./a.out 1 1. 2 3. 3 6. 4 10. 5 15. 0 Anecdote amusante : en FORTRAN, les étiquettes n’étant pas des numéros de ligne, leur ordre n’a aucune importance. GO TO ( liste ) [,] expression Le GO TO calculé permet de transférer le contrôle à l’une des étiquettes d’une liste en fonction de la valeur de l’expression. Si l’expression vaut 1 le contrôle est transféré à la première étiquette de la liste, à la seconde si elle vaut 2, etc. Si l’expression ne correspond à la position d’aucune étiquette, le programme continuera à l’instruction qui suit le GO TO. ! Exemple de computed GO TO 10 PRINT *, ‘Entrez un entier entre 1 et 8:’ READ *, i GO TO (100,200,300,400,500,600,700,800) i PRINT *, ‘Ce nombre ne correspond pas’ GO TO 10 ! redemande un nombre, ad lib. ! Les règles du Perl Club viennent de ! http://www.dave.org.uk/perlclub.html 100 PRINT *, ‘The First Rule of Perl Club’ PRINT *, ‘You do not talk about Perl Club’ GOTO 1000 200 PRINT *, ‘The Second Rule of Perl Club’ PRINT *, ‘You do not talk about Perl Club’ GOTO 1000 300 PRINT *, ‘Third Rule of Perl Club’ PRINT *, ‘A laptop crashes, breaks, runs down. ‘// &’The hack is over’ GOTO 1000 400 PRINT *, ‘Fourth Rule of Perl Club’ PRINT *, ‘Only two programmers to a pair’ GOTO 1000 500 PRINT *, ‘Fifth Rule of Perl Club’ PRINT *, ‘One bug at a time’ GOTO 1000 600 PRINT *, ‘Sixth Rule of Perl Club’ PRINT *, ‘No Java, no VB’ GOTO 1000 700 PRINT *, ‘Seventh Rule of Perl Club’ PRINT *, ‘Hacks will go on as long as they have to’ GOTO 1000 800 PRINT *, ‘Eighth, and Final Rule of Perl Club’ PRINT *, ‘If this is your first night at Perl Club, ‘// &’you have to hack’ GOTO 1000 1000 STOP END L’exécution du programme donne : $ f77 goto02.pod ; ./a.out Entrez un entier entre 1 et 8: 0 Ce nombre ne correspond pas Entrez un entier entre 1 et 8: 9 Ce nombre ne correspond pas Entrez un entier entre 1 et 8: 6 Sixth Rule of Perl Club No Java, no VB En FORTRAN 95, le computed GO TO statement est obsolète. GO TO variable Le GO TO assigné transfère le contrôle à l’étiquette contenue dans la variable entière qui suit. L’étiquette ne peut être affectée à la variable en question qu’avec l’instruction ASSIGN (d’où le nom de ce GO TO). ASSIGN 20 TO I ... GO TO I ... 20 PRINT *, ‘Etiquette 20!’ Avec cette forme de GO TO, on ne peut affecter qu’une étiquette à la variable. Notez qu’on ne peut pas utiliser le = de l’affectation entière pour stocker l’étiquette dans la variable. Goto en Perl Je ne suis pas assez calé en Fortran pour pouvoir dire quel est l’intérêt de cette écriture, sinon pour les effets à distance qu’elle permet (voir le cas de ALTER en COBOL, section suivante). Le cas de COBOL COBOL se distingue non pas par son GO TO, mais par son instruction ALTER, qui permet en quelque sorte d’établir une déviation. Voici un exemple : * Début du programme, toutes les déclarations, * définitions et autres. Verbeux comme c’est * l’habitude en COBOL ALTER etiq1 TO GO TO etiq2. * quelques centaines de lignes de code, également verbeuses GO TO etiq1. * encore quelques centaines de lignes etiq1. DISPLAY „salut“ UPON CONSOLE. GO TO suite. etiq2. DISPLAY „coucou“ UPON CONSOLE. GO TO suite. * et la suite Comme vous l’avez deviné, ce n’est pas salut qui s’affichera à l’écran. Mais l’auriez-vous deviné si j’avais réellement listé le source complet du programme ? Cela dit, l’utilisation de ALTER n’est pas monnaie courante... à aucun branchement goto donc cette instruction est vraisemblablement interdite (il existe des instructions dont le nom comporte goto, mais il s’agit de déplacer le pointeur de lecture dans le tampon en cours d’édition, pas de modifier la position du pointeur d’instruction). Quant aux autres variantes de Lisp et aux langages dérivés, qui n’ont même pas l’excuse d’être incorporés (embedded) dans un éditeur de texte, ils ignorent complètement ce mot et ce concept. Plus curieux : le langage de programmation des calculatrices HP-48 ne comporte aucun goto. Pourtant, la HP-48 est l’héritière de la HP-41 dans laquelle le goto (orthographié GTO) était indispensable dès qu’un programme devait effectuer un traitement itératif. Si vous grepez la documentation de Ruby à la recherche d’un GOTO, vous verrez que c’est un nom ou un prénom assez répandu au Japon, mais que ce n’est pas une instruction du langage. En Java, goto est un mot réservé, mais l’instruction ne fait pas partie du langage. Edsger W. Dijkstra Il existe des langages de programmation où le goto a été laissé de côté ou, peutêtre, oublié. En voici quelques-uns, que les auteurs ont utilisés, le plus souvent de façon éphémère. Vous connaissez le shell. Vous avez déjà écrit quelques scripts pour enchaîner quelques commandes qui reviennent régulièrement. Certains de vos scripts utilisent même des variables, des boucles et des tests camouflés en expressions logiques avec && et || ou des tests explicites avec if then elif else fi. Mais aviez-vous remarqué qu’il n’existe aucune instruction goto ? (Avez-vous au moins lu la page de man ?). Un autre langage incontournable pour quiconque utilise Unix de façon un peu poussée, c’est AWK. Là aussi, lisez la page de manuel ou un tutoriel, vous ne verrez jamais mentionnée d’instruction goto. Emacs est basé sur le langage Elisp et il comporte donc un interpréteur Elisp incorporé ainsi que la documentation du langage. Celui des deux coauteurs qui utilise Emacs pour taper cet article l’a vérifié, la documentation ne fait référence Photo Hamilton Richards Les langages de programmation sans goto Edsger Wybe Dijkstra (1930-2002) est un chercheur en informatique hollandais qui a eu un rôle important dans le monde de la recherche informatique. Il a travaillé sur le premier compilateur ALGOL 60 et est l’auteur d’un algorithme qui porte son nom pour le problème du plus court chemin (vous pouvez trouvez la description de l’algorithme de Dijkstra dans l’article « Recherche des chemins optimaux pour les jeux vidéo » de Fabrice Rossi dans GNU/Linux Magazine 53). L’article de 1968 sur goto a eu une influence considérable : il a accéléré la disparition du goto des habitudes de programmation, fait progresser la notion de « programmation structurée » et amené la création des structures de contrôle telles que les boucles while. La polémique En 1968, Dijkstra a lancé un pavé dans la mare, remettant en question l’ordre établi et proposant de faire table rase du goto. Dijkstra a publié un papier intitulé « A case against the goto statement », mais que Wirth, alors rédacteur en chef des « Communications of the ACM » a changé en courrier au rédacteur en chef, en lui donnant par la même occasion un titre destiné à devenir célèbre, « Go To Statement Considered Harmful ». Dans cet article, Dijkstra constatait que les goto nuisent à la compréhension du programme par un lecteur humain et que la qualité du code varie en sens inverse de la densité des goto. Une petite remarque pour ceux qui voudraient lire cet article : ne vous attardez pas sur la partie médiane de l’article, qui décrit un concept d’index textuel et d’index dynamique. Je doute fort qu’un quelconque programmeur ait eu recours à cette méthode pour décortiquer le fonctionnement d’un programme. L’essentiel est écrit au début et à la fin de l’article, le goto est indésirable et il doit disparaître. Un peu plus tard, Donald Knuth a publié un autre article, « Structured Programming with go to Statements ». Le titre donne l’impression d’être un pamphlet destiné à répondre avec véhémence à l’article de Dijkstra. En lisant l’article, on constate que ce n’est pas du tout le cas. Knuth le dit lui-même : il ne prend pas parti dans la guerre sainte des partisans et des adversaires du goto. Il veut simplement raconter comment il programme et quelle place le goto a dans son code. Il ajoute que les adversaires du goto liront des arguments allant dans le sens de l’éradication du goto et que les partisans du goto liront des arguments justifiant l’existence du goto. Et effectivement, à la lecture de son article, on peut constater que Knuth aborde le sujet avec un esprit ouvert et serein, sans idée préconçue et sans œillères. L’article de Knuth montre qu’il n’y a pas besoin d’insérer des goto pour obtenir un programme illisible. Il montre comment émuler les goto avec une boucle et une structure conditionnelle et il fait remarquer à juste titre que le programme obtenu est encore moins lisible que le programme d’origine avec des goto (construction due à Jacopini). Remarquons que Knuth 75 code réfute ainsi la partie médiane de l’article de Dijkstra en montrant que le système d’index textuels et dynamiques ne permet pas à un humain de mieux comprendre le fonctionnement du programme. Les deux gourous ont tiré des conclusions différentes, que je présenterai au moyen d’une métaphore. Pour Dijkstra, puisque certaines personnes se sont intoxiquées en ingérant de l’eau de Javel, il faut interdire totalement la commercialisation de ce produit et le réserver aux chimistes professionnels. Pour Knuth, il faut vendre l’eau de Javel dans des récipients avec des bouchons de sécurité tels qu’un enfant de moins de 7 ans ne puisse pas l’ouvrir et il faut que les parents instruisent leurs enfants pour leur présenter les dangers de l’eau de Javel et les précautions d’emploi. Quand on y réfléchit bien, nous sommes entourés d’ustensiles et d’engins qui, mal utilisés, sont dangereux voire létaux mais qui, dans des conditions normales d’utilisation, sont inoffensifs ou presque : couteaux, ciseaux à bouts pointus, tondeuses, prises électriques, etc. Pour les programmeurs, il ne faut pas oublier d’ajouter goto à la liste. ;-) Le folklore 76 La notoriété de l’article de Dijkstra a eu un effet secondaire, l’expression « considered harmful» qui, comme nous l’avons vu, n’est pas due à Dijkstra mais à Wirth, a été reprise à maintes reprises et est finalement passée dans le langage courant (des informaticiens, s’entend). Si vous googlez cette expression, vous obtenez 65 000 pages, dont plus de 6 000 si vous restreignez la recherche aux titres. Dans deux cas, les auteurs ont voulu élever le débat au niveau supérieur, avec « ‘Goto statement considered harmful’ considered harmful », publié par l’ACM et cité dans le Jargon File et « ‘Considered harmful’ essays considered harmful », disponible sur le web. Et puisque le GO TO est mauvais, l’inverse doit être bon ! C’est ce que Lawrence Clark a dû se dire lorsqu’il a spécifié une nouvelle instruction, le COME FROM. C’est également ce que se sont dit les auteurs d’INTERCAL, lorsqu’ils ont effectivement implémenté le COME FROM. À noter que Clark avait également spécifié le computed COME FROM et le assigned COME FROM. En 1987, l’un des lauréats de l’IOCCC (International Obfuscated C Code Contest) fut Spencer Hines, grâce à un programme qui contenait une bonne vingtaine de goto. De plus, ce programme déclarait quelques variables entières toog, togo, oogt, ootg, otog, des variables chaînes de caractères toog, ogto, tgoo et ainsi de suite. Quant aux labels vers lesquels pointent les goto, je n’ai pas besoin de vous faire un dessin. Et finalement, le style d’indentation mérite d’être appelé « style », mais pas « indentation ». To go or not to go ? Supprimer les goto Puisque programmer avec des goto est si néfaste, il a fallu proposer d’autres solutions aux programmeurs pour qu’ils arrêtent de cuisiner du spaghetti code. Nous allons vous en présenter quelquesunes, que vous avez certainement déjà rencontrées. La construction de Jacopini Il y a la construction de Jacopini, déjà citée ci-dessus, mais c’est un exemple à ne pas suivre. Vous pourrez en juger par vous-mêmes vers la fin de cet article, nous vous en donnons un échantillon. Les exceptions La programmation par exceptions permet également de supprimer nombre de goto. Jusqu’alors, lorsqu’une erreur était rencontrée, on avait le choix entre la traiter immédiatement (en encombrant ainsi le code principal avec du code de traitement d’erreur souvent aussi gros que le code du traitement principal, si ce n’est plus) ou bien renvoyer l’exécution (par un goto) vers une section du programme prévue à cet effet (mais en transformant le code en un peu ragoûtant plat de spaghetti, avec des renvois dans toutes les directions). Comme nous l’avons dit précédemment, le langage Java n’a pas de goto. Ceci s’explique par le fait que les instructions break et continue (avec étiquettes) remplacent la plupart des utilisations importantes et légitimes de goto et que le mécanisme des exceptions remplace les autres. Le mécanisme des exceptions permet de définir un bloc d’essai (dit « try ») dans lequel le programme va exécuter des appels de méthodes qui risquent de planter. Pour indiquer l’apparition d’une condition exceptionnelle, le bloc de code ou la méthode à laquelle il a fait appel va lever (throw) une exception : le traitement cesse alors et l’exception va se propager jusqu’à sa capture. Les exceptions se propagent au niveau des blocs lexicaux, puis le long de la pile d’appel des méthodes. La capture des exceptions se fait dans le premier bloc catch rencontré. On peut alors soit traiter les cas d’erreurs attendus, soit lever de nouvelles exceptions qui seront éventuellement capturées au niveau supérieur. Toute exception qui passe au travers des mailles des différents filets (euh, blocs catch) mis sur son chemin finira par remonter jusqu’à l’utilisateur, qui verra alors son programme planter à cause d’une exception non capturée. Ainsi, au lieu de s’inquiéter de ce qui peut mal se passer à chaque ligne de code, on va centraliser le traitement des erreurs associées à un bloc logique de code dans un seul bloc de traitement. Ce qui rend ce mécanisme très intéressant, c’est que les méthodes des bibliothèques standards donnent la liste exhaustive des exceptions qu’elles peuvent lever et que le compilateur impose de préciser dans la signature de ces méthodes les exceptions qu’elles peuvent lever. Ainsi, si une méthode de votre classe fait appel à une méthode qui lève une exception d’entrée/ sortie et que votre code ne la traite pas, il vous imposera de déclarer que vous risquez de la propager. Bien sûr, cette technique a aussi ses limites. En Java, nombre de programmeurs paresseux (dans le mauvais sens du terme) ne traitent pas toutes les exceptions qui peuvent se produire et se contentent de les propager. De proche en proche, les exceptions remontent toute la pile d’appels et c’est l’utilisateur qui se retrouve démuni face à une pile d’appels longue comme un jour sans pain. Il existe d’ailleurs un module Perl qui se moque gentiment des programmes « professionnels » qui plantent en générant un message désespérément long et détaillé : Acme:: JavaTrace. Literate Programming La programmation littéraire (Literate Programming), inventée par Don Knuth, vise à écrire des programmes comme on écrit des livres. Le programme est présenté en langue naturelle, d’une façon logique, avec de multiples renvois vers le code effectuant les opérations. Le code de traitement d’erreurs va être typiquement relégué à une autre partie Goto en Perl du fichier source et ne va pas encombrer l’esprit du programmeur qui essaye déjà de comprendre ce que fait le bloc de code qu’il est en train de lire. Ce projet s’appelle « WEB » (son nom date d’avant la création du World-Wide Web et Knuth expliquait ce choix par le fait que c’était l’un des rares acronymes de trois lettres non encore utilisé) et est au cœur de TeX et LaTeX. Ainsi les fichiers source LaTeX contiennent leur propre documentation (en LaTeX) et la description de leur code (accompagnée du code lui-même). Lors de la génération des fichiers associés, la documentation est compilée et mise à disposition au format .dvi tandis que le code lui même (fichiers .sty en général) est installé là où LaTeX ira le chercher. WEB a donné naissance à CWEB, qui est un ensemble de programmes permettant de produire la documentation et les binaires à partir de code source C écrit selon la méthode literate. Les utilisations légitimes de goto goto est utilisé à plusieurs endroits du noyau Linux (et dans de nombreux autres systèmes et logiciels complexes). Estce que les développeurs du kernel sont de mauvais programmeurs ? Non, bien sûr ; goto est souvent le seul moyen de se sortir de cas complexes, typiquement pour la gestion d’erreurs. Les analyseurs syntaxiques (et les machines à états) sont aussi un cas d’utilisation légitime de goto. Nous vous invitons par exemple à examiner le code du module HTML::Parser 2.25 (disponible sur CPAN), dernière version pour Perl de cet analyseur HTML (les suivantes sont en XS, pour des raisons de performance). De nos jours, il existe des alternatives structurées aux utilisations légitimes de goto les plus courantes. Aux constructions de boucles while ou until sont associées les instructions break, redo ou continue qui permettent de quitter la boucle par le début ou la fin et d’effectuer un traitement à chaque tour de boucle, même si celle-ci a été interrompue. Perl et goto You can also « goto hell » if you like, which will of course work better if you’ve defined the label « hell ». (Larry Wall, The Perl Conference, 20 août 1997) Quand on y réfléchit, qu’est-ce qu’un goto ? C’est un saut à un autre point du programme, en général conditionné par un test. Ceci se fait sans aucune initialisation (contrairement à l’appel d’un sous-programme). Le test de la condition ne fait bien sûr pas partie du goto.Nous allons donc nous intéresser aux différentes manières de sauter d’un point à un autre d’un programme Perl, sans initialisation, ce qui exclut les appels à des sousprogrammes et l’utilisation de références à des fonctions (tables de distribution). Les « goto structurés » Dans de nombreux cas de traitements en boucle, on souhaite pouvoir définir d’autres points de sortie que la fin de la boucle, répéter une itération sans tester la condition de sortie ou encore sortir de plusieurs niveaux de boucles imbriquées d’un seul coup. En Perl, les instructions next, last et redo permettent de résoudre ces différents cas de figure sans faire appel au goto ni introduire tests et variables inutiles dans le corps de la boucle.Ces instructions sont toutes des genres de goto, puisqu’elles permettent de sauter à diverses positions dans la boucle (ou juste en dehors). Le bloc continue associé à la boucle while permet quant à lui d’assurer que la partie finale de la boucle sera exécutée même quand on la court-circuite. Quand nous parlons de « genres de goto », il s’agit bien d’une comparaison, car comme le précise la documentation de Perl : A loop LABEL is not actually a valid target for a goto; it’s just the name of the loop. (L’étiquette d’une boucle n’est pas une cible valide pour un goto, il s’agit juste du nom de la boucle.) last La commande last permet de sortir immédiatement d’une boucle. Elle accepte une étiquette optionnelle pour indiquer de quelle boucle on veut sortir, dans le cas de plusieurs boucles imbriquées. Sinon, on sort de la boucle la plus petite contenant l’instruction last. while(<>) { # sort de la boucle last if /^__END__/; ... } # pour continuer ici Avec plusieurs boucles imbriquées : EXTERNE: for my $i ( @indexes ) { } INTERNE: for my $j ( @jndexes ) { ... last EXTERNE if $j == 42; } last ne peut pas être utilisé pour sortir d’un bloc eval {}, sub {} ou do {} (car ceux-ci renvoient une valeur). Il ne peut pas non plus être utilisé pour sortir du bloc de code exécuté par une instruction grep() ou map(). next next permet de court-circuiter la fin de la boucle (comme last) pour reprendre à l’itération suivante. Les instructions associées aux itérations des boucles sont traitées normalement. Ainsi, dans le cas d’une boucle for « à la C », l’expression de modification et l’expression de test sont exécutées. Pour une boucle foreach, l’élément suivant de la liste traitée est utilisé pour la variable d’indice. Et dans le cas d’une boucle while, le bloc continue est exécuté, ainsi que l’expression de test associée au while. # exemple d’analyseur de fichiers while(<>) { # ignore commentaires et lignes blanches next if /^\s*(#|$)/; chomp; ... } redo L’instruction redo ramène le pointeur d’instruction au début du bloc courant (elle accepte également une étiquette pour les cas de blocs imbriqués), sans exécuter les calculs de condition de la structure for, foreach ou while associée. redo ne peut pas être utilisé pour ré- essayer un bloc qui renvoie une valeur, comme eval {}, sub {} ou do {}, ni dans le bloc associé à une instruction grep, map ou sort. En revanche, sachez qu’un bloc étant équivalent à une boucle qui ne s’exécute qu’une seule fois, il est donc possible d’utiliser redo pour le transformer en construction de boucle. continue BLOC Les blocs continue sont associés aux structures de boucles et sont toujours exécutés à la fin de chaque tour de boucle (y compris ceux interrompus par last ou next, c’est tout l’intérêt) juste avant l’évaluation de la clause de condition. 77 code Ceci sert évidement quand on sort prématurément du corps d’une boucle avec next. L’instruction redo ne provoque pas l’exécution du bloc continue. Les instructions next, redo et last peuvent parfaitement apparaître dans un bloc continue. redo et last se comportent comme s’ils avaient été exécutés dans le bloc principal de la boucle. Comme next provoque l’exécution du bloc continue, cela peut provoquer des effets « intéressants » (mais rarement utiles). Notez qu’on peut tout à fait associer un bloc continue à une boucle foreach. En Perl objet, quand on appelle une méthode, Perl va parcourir le tableau @ISA de la classe pour trouver une méthode portant ce nom. Si cette recherche ne donne rien, Perl va alors chercher si l’une des classes définit une méthode AUTOLOAD qui sera alors appelée. Cette méthode va pouvoir exécuter un traitement de substitution pour pallier l’absence de la méthode recherchée. Voici un extrait du module HTTP::Message qui utilise cette technique : # delegate all other method calls the the _headers object. sub AUTOLOAD { my $method = substr($AUTOLOAD, rindex($AUTOLOAD, ‘::’)+2); return if $method eq „DESTROY“; La commande goto Malgré l’existence des commandes de sortie de boucle, une commande goto a tout de même son utilité. C’est ainsi qu’il existe en fait trois formes de goto en Perl. goto ETIQUETTE 78 La forme goto-ETIQUETTE retrouve l’instruction qui porte l’étiquette et continue l’exécution à partir de ce point. Attention, on ne peut pas s’en servir pour sauter à l’intérieur d’un sous-programme ou d’une boucle foreach. De même, on ne peut entrer dans une construction qui est supprimée par le compilateur à la phase d’optimisation, ou pour sortir d’un bloc ou d’une routine passée à sort(). goto EXPR Cette forme permet de faire des goto calculés, à la manière FORTRAN que nous avons vue plus haut. goto („TOTO“, „TITI“, „TUTU“)[$i]; Si le résultat de l’expression est une étiquette qui n’existe pas, nous aurons droit à l’erreur Can’t find label LABEL, tandis que ce sera goto must have a label si le résultat de l’expression est vide (undef). Nous ne connaissons personne ayant eu besoin d’utiliser ce type de goto. goto &NOM Ce goto est assez différent du goto habituel. Il s’agit ici de sauter vers une autre fonction de façon transparente, en effaçant la fonction exécutant le goto de la pile d’appel. Cette technique est beaucoup utilisée en combinaison avec la méthode AUTOLOAD. } # We create the function here so that it will not need to be # autoloaded the next time. no strict ‘refs’; *$method = eval „sub { shift->{‘_headers’}->$method(\@_) }“; goto &$method; Ici, les méthodes inconnues sont déléguées de façon transparente à l’objet associé aux en-têtes du message. La ligne qui précède le goto insère une nouvelle référence de code dans la table des symboles du paquetage en question (ici, HTTP::Message) et le goto se charge d’appeler cette fonction de façon transparente, comme si elle avait toujours existé à cet endroit. Nous sortons ici du cadre que nous nous étions imposé au début de cette partie, car cette forme de goto est en réalité un appel à un sous-programme. Les programmeurs qui découvrent AUTOLOAD laissent souvent libre cours à leur paresse et l’utilisent pour définir les accesseurs de leur classe de cette façon. Nous ne recommandons pas cette technique, qui est à notre avis plus propice à la création de bogues difficiles à tracer (AUTOLOAD va par exemple essayer de faire quelque chose même si la fonction appelée résulte en fait d’une faute de frappe, si votre AUTOLOAD ne provoque pas d’erreur dans ce cas, on aura appelé une fonction qui ne fait probablement rien. Difficile de retrouver la faute de frappe dans ces conditions). Nous préférons la technique qui consiste à compiler les accesseurs à l’avance et à les positionner directement dans la table des symboles du paquetage. for my $attr (qw( name id height width )) { no strict ‘refs’; *{„get_$attr“} = sub { $_[0]->{$attr} }; } Les accesseurs ainsi créés s’utilisent comme s’ils avaient été définis avec sub. Comme ce code est en général dans un module chargé avec use, les fonctions sont disponibles dès le use exécuté. Ce code s’appuie sur les propriétés des fermetures (closures). Notre exemple montre des accesseurs de type get(), mais il est bien sûr possible d’implémenter des méthodes plus complexes ou d’utiliser plusieurs boucles d’initialisation. Il suffit de comparer avec le code équivalent pour voir l’intérêt de cette écriture au niveau de la maintenabilité et de l’évolution du code : # imaginez une définition plus complexe # et trente fonctions identiques sub get_name { $_[0]->{name} } sub get_id { $_[0]->{id} } sub get_height { $_[0]->{height} } sub get_width { $_[0]->{width} } Avec notre exemple, un éventuel changement d’implémentation est instantané, sans risque d’erreur à la recopie et l’ajout d’une méthode revient simplement à ajouter un mot dans la liste passée au foreach. Exemples pratiques Maintenant que nous avons exposé l’histoire et les alternatives au goto, voici quelques exemples pratiques d’utilisation. Une routine de recherche Supposons que l’on cherche l’adresse de divers correspondants. Ces adresses sont stockées à différents niveaux de mémoire, dans une variable du programme, dans un fichier se trouvant sur la machine locale, dans une base de données accessible par le réseau local ou sur Internet. Dans un but de performances, on privilégiera l’accès le plus rapide. use DBI; use WWW::Search::PagesJaunes; my $repert = ‘/home/moi/adresses.txt’; my $db_source = ‘???’; my $db_user = ‘moi’; my $db_passwd = ‘s3kr3t’; my %adresse; sub recherche { my ($qui) = @_; # Cas idéal, il est déjà en mémoire return $adresse{$qui} if $adresse{$qui}; # Fichier local, peut-être ? open REPERT, $repert or goto ESSAI_BDD; while () { my ( $lui, $ou ) = split ‘:’; # Si trouvé, on mémorise et on renvoie return $adresse{$lui} = $ou if $lui eq $qui; Goto en Perl } close REPERT; ESSAI_BDD: my $dbh = DBI->connect( $data_source, $db_user, $db_passwd ) or goto ESSAI_INTERNET; my $acces = $dbh->prepare(„SELECT adresse FROM personnes WHERE nom = ?“); return $dbh->selectrow_array($acces) or goto ESSAI_INTERNET; ESSAI_INTERNET: my $pj = WWW::Search::Pagesjaunes->new(); $pj->find( nom => $qui, departement => “75” ); my @resultats = $pj->results(); return $resultats[0]->addresse if @resultats; } Cet exemple montre l’un des cas d’utilisation admise du goto : la reprise après erreur. Cette fonction est lisible pour deux raisons : tous les goto descendent et la fonction tient sur une page d’écran (nous sommes désolés si la pagination du magazine fait que ce n’est pas le cas sur le papier). La variante sans goto aurait conduit à utiliser un indicateur booléen et à enrober chacun des accès élémentaires read, fetch ou get par un test vérifiant le succès de l’accès précédent open, connect. En fait, on peut également se passer complètement de l’utilisation de goto pour cet exemple, en utilisant des tables de distribution (dispatch tables, voir l’article « Perles de Mongueurs » à ce sujet dans GNU/Linux Magazine 65). Cette technique a l’avantage d’être plus facilement extensible. my %adresse; # table de distribution des méthodes utilisables # l’ordre alphabétique des clés permet de définir # l’ordre de préférence des techniques de recherche my %recherche = ( r00_memoire => sub { return $adresse{$_[0]} } # déclaration en ligne r01_local => \&recherche_fichier, # fonctions définies r02_bdd => \&recherche_bdd, # un peu plus loin r03_internet => \&recheche_internet, # dans le script ); sub recherche { my ($qui) = @_; my $adresse; for my $essai ( sort keys %recherche) { $adresse = $recherche{$essai}->( $qui ); last if $adresse; } # technique de cache pour accélerer les recherches suivantes : # on enrichit le cache local $adresse{$qui} = $address if defined $adresse; } return $adresse; # recherche dans un fichier my $repert = ‘/home/moi/adresses.txt’; sub recherche_fichier { open my $fh, $repert or return; while (<$fh>) { my ( $lui, $ou ) = split ‘:’; return $ou if $lui eq $qui; } close $fh; } # recherche dans une base de données use DBI; my $db_source = ‘???’; my $db_user = ‘moi’; my $db_passwd = ‘s3kr3t’; sub recherche_bdd { # même code que dans l’exemple précédent } A: $car = ; goto FIN unless defined $car; if ($car =~ /[[:alnum:]]/) { $ident = $car; goto B } if ($car eq ‘“’) { $chaine = ‘’; goto C } goto A; B: $car = ; goto FIN unless defined $car; if ($car =~ /[[:alnum:]]/) { $ident .= $car; goto B } if ($car eq q(„)) { $chaine = ‘’; goto C } goto A; C: $car = ; goto D if $car eq q(\\); if ($car eq q(„)) { store($ident, $chaine); goto A } $chaine .= $car; goto C; # recherche sur Internet use WWW::Search::PagesJaunes; sub recherche_internet { # même code que dans l’exemple précédent } L’ajout d’une nouvelle technique de recherche se cantonnera donc à l’ajout d’une fonction dans le code et d’une clé dans la table de hachage. Pour changer l’ordre des tentatives, il suffit de renommer les clés de la table de hachage. Un analyseur lexical et syntaxique Nous prenons un exemple inspiré d’un programme réel conçu par l’un des coauteurs. Je travaillais sur un projet pour écrire des programmes C/SQL qui devaient être déployés dans plusieurs pays. Dès l’origine, il a été convenu de scinder le source de chaque programme en au moins deux fichiers, toto.c qui contient les traitements et toto.h qui contient quelques déclarations du genre : #define MSG „C’est planté !“ char *url = „http://www.mongueurs.net/“; char *actions [] = { „PUT“, „GET“, „POST“ }; char *histoire [] = { “Il demanda : \”Quand ?\”\n”, “Elle répondit : \“Demain...\x22\n“ }; Et c’est à moi qu’est revenue la tâche de spécifier les utilitaires permettant d’extraire les chaînes à traduire et de réinjecter les chaînes traduites. Comme les fichiers en entrée obéissaient à une syntaxe C très simplifiée, l’extraction pouvait se baser sur un automate à quatre états (dans la réalité un peu plus, les fichiers pouvant contenir des commentaires). Voici ce que cela donne en Perl : #!/usr/local/bin/perl # # Extraction des libellés d’un source C simplifié # use strict; use warnings; local $/ = \1; # lecture caractère par caractère my $ident; my $chaine; my $car; open IN, $ARGV[0] or die “Problème avec le fichier“; D: $car = ; $chaine .= q(\\) . $car; goto C; FIN: print “Fini !\n”; sub store { my ($ident, $chaine) = @_; print “$ident -> $chaine\n” # En fait un ordre SQL } Au fait, nous vous avions promis un exemple de la méthode de Jacopini pour éliminer les GOTO. Voici ce que donnerait cette méthode : #!/usr/local/bin/perl # # Extraction des libellés d’un source C simplifié # avec la méthode de Jacopini # use strict; use warnings; local $/ = \1; # caractère par caractère my $ident; my $chaine; my $car; open IN, $ARGV[0] or die “Problème avec le fichier“; my $etiq = ‘A’; while ($etiq ne ‘FIN’) { if ($etiq eq ‘A’) { $car = ; if (not defined $car) { $etiq = ‘FIN’ } elsif ($car =~ /[[:alnum:]]/) { $ident = $car; $etiq = ‘B’ } elsif ($car eq ‘”’) { $chaine = ‘’; $etiq = ‘C’ } else { $etiq = ‘A’ } } if ($etiq eq ‘B’) { $car = ; if (not defined $car) { $etiq = ‘FIN’ } elsif ($car =~ /[[:alnum:]]/) { $ident .= $car; $etiq = ‘B’ } elsif ($car eq q(“)) { $chaine = ‘’; $etiq = ‘C’ } else { $etiq = ‘A’ } } if ($etiq eq ‘C’) { $car = ; if ($car eq q(\\)) { $etiq = ‘D’ } elsif ($car eq q(“)) { store($ident, $chaine); $etiq = ‘A’ } else { $chaine .= $car; $etiq = ‘C’ } } 79 code sub AUTOLOAD { if ($etiq eq ‘D’) { $car = ; $chaine .= q(\\) . $car; $etiq = ‘C’; } # notre classe n’a pas de méthode DESTROY return if $AUTOLOAD =~ /::DESTROY/; # la fonction rights() renvoie la liste des droits # associés à cet utilisateur dans la base if( $AUTOLOAD =~ /::is_(\w+)$/ ) { my $attr = $1; no strict ‘refs’; } print “Fini !\n”; sub store { my ($ident, $chaine) = @_; print “$ident -> $chaine\n” } # crée la méthode et l’insère dans la table des symboles # du paquetage en cours (celui de la classe) *{$AUTOLOAD} = sub { $_[0]->rights()->{$attr} }; Vous serez, je pense, d’accord avec Dijkstra, Knuth et nous-mêmes, cette version est illisible ! La méthode AUTOLOAD 80 Voici un exemple d’utilisation d’AUTOLOAD pour définir le plus tard possible (à l’exécution) le code d’une fonction. C’est le cas usuel d’utilisation du goto routine en Perl. L’exemple de code ci-après est utilisé en production pour définir des accesseurs associés à des valeurs extraites d’une base de donnée. Une table rights définit des associations user_id, right_id, où l’identificateur du droit est une simple chaîne de caractères (admin, support, etc.). Les méthodes is_ admin(), is_support(), etc. sont utilisées dans d’autres parties du code et dans des templates pour déterminer ce à quoi l’utilisateur connecté a accès. } } # appel la méthode de façon transparente goto &{$AUTOLOAD}; de nouveaux mots-clés pour faciliter la programmation structurée. C’est pourquoi en Perl, le goto « classique » est réservé à certains types de programmes et ne doit pas être utilisé pour la sortie de boucles, la gestion d’exception ou l’émulation d’une instruction case. Le goto routine de Perl n’est pas couvert par les réticences d’Edsger Dijkstra : c’est un moyen très courant de manipuler la pile d’appels, qui est souvent utilisé en programmation objet en Perl. # meurt si une méthode inconnue a été appelée croak „AUTOLOAD: Unknown method $AUTOLOAD“; Avec cette technique, les méthodes d’accès aux droits n’ont pas a être ajoutées au fur et à mesure qu’on invente de nouvelles catégories d’utilisateurs et on garantit qu’elles sont toutes codées de la même façon. Auteurs Conclusion Jean Forget Jean Forget pratique Perl depuis 1998 et a quasiment cessé d’utiliser C et awk depuis cette date. Il est secrétaire de l’association « Les Mongueurs de Perl », ainsi que membre du groupe de Paris. Il a participé en tant que correcteur à la traduction de la troisième édition de Programming Perl. Vous l’avez constaté, il existe de nombreux cas en programmation où l’instruction goto est appropriée. Mais depuis la polémique autour de l’utilisation du goto, les langages de programmation ont adopté Philippe “BooK” Bruhat, <book@ mongueurs.net> Philippe Bruhat est président de l’association « Les Mongueurs de Perl » (http://www.mongueurs.net/), membre Annexe Si vous avez lu l’article de Knuth, vous n’avez peut-être pas prêté J’ai vu ces phrases traduites ainsi : attention à l’expression « four-letter words like goto » utilisée par Mauvais Elle n’employait jamais un mot de cinq ou six lettres Knuth. Moi, si. En effet, elle faisait écho à un article que j’ai écrit quand un mot de quatre lettres pouvait suffire. Elle avait un en d’autres circonstances pour un autre public. langage ordurier auquel même nous, vieux pilotes de chasse, En dehors de la programmation Perl, je pratique les jeux de n’arrivions pas à nous faire. simulation historique (wargames). La plupart sont en anglais, La traduction correcte serait plutôt : mais on trouve parfois des traductions pour certains. À force de lire des mauvaises traductions (dont certaines venaient de ma Bon Elle n’employait jamais un mot de six ou sept lettres quand plume :-(), j’ai décidé de mettre par écrit un certain nombre de un mot de cinq lettres pouvait suffire. Elle avait un langage conseils concernant la traduction de l’anglais vers le français, ordurier auquel même nous, vieux pilotes de chasse, n’arrivions conseils que l’on n’apprend pas toujours au collège ou au lycée. pas à nous faire. Pour l’extrait suivant, vous aurez peut-être besoin de revoir la première heure de L’Étoffe des Héros et de réviser votre Histoire de France, ou bien, de chercher les noms propres dans votre moteur de recherche favori (méfiez-vous des homonymes : cherchez « général Pierre Koenig » dans les pages en français). Si vous avez vu L’Étoffe des Héros, vous vous souvenez peut-être de Pancho Barnes, la tenancière du saloon de la base d’Edwards, un personnage haut en couleurs. Dans son autobiographie, Chuck Yeager la décrit ainsi : V.O. Pancho would never use a five- or six-letter word when a four-letter word would do. She had the filthiest mouth that any of us fighter jocks had ever heard. Et pourquoi ? Parce que pour les Français, les termes « un mot de cinq lettres » ne désignent pas n’importe quel mot de la longueur indiquée, mais un mot bien particulier. Vous savez, le « mot de Cambronne », que le général Koenig, assiégé à Bir Hakeim, aurait prononcé quand on lui proposait de se rendre. De même, l’expression « four-letter word » désigne pour les Américains, non pas un mot, mais une série de mots à usage... disons, spécialisé. Cela va du « Nuts » anodin du général McAuliffe, assiégé à Bastogne en 1944 (1) aux deux mots S**t et F**k que vous connaissez bien, en passant par d’autres que je ne vous enseignerai pas. Par conséquent, la véritable traduction de « four-letter word » est « mot de cinq lettres ». Par extension, dans la phrase citée en exemple, il faudra traduire « five or six » par « six ou sept »(2). (1) Comme quoi, les généraux commandant des troupes d’élite (Vieille Garde, Légion Étrangère, Parachutistes) ont parfois les mêmes idées. À propos, quelqu’un peut-il m’indiquer quel mot grossier fut proféré par Fingon, le Haut-Roi des Noldor, encerclé à la bataille des Larmes Innombrables ? ;-) (2) Pour en revenir à la phrase de Knuth, le nombre de lettres n’a aucun intérêt. La traduction qui s’impose serait donc : « des mots obscènes comme goto ». Goto en Perl des groupes Paris.pm et Lyon.pm. Il est consultant en Perl et en sécurité et l’auteur des modules Log::Procmail, HTTP:: Proxy, Regexp::Log et Acme::MetaSyntactic, disponibles sur CPAN. Dans HTTP:: Proxy, il est fier d’avoir utilisé deux des Références goto Edsger W. Dijkstra, Go To Statement Considered Harmful http://www.acm.org/classics/oct95/ Pendant près de quarante ans, Dijkstra a tenu une correspondance abondante avec ses collègues chercheurs. La plupart de ces manuscrits ont été transcrits et sont disponibles sur l’Edsger W. Dijkstra Archive : http://www.cs.utexas.edu/ users/EWD/ Donald E. Knuth, « Structured Programming with go to Statements », Computing Surveys, Vol. 6, No. 4, December 1974. Literate Programming (CSLI Lectures Notes 27, 1992) reprend cet article et bien d’autres. R. Lawrence Clark, « A Linguistic Contribution of GOTO-less Programming », DATAMATION, décembre 1973. http://www.fortranlib.com/gotoless.htm Jargon : considered harmful http://catb.org/~esr/jargon/html/C/ considered-harmful.html Langages de programmation Wikipedia : « Timeline of Programmin g Languages » http://en.wikipedia.org/wiki/Timeline_ of_programming_languages International Obfuscated C Code Contest http://www.ioccc.org/years. html#1987_hines Des références sur FORTRAN http://www.pgroup.com/ppro_docs/ pgf77_ref/f77ref.htm Des références sur COBOL http://www.csis.ul.ie/COBOL/default. htm http://home.swbell.net/mck9/cobol/ cobol.html Perl Club Les règles du Perl Club sont listées sur le site de Dave Cross, http://www.dave.org.uk/perlclub.html Ces règles sont bien sûr inspirées du film Fight Club de David Fincher, avec Edward Norton et Brad Pitt, http://www.imdb.com/title/tt0137523/ trois formes de goto pour créer un minianalyseur de HTML (goto ETIQUETTE, redo) et pour créer des objets avec des méthodes spécifiques à chaque instance (goto &CODEREF). Il vous invite à venir nombreux à la prochaine conférence Perl francophone, Les Journées Perl 2005, qui auront lieu à Marseille, les 9 et 10 juin 2005. http://conferences.mongueurs. net/fpw2005/ Références perlfunc(1) Cette page de manuel contient la documentation de goto, last, next, redo et continue. perlref(1) Le point 4 de la section Making references explique en détail ce que sont les closures. perlfaq7(1) La FAQ de Perl contient également une définition des closures. Vous pouvez y accéder directement par la commande perldoc -q closure. Java : « Handling Errors with Exceptions » Chapitre consacré aux exceptions dans le tutoriel Java, http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html INTERCAL Le premier langage à implémenter le COME FROM, http://www.catb.org/~esr/intercal/ 2 sites incontournables Toute l’actualité du magazine sur : www.gnulinuxmag.com Abonnements et anciens numéros en vente sur : www.ed-diamond.com 81 Creative Commons Paternité - Pas d'Utilisation Commerciale - Pas de Modification 2.0 Creative Commons n'est pas un cabinet d'avocats et ne fournit pas de services de conseil juridique. La distribution de la présente version de ce contrat ne crée aucune relation juridique entre les parties au contrat présenté ci-après et Creative Commons. Creative Commons fournit cette offre de contrat-type en l'état, à seule fin d'information. Creative Commons ne saurait être tenu responsable des éventuels préjudices résultant du contenu ou de l'utilisation de ce contrat. Contrat L'Oeuvre (telle que définie ci-dessous) est mise à disposition selon les termes du présent contrat appelé Contrat Public Creative Commons (dénommé ici « CPCC » ou « Contrat »). L'Oeuvre est protégée par le droit de la propriété littéraire et artistique (droit d'auteur, droits voisins, droits des producteurs de bases de données) ou toute autre loi applicable. Toute utilisation de l'Oeuvre autrement qu'explicitement autorisée selon ce Contrat ou le droit applicable est interdite. L'exercice sur l'Oeuvre de tout droit proposé par le présent contrat vaut acceptation de celui-ci. Selon les termes et les obligations du présent contrat, la partie Offrante propose à la partie Acceptante l'exercice de certains droits présentés ci-après, et l'Acceptant en approuve les termes et conditions d'utilisation. 1. Définitions a. « Oeuvre » : oeuvre de l'esprit protégeable par le droit de la propriété littéraire et artistique ou toute loi applicable et qui est mise à disposition selon les termes du présent Contrat. b. « Oeuvre dite Collective » : une oeuvre dans laquelle l'oeuvre, dans sa forme intégrale et non modifiée, est assemblée en un ensemble collectif avec d'autres contributions qui constituent en elles-mêmes des oeuvres séparées et indépendantes. Constituent notamment des Oeuvres dites Collectives les publications périodiques, les anthologies ou les encyclopédies. Aux termes de la présente autorisation, une oeuvre qui constitue une Oeuvre dite Collective ne sera pas considérée comme une Oeuvre dite Dérivée (telle que définie ci-après). c. « Oeuvre dite Dérivée » : une oeuvre créée soit à partir de l'Oeuvre seule, soit à partir de l'Oeuvre et d'autres oeuvres préexistantes. Constituent notamment des Oeuvres dites Dérivées les traductions, les arrangements musicaux, les adaptations théâtrales, littéraires ou cinématographiques, les enregistrements sonores, les reproductions par un art ou un procédé quelconque, les résumés, ou toute autre forme sous laquelle l'Oeuvre puisse être remaniée, modifiée, transformée ou adaptée, à l'exception d'une oeuvre qui constitue une Oeuvre dite Collective. Une Oeuvre dite Collective ne sera pas considérée comme une Oeuvre dite Dérivée aux termes du présent Contrat. Dans le cas où l'Oeuvre serait une composition musicale ou un enregistrement sonore, la synchronisation de l'oeuvre avec une image animée sera considérée comme une Oeuvre dite Dérivée pour les propos de ce Contrat. d. « Auteur original » : la ou les personnes physiques qui ont créé l'Oeuvre. e. « Offrant » : la ou les personne(s) physique(s) ou morale(s) qui proposent la mise à disposition de l'Oeuvre selon les termes du présent Contrat. f. « Acceptant » : la personne physique ou morale qui accepte le présent contrat et exerce des droits sans en avoir violé les termes au préalable ou qui a reçu l'autorisation expresse de l'Offrant d'exercer des droits dans le cadre du présent contrat malgré une précédente violation de ce contrat. 2. Exceptions aux droits exclusifs. Aucune disposition de ce contrat n'a pour intention de réduire, limiter ou restreindre les prérogatives issues des exceptions aux droits, de l'épuisement des droits ou d'autres limitations aux droits exclusifs des ayants droit selon le droit de la propriété littéraire et artistique ou les autres lois applicables. 3. Autorisation. Soumis aux termes et conditions définis dans cette autorisation, et ceci pendant toute la durée de protection de l'Oeuvre par le droit de la propriété littéraire et artistique ou le droit applicable, l'Offrant accorde à l'Acceptant l'autorisation mondiale d'exercer à titre gratuit et non exclusif les droits suivants : a. reproduire l'Oeuvre, incorporer l'Oeuvre dans une ou plusieurs Oeuvres dites Collectives et reproduire l'Oeuvre telle qu'incorporée dans lesdites Oeuvres dites Collectives; b. distribuer des exemplaires ou enregistrements, présenter, représenter ou communiquer l'Oeuvre au public par tout procédé technique, y compris incorporée dans des Oeuvres Collectives; c. lorsque l'Oeuvre est une base de données, extraire et réutiliser des parties substantielles de l'Oeuvre. Les droits mentionnés ci-dessus peuvent être exercés sur tous les supports, médias, procédés techniques et formats. Les droits cidessus incluent le droit d'effectuer les modifications nécessaires techniquement à l'exercice des droits dans d'autres formats et procédés techniques. L'exercice de tous les droits qui ne sont pas expressément autorisés par l'Offrant ou dont il n'aurait pas la gestion demeure réservé, notamment les mécanismes de gestion collective obligatoire applicables décrits à l'article 4(d). 4. Restrictions. L'autorisation accordée par l'article 3 est expressément assujettie et limitée par le respect des restrictions suivantes : a. L'Acceptant peut reproduire, distribuer, représenter ou communiquer au public l'Oeuvre y compris par voie numérique uniquement selon les termes de ce Contrat. L'Acceptant doit inclure une copie ou l'adresse Internet (Identifiant Uniforme de Ressource) du présent Contrat à toute reproduction ou enregistrement de l'Oeuvre que l'Acceptant distribue, représente ou communique au public y compris par voie numérique. L'Acceptant ne peut pas offrir ou imposer de conditions d'utilisation de l'Oeuvre qui altèrent ou restreignent les termes du présent Contrat ou l'exercice des droits qui y sont accordés au bénéficiaire. L'Acceptant ne peut pas céder de droits sur l'Oeuvre. L'Acceptant doit conserver intactes toutes les informations qui renvoient à ce Contrat et à l'exonération de responsabilité. L'Acceptant ne peut pas reproduire, distribuer, représenter ou communiquer au public l'Oeuvre, y compris par voie numérique, en utilisant une mesure technique de contrôle d'accès ou de contrôle d'utilisation qui serait contradictoire avec les termes de cet Accord contractuel. Les mentions ci-dessus s'appliquent à l'Oeuvre telle qu'incorporée dans une Oeuvre dite Collective, mais, en dehors de l'Oeuvre en ellemême, ne soumettent pas l'Oeuvre dite Collective, aux termes du présent Contrat. Si l'Acceptant crée une Oeuvre dite Collective, à la demande de tout Offrant, il devra, dans la mesure du possible, retirer de l'Oeuvre dite Collective toute référence au dit Offrant, comme demandé. Si l'Acceptant crée une Oeuvre dite Collective, à la demande de tout Auteur, il devra, dans la mesure du possible, retirer de l'Oeuvre dite Collective toute référence au dit Auteur, comme demandé. b. L'Acceptant ne peut exercer aucun des droits conférés par l'article 3 avec l'intention ou l'objectif d'obtenir un profit commercial ou une compensation financière personnelle. L'échange de l'Oeuvre avec d'autres Oeuvres protégées par le droit de la propriété littéraire et artistique par le partage électronique de fichiers, ou par tout autre moyen, n'est pas considéré comme un échange avec l'intention ou l'objectif d'un profit commercial ou d'une compensation financière personnelle, dans la mesure où aucun paiement ou compensation financière n'intervient en relation avec l'échange d'Oeuvres protégées. c. Si l'Acceptant reproduit, distribue, représente ou communique l'Oeuvre au public, y compris par voie numérique, il doit conserver intactes toutes les informations sur le régime des droits et en attribuer la paternité à l'Auteur Original, de manière raisonnable au regard au médium ou au moyen utilisé. Il doit communiquer le nom de l'Auteur Original ou son éventuel pseudonyme s'il est indiqué ; le titre de l'Oeuvre Originale s'il est indiqué ; dans la mesure du possible, l'adresse Internet ou Identifiant Uniforme de Ressource (URI), s'il existe, spécifié par l'Offrant comme associé à l'Oeuvre, à moins que cette adresse ne renvoie pas aux informations légales (paternité et conditions d'utilisation de l'Oeuvre). Ces obligations d'attribution de paternité doivent être exécutées de manière raisonnable. Cependant, dans le cas d'une Oeuvre dite Collective, ces informations doivent, au minimum, apparaître à la place et de manière aussi visible que celles à laquelle apparaissent les informations de même nature. d. Dans le cas où une utilisation de l'Oeuvre serait soumise à un régime légal de gestion collective obligatoire, l'Offrant se réserve le droit exclusif de collecter ces redevances par l'intermédiaire de la société de perception et de répartition des droits compétente. Sont notamment concernés la radiodiffusion et la communication dans un lieu public de phonogrammes publiés à des fins de commerce, certains cas de retransmission par câble et satellite, la copie privée d'Oeuvres fixées sur phonogrammes ou vidéogrammes, la reproduction par reprographie. 5. Garantie et exonération de responsabilité a. En mettant l'Oeuvre à la disposition du public selon les termes de ce Contrat, l'Offrant déclare de bonne foi qu'à sa connaissance et dans les limites d'une enquête raisonnable : i. L'Offrant a obtenu tous les droits sur l'Oeuvre nécessaires pour pouvoir autoriser l'exercice des droits accordés par le présent Contrat, et permettre la jouissance paisible et l'exercice licite de ces droits, ceci sans que l'Acceptant n'ait aucune obligation de verser de rémunération ou tout autre paiement ou droits, dans la limite des mécanismes de gestion collective obligatoire applicables décrits à l'article 4(e); b. L'Oeuvre n'est constitutive ni d'une violation des droits de tiers, notamment du droit de la propriété littéraire et artistique, du droit des marques, du droit de l'information, du droit civil ou de tout autre droit, ni de diffamation, de violation de la vie privée ou de tout autre préjudice délictuel à l'égard de toute tierce partie. c. A l'exception des situations expressément mentionnées dans le présent Contrat ou dans un autre accord écrit, ou exigées par la loi applicable, l'Oeuvre est mise à disposition en l'état sans garantie d'aucune sorte, qu'elle soit expresse ou tacite, y compris à l'égard du contenu ou de l'exactitude de l'Oeuvre. 6. Limitation de responsabilité. A l'exception des garanties d'ordre public imposées par la loi applicable et des réparations imposées par le régime de la responsabilité vis-à-vis d'un tiers en raison de la violation des garanties prévues par l'article 5 du présent contrat, l'Offrant ne sera en aucun cas tenu responsable vis-à-vis de l'Acceptant, sur la base d'aucune théorie légale ni en raison d'aucun préjudice direct, indirect, matériel ou moral, résultant de l'exécution du présent Contrat ou de l'utilisation de l'Oeuvre, y compris dans l'hypothèse où l'Offrant avait connaissance de la possible existence d'un tel préjudice. 7. Résiliation a. Tout manquement aux termes du contrat par l'Acceptant entraîne la résiliation automatique du Contrat et la fin des droits qui en découlent. Cependant, le contrat conserve ses effets envers les personnes physiques ou morales qui ont reçu de la part de l'Acceptant, en exécution du présent contrat, la mise à disposition d'Oeuvres dites Dérivées, ou d'Oeuvres dites Collectives, ceci tant qu'elles respectent pleinement leurs obligations. Les sections 1, 2, 5, 6 et 7 du contrat continuent à s'appliquer après la résiliation de celui-ci. b. Dans les limites indiquées ci-dessus, le présent Contrat s'applique pendant toute la durée de protection de l'Oeuvre selon le droit applicable. Néanmoins, l'Offrant se réserve à tout moment le droit d'exploiter l'Oeuvre sous des conditions contractuelles différentes, ou d'en cesser la diffusion; cependant, le recours à cette option ne doit pas conduire à retirer les effets du présent Contrat (ou de tout contrat qui a été ou doit être accordé selon les termes de ce Contrat), et ce Contrat continuera à s'appliquer dans tous ses effets jusqu'à ce que sa résiliation intervienne dans les conditions décrites ci-dessus. 8. Divers a. A chaque reproduction ou communication au public par voie numérique de l'Oeuvre ou d'une Oeuvre dite Collective par l'Acceptant, l'Offrant propose au bénéficiaire une offre de mise à disposition de l'Oeuvre dans des termes et conditions identiques à ceux accordés à la partie Acceptante dans le présent Contrat. b. La nullité ou l'inapplicabilité d'une quelconque disposition de ce Contrat au regard de la loi applicable n'affecte pas celle des autres dispositions qui resteront pleinement valides et applicables. Sans action additionnelle par les parties à cet accord, lesdites dispositions devront être interprétées dans la mesure minimum nécessaire à leur validité et leur applicabilité. c. Aucune limite, renonciation ou modification des termes ou dispositions du présent Contrat ne pourra être acceptée sans le consentement écrit et signé de la partie compétente. d. Ce Contrat constitue le seul accord entre les parties à propos de l'Oeuvre mise ici à disposition. Il n'existe aucun élément annexe, accord supplémentaire ou mandat portant sur cette Oeuvre en dehors des éléments mentionnés ici. L'Offrant ne sera tenu par aucune disposition supplémentaire qui pourrait apparaître dans une quelconque communication en provenance de l'Acceptant. Ce Contrat ne peut être modifié sans l'accord mutuel écrit de l'Offrant et de l'Acceptant. e. Le droit applicable est le droit français. Creative Commons n'est pas partie à ce Contrat et n'offre aucune forme de garantie relative à l'Oeuvre. Creative Commons décline toute responsabilité à l'égard de l'Acceptant ou de toute autre partie, quel que soit le fondement légal de cette responsabilité et quel que soit le préjudice subi, direct, indirect, matériel ou moral, qui surviendrait en rapport avec le présent Contrat. Cependant, si Creative Commons s'est expressément identifié comme Offrant pour mettre une Oeuvre à disposition selon les termes de ce Contrat, Creative Commons jouira de tous les droits et obligations d'un Offrant. A l'exception des fins limitées à informer le public que l'Oeuvre est mise à disposition sous CPCC, aucune des parties n'utilisera la marque « Creative Commons » ou toute autre indication ou logo afférent sans le consentement préalable écrit de Creative Commons. Toute utilisation autorisée devra être effectuée en conformité avec les lignes directrices de Creative Commons à jour au moment de l'utilisation, telles qu'elles sont disponibles sur son site Internet ou sur simple demande. Creative Commons peut être contacté à http://creativecommons.org/.