Perl, les bases du langage

Sébastien Aperghis-Tramoni, sebastien@aperghis.net

Perl

  • Practical Extraction and Report Language

  • langage interprété et dynamique

  • libre : GNU GPL et Artistic License

  • créé en 1987 par Larry Wall

Caractéristiques

  • à l'origine, langage de glue

  • intermédiaire entre le shell, awk, sed d'un côté et C de l'autre

  • ajouts de langages fonctionnels comme Lisp

  • maintenant, langage dynamique généraliste

  • extrêmement portable

  • très stable

Slogan

  • TIMTOWTDI

    • There is more than one way to do it

  • les trois vertus du programmeur :

    • paresse

    • impatience

    • orgueil

Points forts

  • multi-paradigmes : impératif, fonctionnel, orienté objet

  • types de base : scalaire (chaîne, nombre), tableau, hash

  • gestion de mémoire par ramasse-miettes

  • expressions régulières

  • OO : multi-héritage, surcharge d'opérateur, fermetures

  • Unicode

Points faibles

  • (faiblement typé)

  • très (trop) permissif

  • paradigme objet très (trop) simple

  • ramasse-miettes par comptage de références

  • syntaxe devenue lourde pour certaines opérations

Hello

  •     print "Hello, world\n";

Types

  • scalaire (entier) : $number = 42;

  • scalaire (flottant) : $number = 3.14152;

  • scalaire (chaîne) : $string = "whatever";

  • tableau, liste : @array = ( 1, 2, 3, 4, 5 );

  • hash : %hash = ( "foo" => bar, "quux" => "krack" );

Contextes

  • vide

  • scalaire (scalar)

  • scalaire chaîne

  • scalaire numérique

  • liste

Contextes

  • Exemples :

  •     # contexte scalaire
        $n = @array;
  •     print scalar @array;
  •     # renvoie la liste des lignes d'une base de données
        @rows = $dbh->fetch_rows();
    
        # renvoie le nombre de lignes
        $n = $dbh->fetch_rows();

Variables

  • de base, déclaration non obligatoire

  • en mode strict, déclaration obligatoire

  • use strict;

  • déclaration avec my

  • portée similaire à celle de C

  •     my $x = 123;
        my $y = "foo";
    
        {
            my $x = 456;
            my $z = "bar";
            # $y est visible
        }
    
        # $z non visible
        print $x;   # "123"

Scalaires

  •     $var = "du texte au hasard";
        print "var=$var\n";     # "var=du texte au hasard"
    
        $var = 42;
        print "var=$var\n";     # "var=42"

