Perl Sortie de Rakudo Star

Posté par . Modéré par Mouns.
Tags :
39
30
juil.
2010
Perl
Rakudo, le compilateur Perl 6, annonce aujourd'hui sa première version publique après 10 ans de travail collectif. Baptisée Rakudo * (ou Rakudo Star), elle se base sur la machine virtuelle Parrot, conçue comme un projet indépendant pour interpréter des langages dynamiques.

Ce compilateur est l'implémentation officielle du langage Perl 6, qui est plus ou moins le successeur de Perl 5, dont la première version remonte à 1994. De très nombreuses évolutions sont présentées, révélant les modifications importantes qu'ont subies Perl et sa communauté depuis leur création.

Meme si Rakudo Star n'est pas encore considérée comme une implémentation stable ni même complète de Perl 6, les développeurs de Rakudo espèrent encourager la communauté à tester Perl 6, et à faire remonter des avis sur ce qui fonctionne déjà. Rétrospective : l'histoire de Perl 6

Perl a connu dans les années 1990 un essor très important et est encore aujourd'hui utilisé pour l'administration système, la programmation réseau et web, la bioinformatique et, quoique plus rarement, la création d'applications graphiques.

Perl est un langage atypique, possédant une communauté importante mais discrète, une culture très riche et particulière et des traits de conception assez exceptionnels.

Avant Perl 6

