[gull] Faut-il réhabiliter Perl comme langage de scripting système?

Marc SCHAEFER schaefer at alphanet.ch
Fri Mar 9 10:04:18 CET 2018


Hello,

Perl laisse le choix, par exemple le code suivant:

   $ cat a.pl 
   #! /usr/bin/perl
   
   my $data = "toto";
   
   print $date, "\n";

   $ ./a.pl 

avec les warnings:

$ perl -w a.pl 
Name "main::date" used only once: possible typo at a.pl line 5.
Use of uninitialized value $date in print at a.pl line 5.

avec use strict: 
   $ ./a.pl 
   Global symbol "$date" requires explicit package name at ./a.pl line 7.
   Execution of ./a.pl aborted due to compilation errors.

On Thu, Mar 08, 2018 at 12:25:36PM +0100, Laurent Franceschetti wrote:
> raison valable de se compliquer la vie.

man perl

       Using the "use strict" pragma ensures that all variables are properly
       declared and prevents other misuses of legacy Perl features.

       The "use warnings" pragma produces some lovely diagnostics. One can
       also use the -w flag, but its use is normally discouraged, because it
       gets applied to all executed Perl code, including that not under your
       control.

En ce qui me concerne, je trouve le risque de n'être pas informé
de ce genre d'erreurs plus grave que d'écrire 2 lignes systématiquement
dans mes scripts Perl.

Après, il y a aussi le style de programmation, comparer:

   #! /usr/bin/perl
   
   use strict;
   use warnings;
   
   my %data = ('un' => 'bla', 'deux' => 'toto');
   
   print $data{'deux'},
         $data{'uns'}, # <-- ici un warning, bien
         "\n";
   
   $data{'uns'} = 'toto'; # <-- ici pas de warning, clé 'uns' créée alors
                          #     que je voulais réellement mettre à jour
                          #     'un'
   
   # NB: en Perl on peut aussi écrire $data{uns} sous certaines conditions,
   #     mais je ne préfère pas.

avec:

   #! /usr/bin/perl
   
   use strict;
   use warnings;
   
   my $data = new data;
   
   # setters
   $data->un("new value");
   $data->deux("new value 2");
   
   # getters $obj->nom ou $obj->nom()
   print join("\n", $data->un, $data->deux(), "");
   
   # print $data->uns; # <-- ici erreur, bien (un peu comme avant)
   
   $data->uns("new value"); # <-- ici erreur, mieux qu'avant
   
   package data;
   use strict;
   use warnings;
   use parent 'Class::Accessor::Fast';
   
   BEGIN {
       __PACKAGE__->mk_accessors(qw/un deux/);
   }
   
   sub new {
      my $class = shift;
   
      return $class->SUPER::new();
   }

Après, je dois avouer que je fais rarement ce genre d'erreurs, donc j'utilise
rarement ça, d'un autre côté, avec la vue qui baisse avec l'âge ...

NB: pour de l'OO encore plus moderne, par exemple (exemple de la manpage Moose)

         package Point;
         use Moose; # automatically turns on strict and warnings

         has 'x' => (is => 'rw', isa => 'Int');
         has 'y' => (is => 'rw', isa => 'Int');

         sub clear {
             my $self = shift;
             $self->x(0);
             $self->y(0);
         }

         package Point3D;
         use Moose;

         extends 'Point';

         has 'z' => (is => 'rw', isa => 'Int');

         after 'clear' => sub {
             my $self = shift;
             $self->z(0);
         };

J'ai un peu joué avec Moose, mais ce n'est pas ma façon de
faire du Perl, c'est trop haut niveau :->

En ce qui me concerne, si j'utilise souvent du code qui fait
usage de ce genre de chose ou approchant (style l'autoparseur
de DB existante qui génère les classes ORM automatiquement,
complété ci-dessous par une requête complexe manuelle

# http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Manual/Cookbook.pod
# http://stackoverflow.com/questions/8939475/dbix-and-arbitrary-sql-through-a-custom-resultsource
package get_services_complex_query;
use strict;
use warnings;
use base 'DBIx::Class::Core';

__PACKAGE__->table("dummy");

__PACKAGE__->add_columns('name');

__PACKAGE__->result_source_instance->name(\'(
   SELECT p.name
      FROM proto p, source_fetch of, source_fetch_content ofc, source_fetch_content_data ofcd, source o
      WHERE (p.id = ofcd.proto) AND (of.id = ofc.source_fetch) AND (of.source = o.id) AND (o.id = ?)
)');

1;

# generate classes at runtime from the DB schema
# see qw/DBIx::Class::Schema::Loader
package schema;
use base qw/DBIx::Class::Schema::Loader/;

__PACKAGE__->loader_options(
    );

__PACKAGE__->register_class(get_services_complex_query => 'get_services_complex_query');

1;

Qu'on utilise ensuite ainsi:

my $dbi = schema->connect($CFG::config{'dbi_dsn'},
                          $CFG::config{'dbi_user'},
                          $CFG::config{'dbi_pass'},
                          { RaiseError => 1, AutoCommit => 1 });
my $o = $dbi->resultset('Services')->find({name => $service});

my @r = $dbi->resultset('get_services_complex_query')
        ->search({},
                {bind => [ $o->id ]});

return map { $_->name } @r;

)

je suis plus `manuel' dans mon code Perl. Question de goût.



More information about the gull mailing list