Scalaires - Chaînes

  • délimiteurs de chaînes comme en shell

  • doubles quotes (")

    • interprétation des séquences \n, \t..

    • caractères en octal (\015), hexadécimal (\x7f, \x{263a}), par nom Unicode (\N{ARABIC LETTER ALEF})

    • interpolation des scalaires : "${prefix}word$suffix"

    • interpolation des tableaux : "args: @args"

    • caractères protégés (\$, \@, \", \\)

  • simples quotes (')

    • pas d'interprétation hormis \' et \\

Scalaires - Booléens

  • n'existent pas

  • valeur de vérité vraie : tout ce qui n'est pas faux

  • valeur de vérité fausse : 0, "0", "", undef

undef

  • valeur non définie

  • valeur par défaut des variables non initialisées

  • test avec defined()

  •     if (defined($var)) {
            ...
        }

Opérateurs, fonctions

  • comme en C, Java..

  • concaténation de chaînes : "foo" . "bar"

  • aspect particulier : Perl DWIM

  • transformation automatique

  • chaîne => nombre en contexte numérique

  • nombre => chaîne en contexte de chaîne

  • opérateurs spécifiques pour les chaînes

  • gt, lt, ge, le, eq, ne, cmp

  • < , >, <=, >=, ==, != <=>

Opérateurs, fonctions

  • Exemples :

  •     $v = "30" + "12";   # $v = 42
  •     $v = 30 . 12;       # $v = "3012"
  •     $n = length 42;     # $n = 2
  •     7 lt 13             # faux
  •     "foo" gt "bar"      # vrai
  •     "bar" cmp "foo"     # -1
  • auto-incrément magique

  •     $v = "foo";
        $v++;
        print $v;   # "fop"

Tableaux

  •     @array = ( 1, 2, 3, 4, 5 );
        @array = ( "abc", "def", "ghi" );
  • TIMTOWTDI :

  •     @array = ( 1 .. 5 );
        @array = ( "a" .. "z" );
  •     @array = qw( abc def ghi );
  •     @array = ( 1..5, "foo", "bar", 3.1415 );

Sigils

  • caractère qui précède le nom de la variable

  • type de la/des donnée(s) à récupérer

  • $ : scalaire

  • @ : tableau, liste

  • % : hash

Tableaux

  • valeurs et tranches :

  •     @array  = ( 1 .. 5 );
    
        $var    = $array[2];        # 3
        @values = @array[1, 3];     # (2, 4)

Tableaux

  • push, pop, shift, unshift, delete :

  •     @array = ( 1 .. 5 );
  •     push @array, 6, 7;          # (1, 2, 3, 4, 5, 6, 7)
        $var = pop @array;          # (1, 2, 3, 4, 5, 6)
  •     $var = shift @array;        # (2, 3, 4, 5, 6)
        unshift @array, 0;          # (0, 2, 3, 4, 5, 6)
  •     $var = delete $array[3];    # (0, 2, 3, 5, 6)

Tableaux

  • splice(ARRAY, OFFSET, LENGTH, LIST)

  •     @array = ( 1 .. 5);
  •     splice @array, 2, 2, "oh hai";
        # ( 1, 2, "oh hai", 5)
  •     splice @array, 2;
        # ( 1, 2 )
  •     splice @array;
        # ( )

Listes

  • sort :

  •     @array = ( 4, 8, 5, 3, 0, 2 );
    
        @array = sort @array;       # (0, 2, 3, 4, 5, 8)
    
        @array = sort { $b <=> $a } @array;
  • reverse :

  •     @array = ( 1 .. 5 );
    
        @array = reverse @array;    # (5, 4, 3, 2, 1)

Hashes (tableaux associatifs)

  •     %hash = (
            perl    => "Practical Extraction and Report Language",
            sfid    => "Software Freedom International Days",
            42      => "la réponse",
            foo     => "bar",
            "Yoko Kanno" => "musicienne japonaise",
        );
  • valeurs et tranches :

  •     $var = $hash{perl};
        $var = $hash{"perl"};
    
        $var = $hash{"Yoko Kanno"};
    
        @values = @hash{42, "foo"}; # ("la réponse", "bar")

Hashes (tableaux associatifs)

  • opérateurs keys, values, delete :

  •     @keys = keys %hash;     # ( 42, "sfid", "foo", "Yoko Kanno" )
    
        @values = values %hash;
    
        delete $hash{42};

Références

  • référence de tableaux et hashes existants :

  •     $arrayref = \@array;
        $hashref  = \%hash;
  • tableaux et hashes anonymes :

  •     my $arrayref = [ 1 .. 5 ];
        print $arrayref->[2];       # 3
  •     my $hashref = { foo => "bar" };
        print $hashref->{foo};      # "bar"

Structures

  •     %machine = (
            profane => {
                hostname  => "profane.mongueurs.net",
                addresses => [
                    { type => "ipv4", addr => "81.80.147.194" },
                ],
                status    => "up",
                services  => [ "http", "svn", "smtp" ],
            },
            sferics => {
                hostname  => "sferics.mongueurs.net",
                addresses => [
                    { type => "ipv4", addr => "81.80.147.197" },
                ],
                status    => "down",
                services  => [ "http", "cvs", "smtp" ],
            },
        );
  •     print $machine{profane}{addresses}[0]{addr};    # "81.80.147.194"

Contrôle de flux

  •     if (CONDITION1) {
            ...
        }
        elsif (CONDITION2) {
            ...
        }
        else {
            ...
        }
  •     INSTRUCTION if CONDITION;
  •     print $var if defined $var;
  •     INSTRUCTION unless CONDITION;

Contrôle de flux

  •     while (CONDITION) {
            ...
        }
  •     INSTRUCTION while CONDITION;

Contrôle de flux

  •     while (defined ($line = <$in>)) {
            next if $line =~ /^\s*$/ or $line =~ /^#/;
            last if $line =~ /^__END__$/;
    
            chomp $line;
    
            if ($line =~ /\\$/) {
                $line .= <$in>;
                redo;
            }
            
            # process $line
            # ...
        }
  •     continue {
            # do a bit more with $line
        }

Contrôle de flux

  •     for (INIT; CONDITION; INCREMENT) {
            ...
        }
  •     for (my $i=0; $i<50; $i++) {
            ...
        }

Contrôle de flux

  •     for VARIABLE (LIST) {
            ...
        }
  •     for my $i (1..5) {
            ...
        }

smart match

  • opérateur ~~

  • switch on steroids

  • permet de comparer magiquement tout type de données

  • cf. perlsyn

given .. when

  • basé sur le smart match

  •     given ($var) {
            when (undef)  { say '$var non défini' }
            when (@array) { say '$var est dans @array' }
            when (%hash)  { say '$var est une clé de %hash' }
            when (\&code) { say 'code($var) est vrai' }
            when (qr/../) { say '$var correspond à la regexp' }
            default       { ... }
        }

Fonctions

  • déclarées avec sub

  • arguments passés sous forme de liste

  • accessibles par @_

Fonctions

  •     sub fib {
            my ($n) = @_;
            return 1 if $n == 1 or $n == 2;
            return fib($n-1) + fib($n-2);
        }
  •     print fib(7);       # 13

Fermetures

  •     {
            my $seq = 42;
            sub next_seq { return ++$seq }
        }
    
        print next_seq() for 1..3;      # "43 44 45"

Fermetures

  •     sub curry_mult {
            my $num = shift;
            return sub { return $_[0] * $num }
        }
    
        *times_two   = curry_mult(2);
        *times_three = curry_mult(3);
    
        print times_two(5);     # 10
        print times_two(7);     # 14
        print times_three(5);   # 15
        print times_three(7);   # 21

Objets

  • fondamentalement, une référence "consacrée" (bless) dans un espace de noms (classe)

  • Class->method()

  • $objet->method()

Objets

  •     package Tree;
    
        sub new {
            my ($class, %args) = @_;
            my $self = bless {}, $class;
            # init $self using %args
            return $self
        }
    
        sub add_node {
            # ..
        }
  •     use Tree;
    
        my $tree = Tree->new;
    
        $tree->add_node(...);
        $tree->add_node(...);
    
        print $tree->render(as => "text");

Lecture

Lecture

  • Perl moderne

  • expressions régulières actuelles

  • objet moderne avec Moose

  • bases de données avec DBI

  • programmation événementielle avec POE

  • navigation sur le web avec LWP et WWW::Mechanize

  • http://perlmoderne.fr/