Une grande partie de ces originalités provient probablement de la personnalité du créateur de Perl, Larry Wall. En effet, celui-ci n'a pas initialement bénéficié d'une formation d'informaticien, mais de linguiste. Hacker passionné, Wall fréquentait cependant beaucoup d'informaticiens (au quotidien ou via les newsgroups Usenet, qui sont un peu l'ancêtre des forums web) et est par exemple l'auteur du célèbre programme patch.

Ainsi, Wall commence à travailler sur un nouveau langage nommé Pearl dans les années 1987 (renommé Perl depuis car un langage avec ce nom existait en fait déjà). Son but était de proposer un nouvel outil de manipulation de fichiers de texte, à la fois plus simple et complet que sed et AWK. Le newsgroup comp.sources.misc, sur lequel Wall publie les codes source de son travail reconnaît très vite l'intérêt de Perl. Le langage se développe rapidement, atteignant la version deux en 1988, puis la troisième en 1989.

Durant les années 90, Perl connaît un grand succès et est le deuxième langage s'étant le plus développé pendant cette décennie (après le langage Java, qui bénéficie du marketing constant de la société SUN Microsystems). Le livre Programming Perl de Larry Wall, publié aux éditions O'Reilly en 1991, se pose comme la référence du langage et permet sa diffusion. Simultanément, Perl sort en version 4 laquelle demeure jusqu'en 1994.

À la fin de l'année, Wall publie Perl 5, qui est une refonte quasi-totale du langage et de l'interpréteur. Perl continue de se développer et devient, peu de temps après la naissance du web, l'outil de prédilection pour l'écriture de scripts CGI : ces scripts sont la première forme de programmation côté serveur (bien avant PHP, dont la première version a d'ailleurs été écrite en Perl pour simplifier le développement web). Jusqu'en 2000, Perl 5 continue de se développer (Perl 5.6 sort en mars 2000) et supporte petit à petit de nombreuses plate-formes, de Windows à BeOS.

Larry Wall est constamment impliqué dans le développement de Perl et est d'ailleurs désigné dictateur bénévole à vie par la communauté : par ce titre, les programmeurs utilisant Perl reconnaissent son rôle capital dans le développement du langage, y compris dans les versions futures. Il est intéressant de remarquer que, jusqu'à cette époque, aucune définition formelle du langage n'a été faite : le langage Perl est ce que l'unique interpréteur éponyme, celui auquel Wall contribue, interprète.

Un nouveau langage

Cependant, le développement de Perl connaît au début des années 2000 de grosses difficultés. L'interpréteur est devenu compliqué à maintenir et encore plus à faire évoluer. Ainsi, à la Conférence des projets Open Source de l'éditeur O'Reilly du mois de juillet 2000, Larry Wall annonce la nécessité de reprendre à nouveau les choses à zéro : c'est la naissance de Perl 6. Mais, selon Wall, Perl 6 doit être un travail communautaire. Il propose ainsi aux développeurs Perl de lui soumettre des RFC dans lesquels ils pourront détailler leurs idées.

Les réponses de la communauté sont nombreuses : de 2000 à 2001, Larry Wall doit étudier au total 361 propositions d'améliorations. Il en tire une série d'articles synthétiques, baptisés les Apocalypses (au premier sens du terme, à savoir des « révélations » faites à la communauté). Cependant, ces articles manquent de clarté, et un autre développeur de la communauté, Damian Conway, se charge de les expliquer dans les Exégèses. Conway écrit également des modules pour Perl 5 permettant d'émuler certains traits de Perl 6, notamment pour appuyer ses explications.

Mais tous ces articles peinent à définir Perl 6, et, en 2004, le langage n'a toujours pas progressé. Une nouvelle série d'articles, plus détaillés, paraissent donc : les Synopses. Ces documents contiennent les spécifications de Perl 6 (c'est-à-dire les caractéristiques théoriques du langage) et présentent surtout l'intérêt d'être fréquemment mis à jour, au fur et à mesure que les idées au sujet de Perl 6 évoluent.

Une jeune développeuse, Audrey Tang, entreprend alors de développer une implémentation (c'est-à-dire une version utilisable) de Perl 6, dans le langage de programmation Haskell. Cette version, baptisée Pugs, profite de certaines technologies de Haskell pour se développer rapidement, comme le compilateur GHC et la bibliothèque Parsec. L'implémentation de Tang permet ainsi de finir d'écrire les spécifications de Perl 6 et de commencer à utiliser ce langage. Il est également certain que la conception de Perl 6 a été influencée par Haskell lors de cette phase d'expérimentations et que, sans Pugs, Perl 6 serait aujourd'hui beaucoup moins avancé.

Parrot et Rakudo

Pendant que Perl 6 prenait forme, la question de l'implémentation officielle du langage était également à l'étude. Dès 2001, des développeurs ont étudié la capacité de la JVM à accueillir une implémentation de Perl 6. Mais cette machine virtuelle se révèle, encore aujourd'hui, être très peu adaptée aux langages dynamiques comme Perl. Il a donc été décidé de développer Parrot, une nouvelle machine virtuelle adaptée aux besoins de Perl 6. Cependant, les développeurs de Parrot, menés par la linguiste et développeuse Allison Randal (autre membre éminent de la communauté Perl), ont été plus ambitieux et ont conçu une machine virtuelle indépendante de Perl, ainsi qu'un ensemble d'outils facilitant la création de nouveaux compilateurs pour tous les langages. Il est donc possible de développer de nouveaux langages pour Parrot qui seront compatibles avec tous les programmes Perl.

À condition bien sûr qu'un compilateur pour Perl existe ! Et c'est ce rôle que remplit Rakudo (« la voie du chameau » en japonais, le chameau étant l'animal emblématique de Perl). Il utilise au mieux les technologies proposées par Parrot, telles que le Parser Grammar Engine (PGE). Ce dernier permet de définir simplement la syntaxe d'un langage (ce qui, dans le cas de Perl, n'est pas une mince affaire !) et est en réalité une implémentation directe dans Parrot des grammaires de Perl 6. De plus, Rakudo est écrit dans le langage Not Quite Perl (NQP), lui aussi proposé par Parrot.

Le développement de Rakudo a été séparé de celui de Parrot en février 2009 et a connu depuis un rythme de développement régulier, proposant une nouvelle version tous les mois. Bien qu'il ne soit pas la première implémentation utilisable de Perl 6, Rakudo a été la plus active ces dernières années.

Les modules de CPAN

Conçu en 1995, le CPAN (Comprehensive Perl Archive Network) est une des plus grandes forces de Perl 5 : c'est un ensemble de modules accessibles sur Internet, comprenant aussi bien des bibliothèques pour accéder à des bases de données ou à une interface graphique que des extensions du langage. Il compte actuellement plus de 20 000 modules qui peuvent être téléchargés et installés automatiquement. Les modules du CPAN devraient être compatibles avec Perl 6 sans demander trop de modifications.

Cependant, certains modules pourraient être écrits spécifiquement pour Perl 6 et Parrot (ce qui permettrait de les utiliser depuis n'importe quel langage supporté par la machine virtuelle), d'où la nécessité d'un nouveau réseau : CPAN 6. Celui-ci est encore en développement à l'heure actuelle. Un dépôt de modules est cependant déjà disponible, ainsi que Proto, un système de gestion des dépendances léger pour installer des modules Perl 6.

Les nouveautés de Perl 6

Perl a toujours été un langage regorgeant de fonctionnalités parfois très pointues qui permettent aux programmeurs compétents d'écrire des codes beaucoup plus concis que ce qu'ils écriraient dans les langages de plus bas niveau. Mais il ne s'utilise comme aucun autre langage : ses particularités sont plus ou moins bien comprises par les débutants ou les développeurs issus d'autres technologies, ce qui contribue à lui donner la réputation d'un langage obscur au comportement bizarre.

Perl 6 introduit donc quelques différences avec Perl 5 qui proviennent d'autres langages, et visent à le rendre un peu plus compréhensible et un peu plus rigoureux. De plus, un certain nombre de nouvelles fonctionnalités ont été imaginées pendant le développement de Pugs et proviennent donc du langage fonctionnel Haskell (mais sous une forme adaptée à Perl).

Les sigils et les contextes

Le terme de « sigil » désigne les caractères non-alphabétiques qui précèdent le nom des variables en Perl. Par exemple, les variables « scalaires » (nombres et chaînes) sont précédées d'un dollar et les tableaux - d'un arobase. Ceci trouve son origine dans le passé de linguiste de Larry Wall : pour un être humain, il est naturel de dire

Cette pomme
Ces pommes
Cette troisième pomme


Les sigils ont donc été inventés pour respecter une forme de séparation entre singulier et pluriel. Ainsi, en Perl 5 on écrivait $apple pour désigner une variable scalaire, @apples pour un tableaux de pommes et $apples[2] pour désigner la troisième pomme. Le dollar montrait qu'on ne désignait qu'un seul élément, donc servait de singulier.

Le but de cette approche (à distinguer de celle d'AppleScript) était de permettre d'écrire un code assez naturel pour le programmeur : écrire du Perl devait être aussi simple que de parler. Cependant, les concepteurs de Perl ont par la suite remarqué que certaines utilisations des tableaux ou d'autres structures de données devenaient beaucoup trop complexes pour correspondre à la parole humaine. En d'autres termes, ce mécanisme rendait très simple l'écriture de morceaux de code simples, mais devenait trop compliqué pour des utilisations moins basiques.

Il a donc été décidé, en Perl 6, d'associer une fois pour toute un sigil et sa variable (on écrit donc @apples[2]). Mais un autre trait caractéristique de Perl intervient alors pour déterminer la nature de ce qui est renvoyé : le contexte. De même qu'en anglais ou en français une expression peut avoir un sens différent selon ce qui l'entoure, les expressions Perl sont évaluées dans un certain contexte qui peut faire varier leur résultat. Ainsi, on distingue entre autres le contexte scalaire et le contexte des tableaux :

@tableau = ('a', 'b', 'c');
$element = @tableau[1]; # Ici $element vaut 'b'
@extrait = @tableau[1]; # Ici @extrait vaut ('b'), un tableau de 1 élément


Suivant ce qui se trouve à gauche du symbole = (un scalaire ou un tableau), Perl 6 va comprendre que vous attendez de récupérer un élément scalaire du tableau ou un extrait du tableau (un autre tableau ne contenant qu'une partie des éléments initiaux). Naturellement, les contextes permettent de faire bien d'autres choses et nous les reverrons dans la suite.

Des objets partout

Les principaux concurrents de Perl se sont tous progressivement dotés d'un système de programmation orientée objet, avec plus ou moins de réussite. Même si Perl permettait déjà d'utiliser des objets dans sa version 5, ainsi que d'importer des modules proposant un nouveau système (comme Moose), les valeurs de base du langage n'en profitaient pas.

Perl 6 apporte donc des méthodes à toutes les valeurs. Par exemple, les tableaux ont une méthode elem qui renvoie le nombre d'éléments qu'ils contiennent, une méthode end qui renvoie le plus grand indice du tableau (pour en désigner la fin), une méthode pick pour prendre un ou plusieurs éléments au hasard,… Pour la plupart des objets, les anciennes fonctions (appelées sous-routines en Perl) restent disponibles, mais ont également été ajoutées aux objets qu'elles concernaient. Par exemple, pour trier un tableau, on utilisera indifféremment @tableau.sort ou sort @tableau.

À ce propos, on utilise désormais le point et non plus la flèche, pour appeler une méthode ou désigner un attribut.

Typage statique ou dynamique

Perl 6 rompt avec les versions précédentes de Perl en proposant un panel assez vaste de fonctionnalités destinées à vérifier les types d'un programme. Comme avant, les variables peuvent être dynamiquement typées, ce qui veut dire que leur type n'est connu qu'à l'exécution. Mais il est également possible de préciser des types pour ces variables, ce qui permet aussi bien de détecter des erreurs à la compilation que d'effectuer des optimisations, quand c'est possible.

En tout cas, une contrainte de type non-respectée à l'exécution provoquera une erreur. Il est par exemple interdit de faire

my Int $x = 3; # Déclaration de $x comme entier
$x = "foo";


Les types « normaux » (ne jouant pas de rôle particulier) héritent du type Any, qui lui-même hérite du type Mu (parent de tout autre type). Des types génériques sont possibles, par exemple :

my Int @a = 1, 2, 3; # déclare le tableau @a comme étant de type Array of Int.

On peut connaître le type d'une variable à l'aide de sa méthode WHAT et tester la capacité d'une variable à être convertie en un autre type à l'aide de l'opérateur ~~ :

if $x ~~ Int {
say 'Variable $x contains an integer';
}


Il est possible de définir des contraintes plus fortes sur des sous-ensembles de certains types, par exemple un ensemble de nombres pairs :

subset Pairs of Int where -> $n { $n % 2 == 0 }
my Pairs $n = 2;
say $n++; # Erreur : $n va recevoir 3, qui ne vérifie pas la contrainte


Les Synopses de Perl 6 autorisent un compilateur à remarquer aussi tôt que possible des éventuelles erreurs de types (avant l'exécution de l'instruction fautive). Cependant, l'exemple suivant montre que certaines contraintes de types seront de toute façon dynamiques :

my enum Day ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
subset Weekday of Day where 'Mon' .. 'Fri'; # contrainte statique
subset Today of Day where *.today; # contrainte dynamique


La synopsis 12 traite plus en détail des questions de dynamisme.

Structures de contrôle et blocs

Les structures de contrôle de Perl 6 ressemblent à celles de Perl 5, mais suivent la tendance de plusieurs langages (Python, Go) à se débarrasser des parenthèses autrefois nécessaires. Par exemple, il est possible d'écrire if $nombre < 42 { ... }. Comme en Perl 5, les modificateurs placés après des instructions sont toujours autorisés : say "Perdu !" if $answer != 42;.

La boucle for ne sert désormais qu'à parcourir des listes (comme foreach autrefois) ; la version de for du langage C s'appelle désormais loop. Pour parcourir une liste, for attend un bloc contenant les instructions à exécuter sur chaque élément. Par exemple, pour afficher les entiers de 1 à 10 :

for 1..10 -> $x {
say $x;
}


ou pour lire les lignes d'un fichier "text.txt" :

for lines "text.txt" -> $line {
say $line.chars;
}


Les blocs correspondent à des morceaux de code pouvant prendre des arguments et être manipulés, comme les fonctions anonymes que l'on trouve dans d'autres langages. Ils peuvent prendre un nombre variable d'arguments : dans ce cas, le comportement de la boucle for est modifié. Par exemple :

my @tableau =

for @tableau -> $nom, $age {
say "$nom a $age ans."
}


La synopsis 4 traite des structures de contrôle et des blocs.

Sous-routines (ou fonctions)

La définition de fonctions a été grandement revue dans Perl 6. Il est possible de préciser une liste formelle d'arguments, éventuellement accompagnés de types, de valeurs par défaut ou d'indications sur leur mutabilité. Par exemple :

sub ma_sub (Int $a is rw, $b = 3 is copy) { ... }

définit une sous-routine ma_sub prenant un paramètre $a pouvant être modifié (il est passé en mode read-write, soit lecture et écriture) et un paramètre $b dont on est sûr qu'il ne sera pas modifié puisqu'il est copié (cependant la copie peut être modifiée à l'intérieur de la sous-routine). De plus, $b est optionnel, sa valeur par défaut est 3.

Les arguments peuvent être nommés, en les préfixant par « : » dans la liste des arguments. Lors de l'appel de la fonction, on écrit alors argument => valeur. Certaines fonctions utilisent ces arguments nommés comme des options : par exemple, la méthode pick des tableaux permet de choisir un élément au hasard dans le tableau lequel sera enlevé. Mais l'argument optionnel nommé replace permet de préciser à pick qu'on souhaite replacer l'élément pioché dans le tableau. On écrit alors :

@tableau.pick(4, replace => True) # ou, plus simplement :
@tableau.pick(4, :replace) # ce qui est équivalent (mais plus court).


Par exemple, on peut simuler le lancement de 4 dés en écrivant : (1..6).pick(4, :replace).

L'ancien tableau d'arguments @_ de Perl 5 reste cependant accessible si aucune liste formelle d'arguments n'est spécifiée. Consultez la synopsis 6 sur les sous-routines pour plus d'informations.

Un nouveau système d'objets

La programmation objet en Perl a été entièrement repensée. Un certain nombre de nouveaux mot-clefs ont été introduits, permettant de définir des classes de la même manière que dans la plupart des langages de programmation : ici, une classe Rectangle qui hérite d'une classe Shape, avec deux attributs mutables et une méthode :

class Rectangle is Shape {
has $.width is rw;
has $.height is rw;

method area {
$!width * $!height;
}
}


Les twigils (sur lesquels nous reviendrons) permettent, comme les sigils en Ruby, de préciser l'accessibilité d'un attribut : on notera $.attribut pour un attribut public et $!attribut s'il est privé.

Perl 6 offre un autre mécanisme de programmation orientée objet qui ressemble aux classes, mais sans l'idée de hiérarchisation des classes : les rôles. Ils s'utilisent avec le mot-clef does. Par exemple, une classe Chien héritera probablement d'une classe Mammifère, de même qu'une classe Loup. Mais on pourra également définir un rôle AnimalDomestique supporté par tous les chiens et éventuellement quelques oiseaux, mais pas par les loups : il est clair que ce rôle ne rentre alors pas dans la hiérarchie précédente. De plus, Perl 6 permet de faire jouer un rôle à un objet particulier plutôt qu'à toute sa classe (on pourrait donc avoir des loups domestiques).

Les rôles sont donc un moyen de décrire ce que les objets font et pas ce qu'ils sont. Par exemple, des objets peuvent supporter les rôles Callable ou Positional pour jouer respectivement le rôle de blocs (pouvant être appelés, i.e. exécutés) ou de tableaux (on pourra alors leur adjoindre le sigil @). Cette fonctionnalité est donc à opposer à des approches comme celle des interfaces ou des ABC où rôles et héritage sont liés. Elle est également présentée comme plus fiable que le duck typing.

La synopsis 14 traite de la façon dont Perl 6 utilisera les rôles.

Les règles, les expressions régulières (« regexps ») et l'analyse syntaxiques

Perl est connu pour ses expressions rationnelles (les « regexps »), qui sont en réalité beaucoup plus puissantes que le modèle théorique dont elles sont inspirées. Perl 6 généralise encore cet outil afin de le rendre plus adapté pour l'analyse syntaxique (rappelons que Perl doit être utilisé par Parrot pour écrire des compilateurs).

Il est donc possible de décrire des grammaires complètes de façon beaucoup plus lisibles qu'avec de simples regexps. Voici un exemple servant à analyser des URL, pour récupérer par exemple leur nom d'hôte :

grammar URL {
token TOP {
'://'
[ | ]
[ ':' ]?
'/' ?
}
token byte {
(\d**{1..3}) <?{ $0 < 256 }>
}
token ip {
[\. ] ** 3
}
token schema {
\w+
}
token hostname {
(\w+) ( \. \w+ )*
}
token port {
\d+
}
token path {
<[ a..z A..Z 0..9 -_.!~*'():@&=+$,/ ]>+ <br/> } <br/> } <br/> <br/> my $match = URL.parse('http://perl6.org/documentation/');
say $match # affichera "perl6.org"


Outre une plus grande lisibilité, les grammaires peuvent être composées. Par exemple, pour se limiter aux URL du protocole HTTP, on peut dériver la grammaire précédente ainsi :

grammar URL::HTTP is URL {
token schema { 'http' }
}


Cependant, il est toujours possible d'utiliser des regexps avec une syntaxe proche de celle de Perl 5, pour faire des substitutions ou des recherches dans une chaîne de caractères :

my $x = 'Abcd';
$x ~~ s:ii/^../foo/; # substitution qui conserve la casse
say $x; # affiche Foocd


Les jonctions

Perl 6 introduit un nouveau type d'objets représentant des calculs effectués de façon parallèle : les jonctions. Par exemple, on exprime l'objet « 1 ou 2 » par 1|2. Il devient alors possible d'écrire if $a == 1|2. De plus, ces objets supportent les opérations usuelles qui sont alors distribuées sur tous leurs éléments : (1|2) + 1 == (2|3).

Trois opérateurs servent pour les jonctions : |, & et ^ qui désignent respectivement la disjonction, la conjonction et l'unicité. Ils correspondent en fait à trois fonctions prédéfinies : any, all et one. Une fonction none est également définie qui fait le contraire de all. Le but initial était de rester proche (une fois de plus) du langage naturel : on dit souvent « si x est égal à ceci ou cela ». Cependant, il est clair que les jonctions peuvent trouver d'autres applications : il n'est pas exclu de les utiliser pour le calcul parallèle et il est de plus possible d'écrire, si @items est un tableau d'entiers :

if all(@items) >= 0 { # Ou none(@items) < 0
say "Tous positifs !"
}


La paresse

Une des caractéristiques de Perl 6 empruntées à Haskell lors du développement de Pugs est certainement l'évaluation paresseuse : en Haskell, tous les calculs d'un programme sont laissés en suspens jusqu'au moment où ils sont vraiment nécessaires. Cela permet par exemple de travailler avec des listes infinies : tant qu'on n'essaye pas, par exemple, d'en mesurer la longueur, seul un nombre fini de valeurs est calculé.

En Perl, on se retrouve très vite confronté à l'évaluation paresseuse des listes quand on veut par exemple afficher les lignes d'un fichier en les numérotant : d'après ce qui précède, on serait tenté d'utiliser une boucle for et un bloc pointé, mais jusqu'à combien faudrait-il compter ? Impossible de prévoir. On écrit donc que l'on compte jusqu'à l'infini, en réalité seules les valeurs utiles seront calculées :

my $file = open '/etc/passwd', :r;
for $file.lines Z 1..Inf -> $text, $n {
say "$n : $line";
}


L'opérateur Z sert à fusionner deux listes en une seule. C'est un raccourci pour « zip » (une fonction qui existe également en Haskell, en OCaml ou en Python), qui regroupe deux listes en une seule - comme une fermeture éclair.

Il est également possible de construire une liste paresseuse à l'aide des mot-clefs gather et take, proches du concept de générateurs en Python. Le premier sert à délimiter un bloc qui sera exécuté à chaque fois que l'on aura besoin d'une nouvelle valeur pour la liste. Le second sert précisément à générer ces valeurs. Il est alors possible d'affecter le résultat à une liste, ce qui construira paresseusement la liste (il faut toutefois utiliser := plutôt que =, ce dernier évaluant toute la liste).

La synopsis 9 traite des structures de données de Perl 6.

Les multiples opérateurs de Perl 6

Perl est célèbre pour son impressionnante quantité d'opérateurs. Avec Perl 6, c'est pire, à tel point qu'une classification périodique des opérateurs a été établie ! Jouant un rôle comparable à celui des fonctions d'ordre supérieur, les meta-opérateurs de Perl 6 permettent de réutiliser d'autres opérateurs en les appliquant sur des ensembles de données.

Par exemple, l'opérateur de réduction (noté [ ]) applique successivement une opération à toute une liste. Cela peut par exemple servir à additionner tous les éléments d'une liste : il suffit d'écrire [+] (1, 6, 3, 2) pour calculer 1 + 6 + 3 + 2. De même, il est parfaitement naturel d'écrire if [<=] @tableau pour vérifier que tous les éléments de @tableau sont rangés dans l'ordre croissant. Il est également possible de générer tous les résultats intermédiaires dans une liste, en notant [\ ] plutôt que [ ] : ainsi, [\*] 1..10 générera la liste des factorielles de 1 à 10. <br/> <br/> Plusieurs opérateurs servent à combiner les listes entre elles. C'est le cas de Z, qui « zippe » deux listes (éventuellement à l'aide d'un autre opérateur, par exemple (1, 2) Z+ (3, 4) donne (4, 6)), de X, qui distribue une liste sur l'autre, ou encore des <a href="http://perlcabal.org/syn/S03.html#Hyper_operators">hyper-opérateurs</a> « et » (qui peuvent également être écrits << et >>). Ceux-ci servent à distribuer une opération sur tous les éléments d'une liste - ou, en réalité, d'une structure de données jouant le rôle d'un Iterator. Par exemple, -<< (1,2,3) produit la liste (-1, -2, -3). De plus, (1,1,2,3,5) »+« (1,2,3,5,8) produit (2,3,5,8,13), les éléments étant combinés. Les hyper-opérateurs suivent en réalité des règles complexes, qui semblent pour l'instant être mal supportées par Rakudo.

Enfin, il est possible de définir ses propres opérateurs. Par exemple, on peut définir la factorielle par :
sub postfix:<!>($arg) {
if ($arg == 0) {
1;
}
else {
($arg-1)! * $arg; # Définition récursive !
}
}


ou, avec ce qui précède, sub postfix:<!>($arg) { [*] 1..$arg }. Il est possible de gérer finement l'ordre de priorité de chaque opérateur, par rapport à d'autres opérateurs (grâce à des mot-clefs comme is tighter, equiv ou looser), ainsi que de préciser quel type d'opérateur on définit (infixe, postfixe, préfixe, ainsi que circumfix (autour des données) et postcircumfix (comme les crochets d'un dictionnaire)).

Les twigils : des indications de portée

Ruby, en héritant de Perl, a changé quelques caractéristiques, en changeant par exemple le rôle des sigils. Alors qu'en Perl 5 ils indiquent la nature d'une variable, en Ruby ils indiquent sa portée : est-ce une variable globale, locale, l'attribut d'un objet… Perl 6 reprend cette idée, mais sans pour autant supprimer l'idée première des sigils. La solution ? Ajouter un deuxième sigil, placé après le premier - ce que l'on appelle un twigil.

Par exemple, $*foo dénote une variable globale ; $.foo et $!foo, respectivement des attributs publics et privés d'une classe ; $^foo est un paramètre auto-déclaré dans un bloc. Concernant ce dernier, Perl 6 corrige en effet une inélégance de Perl 5, qui consistait à réserver, dans les blocs, certains noms de variables pour leur faire jouer des rôles spéciaux. Ainsi on écrivait sort { $a <=> $b } @array pour trier un tableau. En Perl 6, le twigil ^ permet de déclarer ce genre de paramètre sans rôle spécial : il est équivalent d'écrire sort { $^a <=> $^b } @array.

Quand le bloc prend plusieurs arguments, ceux-ci sont affectés aux paramètres auto-déclarés… par ordre alphabétique. Par exemple :

my @tableau =

for @tableau { # Rappelez-vous, ici on utilisait -> $x, $y
say "$^alpha a $^bravo ans."
}


Enfin, les variables traitées à la compilation telles que __LINE__ ou __FILE__ sont remplacées par $?LINE et $?FILE - avec le twigil ?.

L’astérisque * et les blocs

Les programmeurs Perl chevronnés considèrent comme un sport l'écriture de codes les plus courts possible qui font appel aux nombreux outils du langage. Afin de donner de l'expressivité aux développeurs, Perl 6 définit un objet particulier, *, qui est en fait le seul objet de type Whatever. C'est une valeur spéciale que les développeurs peuvent utiliser comme raccourci pour dire « autant que nécessaire » ou « quoi que ce soit ». Par exemple, @cartes.pick(*) mélange le tableau cartes, car .pick prélève les cartes une par une au hasard jusqu'à ce que le tableau soit vide et renvoie le tout. De même, on peut par exemple compter jusqu'à l'infini en écrivant 1 ... * ou générer la liste des puissances de deux avec 1, 2, 4 ... *. Dans un switch, * joue également le rôle de joker.

Mais l'astérisque peut également servir à construire des blocs de code qui, vous l'aurez compris, jouent un rôle clef dans les programmes Perl 6. Ainsi, écrire par exemple * + * génère le bloc $x, $y -> {$x + $y}. Cela donne donc une grande expressivité à Perl 6 : par exemple, si on sait que la méthode .chop supprime le dernier caractère d'une chaîne, on ne s'étonnera pas que 'Camelia', *.chop ... ''; génère la liste de tous les préfixes du mot « Camelia ». De même, si une classe Etudiants est définie par :

class Etudiant {
has Str $.nom;
has Int $.annee is rw;
}


on appréciera de pouvoir écrire @students.sort: *.nom; pour trier les étudiants par nom.

Rakudo Star

C'est donc aujourd'hui que la première version publique du compilateur Rakudo est publiée, sous le nom de « Rakudo * ». Selon Patrick Michaud, chef du projet, c'est un clin d'œil à l'objet * de Perl 6 : Rakudo n'est pas encore tout à fait mature, mais il a assez traîné et ses développeurs le publient « quoi qu'il en soit ». Michaud déplore la lenteur et les quelques bugs qui peuvent encore être rencontrés, mais le développement de Rakudo est actif et la diffusion de Perl 6 ne pourra qu'attirer des programmeurs et multiplier les rapports de bug.

De plus, Rakudo respecte déjà une très grande partie des spécifications de Perl 6, dont celles qui ont été présentées dans la partie précédente. Rakudo Star est en réalité une distribution contenant la version #31 de Rakudo, ainsi que la machine virtuelle Parrot nécessaire pour exécuter du code.

Un certain nombre de modules sont également livrés, qui permettent par exemple de faire tourner un petit serveur web, d'appeler des bibliothèques C ou Perl 5 ou, encore, d'interagir avec des bases de données. Ce sont essentiellement des modules de test qui pourraient être remplacés par des modules plus standards à l'avenir.

Rakudo Star peut être téléchargé depuis github. Si vous utilisez une distribution GNU/Linux, il est probable que des paquets soient disponibles. Un binaire Windows devrait également être disponible sur le site officiel. Si vous ne souhaitez pas installer Rakudo pour tester Perl 6, il est également possible d'aller parler en privé au robot p6eval sur le réseau irc.freenode.net, en préfixant votre commande par rakudo: pour préciser l'interpréteur. Par exemple :

[23:07] poulet: rakudo: say ([\*] 1..10).perl
[23:07] p6eval: rakudo fe29cd: OUTPUT«(1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800)»
  • # Ça donne presque envie d'essayer !

    Posté par . Évalué à  10 .

    Malheureusement je ne me ferai jamais à Perl. Ça me semble intéressant sur le principe d'avoir un langage de programmation « naturel » à l'utilisation, mais en même temps ça multiplie les manières de faire les choses (TIMTOWTDI) et du coup ça rend les programmes plus compliquées à relire ou à comprendre.

    En même temps, je suis Pythonneux convaincu, donc mon point de vue est loin d'être objectif.

    Très bonne dépêche, sinon. C'est bien détaillé, bien sourcé, c'est bête que les codes sources ne soient pas en monospace car ça rend le tout un peu moins lisible.
    • [^] # Re: Ça donne presque envie d'essayer !

      Posté par (page perso) . Évalué à  3 .

      Les codes sources sont en monospace, en dehors de deux boucles for (va savoir pourquoi).
      • [^] # Re: Ça donne presque envie d'essayer !

        Posté par . Évalué à  2 .

        Oh. Il faut croire que nightgrey n'est plus à jour :'( . Merci de me l'avoir fait remarquer.
        • [^] # Re: Ça donne presque envie d'essayer !

          Posté par . Évalué à  2 .

          Je viens de vérifier et tout le code est effectivement à chasse variable.

          C'est ma faute : J'ai spécifié des fontes par défaut à « * » en début de C.S.S. et j'ai redéfini les balises <code> au cas par cas après. Je n'étais pas au point à 100 % quand je l'ai écrite.

          Je tâcherai de corriger ça vite fait. Par contre, ça marche bien avec Springtime.
    • [^] # Re: Ça donne presque envie d'essayer !

      Posté par . Évalué à  2 .

      Pour moi sera pour le jour où il existera des bindings pour des bibliothèques GUI (disponibles pour linux et OS proprio connu).

      D'après le lien suivant il n'y a encore rien (mais ça date de mars) http://www.perlmonks.org/index.pl?node_id=831973
    • [^] # Re: Ça donne presque envie d'essayer !

      Posté par (page perso) . Évalué à  2 .

      Randall Schwartz a dit un jour « il y a plus d'une manière de faire les choses, mais toutes ne sont pas bonnes ». Bref, il ne faut pas surexagérer le TIMTOWTDI, pouvoir faire les choses de plusieurs manières ne veut pas dire les faire n'importe comment :). En fait pour essayer, les livres de Randall Schwartz et Cie (Learning Perl, Intermediate Perl) sont franchement à lire, ils figurent parmi les meilleurs bouquins de prog que j'ai pu lire.

      J'aime beaucoup Python (je dis ça sérieusement, je le trouve très chouette et l'utilise), mais je bloque réguilèrement sur le TIOWTDIFEV (there is one way to do it for each version). Pour l'instant je m'en tiens à Python 2.6 en regardant doucement venir. En passant de Perl 5.8 à Perl 5.10, j'ai rien eu à changer, en passant à Perl 5.12, je pense que j'aurais rien à changer non plus. Et tous mes scripts Perl5 sont compatibles avec Perl6. Franchement, c'est l'un des trucs que j'aime beaucoup chez Perl : pas de table rase. Sur la plupart des système que j'utilise, il y a un Perl, et deux, trois voire plus Python.

      Bon ok, avec Perl6 il y aura peut-être un temps de battement avec deux Perl :).
      • [^] # Re: Ça donne presque envie d'essayer !

        Posté par . Évalué à  2 .

        Bref, il ne faut pas surexagérer le TIMTOWTDI […] mais je bloque réguilèrement sur le TIOWTDIFEV

        Quelque chose de très innovant dans tout cela, c'est qu'il faut apprendre la définition de ces sigles comme moyen mnémotechnique pour savoir comment les écrire. :-)
  • # ++

    Posté par . Évalué à  8 .

    Merci beaucoup pour cette très très bonne dépêche.
  • # Rooohhh !!!

    Posté par (page perso) . Évalué à  1 .

    ou via les newsgroups Usenet, qui sont un peu l'ancêtre des forums web

    P'taing, mais c'est quoi cet amalgame àlc ?

    Ahhh, oké, d'accord, j'ai compris...

    ÇAI UN TROLL phpbb !.

    * Ils vendront Usenet quand on aura fini de le remplir.

    • [^] # Re: Rooohhh !!!

      Posté par . Évalué à  3 .

      Hum.

      Certaines remarques (ou simplifications) dans l'article viennent du faire que ma dépêche était initialement prévue pour un autre site. Notamment, je pensais avoir supprimé celle-là. Désolé !
      • [^] # Re: Rooohhh !!!

        Posté par . Évalué à  2 .

        Comment, les gens ne connaissent pas les netnews sur le Site du Zéro ? ;-)
  • # quels chameaux ces dromadaires

    Posté par . Évalué à  6 .

    > le chameau étant l'animal emblématique de Perl

    perdu, il a qu'une bosse.
    • [^] # Re: quels chameaux ces dromadaires

      Posté par . Évalué à  2 .

      > perdu, il a qu'une bosse.

      Pas perdu, un dromadaire est juste un chameau un peu particulier.
      Il fut un temps où l'on ne disait pas "dromadaire", mais "chameau dromadaire" (Cf Littré http://francois.gannaz.free.fr/Littre/xmlittre.php?requete=chameau ).
  • # questions philosophiques...

    Posté par . Évalué à  3 .

    pour moi Perl5 est un langage incroyable car il simplifie vraiment les étapes d'écriture d'un programme : type dynamique, ecriture consise et clair, gestion puissante des tableau et hash.
    Pour moi la notion la plus puissante qui a permis a Perl de se distinguer est la notion de contexte. C'est toujours un peu déroutant au début, mais une fois compris, on écrit et on lit naturelement des lignes de code très courtes et qui veulent tout dire!

    Le bémol de tout ça est que c'est un langage offrant beaucoup de liberté et que cela donne un peu libre cours au style du programmeur. C'est pourquoi je pense que son utilisation de prédilection reste le scripting d'administration et pas le programmes "lourds" qui nécéssite une langage plus structuré.

    Par contre je ne m'explique toujours pas le succès du PHP face au perl... Enfin si... je pense que la disponibilté du mod_php a permis d'ouvrir les premiers hébergeurs tout public aux pages dynamique tout en permettant un meilleur controle. C'est en tout cas pour moi un gachi car perl n'a pas eut la reconnaissance qu'il méritait, malgré une puissance et une précision largement meilleure.


    Sur Perl6, je reste un peu dubitatif, malgré mon amour du Perl5. Qu'en pense les perlistes convaincus? Mais je dois reconnaitre qu'il y a quand meme des choses interressantes. Mais trop de syntaxe a mon avis et je deteste apprendre par coeur...

    --
    Send with a small keybord
  • # $_ ~~ /@!_/;

    Posté par (page perso) . Évalué à  3 .

    Ave,

    > Le but de cette approche (à distinguer de celle d'AppleScript) était de permettre d'écrire un code assez naturel.

    Pour le coups, l'utilisation abusive de caractère non alphabétique a complètement flingué cet objectif. À moins de ne faire que du Perl, on passe son temps à traduire la ponctuation en recherchant dans la doc. Sur ce point, Python a vraiment réussit : quasiment aucune ponctuation. C'est très lisible. On croirait écrire du pseudo code.

    Effectivement, dans nos langue naturelle, « il y a plusieurs manière de le dire ». Mais àmha, en programmation, on cherche l'expression universelle, optimale d'un algorithme. Renoncer à ça confinera toujours Perl à du scriptage.

    Parcontre, j'ai hâte de faire mumuse avec Python et Perl 6 sur Parrot. Malheureusement, http://pirate.tangentcode.com/ semble moribond .

    Donc, longue vie à Perl, mais sans moi :)

    Étienne
  • # Templeet a bouffé la moitié de la grammaire.

    Posté par . Évalué à  2 .

    Tout ce qui était entre <> s'est fait virer, en fait.
    Comme, en majorité ici, les <> contiennent les différents tokens qui sont définis, le token TOP perd tout son sens (ça illustre assez mal le fait que c'est plus clair que les regex de Perl 5, du coup !).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.