Perl 5.38, la dernière mise à jour du langage de programmation, est disponible, et apporte une nouvelle fonctionnalité expérimentale pour les classes, ainsi que plusieurs améliorations

Après plus d'un an de développement depuis Perl 5.36, la version 5.38 de Perl vient d'être publiée et constitue la dernière mise à jour de ce langage de programmation. Cette mouture fournit une nouvelle syntaxe expérimentale pour définir les classes d'objets et prend désormais en charge l'Unicode 15.0. Elle propose également de nouvelles API, une nouvelle variable d'environnement pour la génération des nombres aléatoires, ainsi que divers autres changements.


Améliorations de base

Nouvelle fonctionnalité pour les classes

Une nouvelle syntaxe expérimentale est désormais disponible pour définir des classes d'objets, où les données par instance sont stockées dans des variables " field " qui se comportent comme des lexiques.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
use feature 'class';
 
class Point
{
    field $x;
    field $y;
 
    method zero { $x = $y = 0; }
}

Cette syntaxe est décrite plus en détail dans perlclass. Des notes sur les aspects internes de son implémentation et d'autres détails connexes peuvent être trouvés dans perlclassguts.

Il s'agit d'une fonctionnalité nouvelle et expérimentale, qui est encore en cours de développement. Elle fera l'objet d'ajouts, de raffinements et de modifications dans les prochaines versions. Comme il s'agit d'une fonctionnalité expérimentale, elle produit des avertissements dans la catégorie experimental::class. Ces avertissements peuvent être supprimés par une déclaration no warnings.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
use feature 'class';
no warnings 'experimental::class';

Unicode 15.0 est désormais pris en charge

Voir Unicode 15.0.0 pour plus de détails.

Les avertissements de dépréciation ont maintenant des sous-catégories spécifiques

Tous les avertissements de dépréciation ont maintenant leur propre catégorie de dépréciation spécifique qui peut être désactivée individuellement. Vous pouvez voir une liste de toutes les fonctionnalités dépréciées dans perldeprecation, et dans warnings. La liste suivante provient des avertissements :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+- deprecated ----+
|                 |
|                 +- deprecated::apostrophe_as_package_separator
|                 |
|                 +- deprecated::delimiter_will_be_paired
|                 |
|                 +- deprecated::dot_in_inc
|                 |
|                 +- deprecated::goto_construct
|                 |
|                 +- deprecated::smartmatch
|                 |
|                 +- deprecated::unicode_property_name
|                 |
|                 +- deprecated::version_downgrade

Il est toujours possible de désactiver tous les avertissements de dépréciation en une seule déclaration avec la commande

Code : Sélectionner tout - Visualiser dans une fenêtre à part
no warnings 'deprecated';

mais il est maintenant possible d'avoir un contrôle plus fin. Comme cela a toujours été le cas, ces avertissements sont automatiquement activés avec la commande


Introduction de l'API %{^HOOK}

Pour diverses raisons, il peut être difficile de créer des wrappers de sous-programmes pour certains mots-clés de Perl. Tout mot-clé dont le prototype n'est pas défini ne peut tout simplement pas être encapsulé dans une sous-routine, et certains mots-clés que perl permet d'encapsuler sont en pratique très difficiles à intégrer. Par exemple, require est délicat à envelopper, c'est possible mais cela modifie la profondeur de la pile, et les méthodes standard d'exportation supposent qu'elles seront exportées vers un paquet à une certaine profondeur de la pile, et l'enveloppe changera donc l'endroit où les fonctions sont exportées à moins d'être implémentée avec beaucoup d'attention. Cela peut être très gênant à gérer.

C'est pourquoi un nouveau hachage appelé %{^HOOK} a été introduit afin de faciliter ce genre de situation. Lorsqu'un mot-clé supporte une sorte de crochet spécial, ce hook sera placé dans ce nouveau hachage. Les crochets de ce hachage seront nommés d'après la fonction par laquelle ils sont appelés, suivie de deux barres inférieures, puis de la phase dans laquelle ils sont exécutés, actuellement avant ou après l'exécution du mot-clé.

Cette version initiale supporte désormais deux types de crochets require__before et require__after. Ils sont fournis pour faciliter l'exécution de tâches avant et après une déclaration require.

PERL_RAND_SEED

Une nouvelle variable d'environnement PERL_RAND_SEED a été ajoutée et peut être utilisée pour faire en sorte qu'un programme perl qui utilise rand sans utiliser explicitement srand() ou qui utilise srand() sans arguments soit répétable. Voir perlrun. Cette fonctionnalité peut être désactivée à la compilation en passant l'option

Code : Sélectionner tout - Visualiser dans une fenêtre à part
-Accflags=-DNO_PERL_RAND_SEED

à Configure pendant le processus de compilation.

Expressions par défaut des affectations définies-ou et logique-ou dans les signatures

L'expression par défaut pour un paramètre de signature de sous-routine peut maintenant être assignée en utilisant les opérateurs //= ou ||=, pour appliquer les valeurs par défaut lorsque l'appelant a fourni une valeur indéfinie ou fausse (respectivement), plutôt que simplement lorsque le paramètre est entièrement manquant. Pour plus de détails, voir la documentation de perlsub.

Améliorations des crochets @INC et $INC et INCDIR

La partie interne des crochets @INC a été renforcée pour gérer différents cas de figure et ne devrait plus générer de segfault ou d'assert failures lorsque les crochets modifient @INC au cours d'une opération require. Dans ce cadre, il est maintenant assuré qu'un crochet donné n'est exécuté qu'une seule fois lors d'un appel de requête, et que les répertoires dupliqués ne déclenchent pas de sondes de répertoires supplémentaires.

Pour permettre aux développeurs de mieux contrôler la recherche dynamique de modules, une nouvelle méthode de crochet, INCDIR, est désormais prise en charge. Un objet supportant cette méthode peut être injecté dans le tableau @INC, et lorsqu'il est rencontré dans le processus de recherche de module, il sera exécuté, de la même manière que les crochets INC sont exécutés, et sa valeur de retour sera utilisée comme une liste de répertoires à rechercher pour le module. Le retour d'une liste vide est un no-op. Notez qu'étant donné que toutes les références renvoyées par ce crochet seront transformées en chaînes et utilisées comme chaînes, vous ne pouvez pas renvoyer un crochet qui sera exécuté ultérieurement via cette API.

Lorsqu'un crochet @INC (soit INC ou INCDIR) est appelé pendant require, la variable $INC sera localisée pour être la valeur de l'index de @INC à partir duquel le crochet est venu. Si le crochet souhaite modifier l'index "next" de @INC, il peut mettre à jour $INC pour qu'il soit inférieur d'une unité à l'index désiré (undef équivaut à -1). Cela permet à un hook @INC de réécrire complètement le tableau @INC et de faire en sorte que perl redémarre ses sondages de répertoires à partir du début de @INC.

Les références blessed CODE dans @INC qui ne supportent pas les méthodes INC ou INCDIR ne déclencheront plus d'exception, et à la place seront traitées de la même manière que les références unblessed code, et exécutées comme s'il s'agissait d'un crochet INC.

Le flux de contrôle interdit en dehors de defer ou finally est maintenant détecté à la compilation

Il est interdit d'essayer de quitter un bloc defer ou finally au moyen d'un flux de contrôle tel que return ou goto. Les versions précédentes de perl ne pouvaient détecter cela qu'en cas de tentative à l'exécution.

Cette version de perl ajoute une détection à la compilation pour de nombreux cas qui peuvent être déterminés statiquement. Cela peut signifier que du code qui a été compilé avec succès dans une version précédente de perl est maintenant signalé comme une erreur de compilation dans cette version. Cela ne se produit que dans les cas où l'exécution du code aurait été de toute façon une erreur ; l'erreur se produit simplement à un moment antérieur.

Eval optimiste dans les motifs

L'utilisation de (?{ ... }) et de (??{ ... }) dans un motif désactive diverses optimisations globales dans ce motif. Cela peut être souhaité ou non par le programmeur. Cette version ajoute l'équivalent (*{ ... }). La seule différence est qu'il ne désactive et ne désactivera jamais aucune optimisation dans le moteur de regex. Cela peut le rendre plus instable dans le sens où il peut être appelé plus ou moins de fois dans le futur, cependant le nombre de fois qu'il s'exécute correspondra vraiment à la façon dont le moteur de regex fonctionne. Par exemple, certains types d'optimisation sont désactivés lorsque (?{ ... }) est inclus dans un motif, de sorte que les motifs qui sont en O(N) en utilisation normale deviennent en O(N*N) avec un motif (?{ ... }). Le passage à (*{ ... }) signifie que le motif restera en O(N).

REG_INF est passé de 65 536 à 2 147 483 647

De nombreux quantificateurs de regex étaient limités à U16_MAX dans le passé, mais sont maintenant limités à I32_MAX, de sorte qu'il est maintenant possible d'écrire /(?:word){1000000}/ par exemple. Notez qu'en procédant de la sorte, le moteur de regex peut s'exécuter plus longtemps et utiliser plus de mémoire.

Nouvelles fonctions API optimize_optree et finalize_optree

Il y a deux nouvelles fonctions API pour opérer sur les fragments d'arborescence, assurant que vous pouvez invoquer les parties requises du processus de génération d'arborescence qui pourraient autrement ne pas être invoquées (par exemple, lors de la création d'un LOGOP personnalisé). Pour accéder à ces fonctions, vous devez d'abord définir une #define pour accepter d'utiliser ces fonctions.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
#define PERL_USE_VOLATILE_API

Ces fonctions sont étroitement liées au fonctionnement interne de l'interpréteur, et peuvent être modifiées ou supprimées à tout moment si d'autres changements internes le rendent nécessaire.

Certains gotos sont maintenant autorisés dans les blocs defer et finally

La version 5.36.0 de Perl a ajouté les blocs defer et autorisé le mot-clé finally pour ajouter un comportement similaire à la syntaxe try/catch. Ces blocs n'autorisaient aucune expression goto à l'intérieur du corps, car cela aurait pu faire sortir le flux de contrôle du bloc. Désormais, certaines expressions goto sont autorisées si elles ont une étiquette cible constante et que cette étiquette se trouve à l'intérieur du bloc.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
use feature 'defer';
 
defer {
  goto LABEL;
  print "This does not execute\n";
  LABEL: print "This does\n";
}

Nouvelle variable regexp ${^LAST_SUCCESSFUL_PATTERN}

Elle permet d'accéder au dernier motif réussi dans la portée courante. De nombreux aspects du moteur de regex font référence au "dernier motif réussi". Le motif vide le réutilise, et toutes les variables magiques de regex s'y rapportent. Cela permet d'accéder à son motif. Le code suivant

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
if (m/foo/ || m/bar/) {
    s//PQR/;
}

peut être réécrit comme suit

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
if (m/foo/ || m/bar/) {
    s/${^LAST_SUCCESSFUL_PATTERN}/PQR/;
}

et il fera exactement la même chose.

La catégorie LC_NAME est désormais prise en charge sur les plates-formes participantes

Sur les plates-formes qui disposent de la catégorie LC_NAME de l'extension GNU, vous pouvez désormais l'utiliser comme paramètre de catégorie à "setlocale" dans POSIX pour définir et interroger ses paramètres linguistiques.

Lire la suite sur Perl.org

Syntaxe des classes Perl

SYNOPSIS

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use v5.38;
use feature 'class';
 
class My::Example 1.234 {
    field $x;
 
    ADJUST {
        $x = "Hello, world";
    }
 
    method print_message {
        say $x;
    }
}
 
My::Example->new->print_message;

DESCRIPTION

Ce document décrit la syntaxe de la fonctionnalité class de Perl, qui fournit des mots-clés natifs supportant le paradigme de la programmation orientée objet.

Historique

Depuis Perl 5, la prise en charge des objets s'articule autour du concept de blessing (bénédiction) des références avec un nom de paquetage. Cette référence pouvait alors être utilisée pour appeler des sous-programmes du paquetage avec lequel elle avait été bénite (ou n'importe lequel de ses parents). Ce système, bien que dépouillé, était suffisamment souple pour permettre la création de plusieurs systèmes d'orientation objet plus avancés et gérés par la communauté.

Class feature est une implémentation de base de la syntaxe de classe qui est familière à ce que l'on trouve dans d'autres langages de programmation. Il ne s'agit pas d'un wrapper bless, mais d'un système complètement nouveau intégré à l'interpréteur Perl.

MOTS-CLÉS

L'activation de la fonctionnalité class permet l'utilisation des nouveaux mots-clés suivants dans le cadre du paquetage actuel :

class

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
class NAME BLOCK
 
class NAME VERSION BLOCK
 
class NAME;
 
class NAME VERSION;

Le mot-clé class déclare un nouveau paquetage destiné à être une classe. Tous les autres mots-clés de la fonctionnalité class doivent être utilisés dans le cadre de cette déclaration.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
class WithVersion 1.000 {
    # class definition goes here
}

Les classes peuvent être déclarées dans la syntaxe du bloc ou de la déclaration. Si un bloc est utilisé, le corps du bloc contient l'implémentation de la classe. Dans le cas d'une déclaration, le reste du fichier est utilisé jusqu'à la prochaine déclaration class ou package.

Les déclarations class et package sont similaires, mais les classes ont automatiquement un constructeur nommé new - vous n'avez pas à (et ne devriez pas) en écrire un. En outre, dans la classe BLOCK, vous êtes autorisé à déclarer des champs et des méthodes.

field

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
field VARIABLE_NAME;
 
field VARIABLE_NAME = EXPR;
 
field VARIABLE_NAME : ATTRIBUTES;
 
field VARIABLE_NAME : ATTRIBUTES = EXPR;

Les champs sont des variables visibles dans le cadre de la classe - plus précisément dans les blocs "method" et ADJUST. Chaque instance de classe dispose de son propre stockage de champs, indépendamment les uns des autres.

Un champ se comporte comme une variable lexicale normale. Il possède un sigil et est privé pour la classe (bien que la création d'une méthode d'accès le rende accessible de l'extérieur). La principale différence est que des instances différentes accèdent à des valeurs différentes dans la même portée.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
class WithFields {
    field $scalar = 42;
    field @array  = qw(this is just an array);
    field %hash   = (species => 'Martian', planet => 'Mars');
}

Les champs peuvent optionnellement avoir des expressions d'initialisation. Si elle est présente, l'expression sera évaluée dans le constructeur de chaque instance d'objet. Lors de chaque évaluation, l'expression peut utiliser la valeur de n'importe quel champ précédemment défini, ainsi que voir toutes les autres variables dans la portée.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
class WithACounter {
    my $next_count = 1;
    field $count = $next_count++;
}

Combinée à l'attribut de champ :param, l'expression par défaut peut utiliser n'importe lequel des opérateurs =, //= ou ||=. Les expressions utilisant = s'appliquent lorsque l'appelant n'a pas transmis le paramètre correspondant au constructeur. Les expressions utilisant //= s'appliqueront également si l'appelant a passé le paramètre mais que la valeur était indéfinie, et les expressions utilisant ||= s'appliqueront si la valeur était fausse.

method

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
method METHOD_NAME SIGNATURE BLOCK
 
method METHOD_NAME BLOCK
 
method SIGNATURE BLOCK
 
method BLOCK

Les méthodes sont des sous-programmes destinés à être appelés dans le contexte des objets de la classe.

Une variable nommée $self remplie avec l'instance de l'objet courant sera automatiquement créée dans la portée lexicale de method.

Les méthodes agissent toujours comme si use feature 'signatures' était en vigueur, mais $self n'apparaîtra pas dans la liste des arguments en ce qui concerne la signature.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
class WithMethods {
    field $greetings;
 
    ADJUST {
        $greetings = "Hello";
    }
 
    method greet($name = "someone") {
        say "$greetings, $name";
    }
}

Tout comme les sous-programmes ordinaires, les méthodes peuvent être anonymes :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
class AnonMethodFactory {
 
    method get_anon_method {
        return method {
            return 'this is an anonymous method';
        };
    }
}

ATTRIBUTS

Les aspects spécifiques des mots-clés mentionnés ci-dessus sont gérés à l'aide d'attributs. Les attributs commencent tous par deux points et un ou plusieurs d'entre eux peuvent être ajoutés après le nom de l'élément, séparés par un espace.

Attributs de classe

:isa

Les classes peuvent hériter d'une superclasse en utilisant l'attribut de classe :isa.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
class Example::Base { ... }
 
class Example::Subclass :isa(Example::Base) { ... }

Les méthodes héritées sont visibles et peuvent être invoquées. Les champs sont toujours lexicaux et ne sont donc pas visibles par héritage.

L'attribut :isa peut demander une version minimale de la classe de base ; il est appliqué de manière similaire à use - si la version fournie est trop faible, elle échouera au moment de la compilation.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
class Example::Subclass :isa(Example::Base 2.345) { ... }

L'attribut :isa tentera require sur le module nommé s'il n'est pas déjà chargé.

Attributs de champ

:param

Un champ scalaire avec un attribut :param prendra sa valeur à partir d'un paramètre nommé passé au constructeur. Par défaut, le paramètre aura le même nom que le champ (moins le sigle $), mais un nom différent peut être spécifié dans l'attribut.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
field $x :param;
field $y :param(the_y_value);

S'il n'y a pas d'expression par défaut, le paramètre est requis par le constructeur ; l'appelant doit le passer ou une exception est levée. Avec une expression par défaut, ce paramètre devient facultatif.

CYCLE DE VIE DE L'OBJET

Construction

Chaque objet commence sa vie par l'appel d'un constructeur. Le constructeur est toujours nommé new et est invoqué comme un appel de méthode sur le nom de la classe :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
my $object = My::Class->new(%arguments);

Pendant la construction, les champs de la classe sont comparés au hachage %arguments et remplis si possible.

Ajustement

L'ajustement d'un objet peut être effectué pendant la construction afin d'exécuter un code défini par l'utilisateur. Cela se fait à l'aide des blocs ADJUST, qui sont appelés dans l'ordre de la déclaration.

Ils sont similaires aux blocs BEGIN, qui s'exécutent pendant la compilation d'un paquetage. Cependant, ils ont également accès à $self lexical (instance d'objet) et à tous les champs d'objet créés jusqu'à ce point.

Durée de vie

Après la phase de construction, l'objet est prêt à être utilisé.

L'utilisation de blessed (Scalar::Util::blessed ou builtin::blessed) sur l'objet renverra le nom de la classe, tandis que reftype (Scalar::Util::reftype ou builtin::reftype) renverra la chaîne 'OBJECT'.

Destruction

Comme pour les autres références, lorsque le nombre de références d'un objet atteint zéro, l'objet est automatiquement détruit.

Sources : Perl 5.38, Perl Class

Et vous ?

Que pensez-vous de cette nouvelle version de Perl ?

Utilisez-vous ce langage de programmation ? Quel est votre avis sur l'ajout des fonctionnalités de classes dans Perl 5.38 ? Envisagez-vous d'y recourir dans vos projets ?

Voir aussi

Le comité de pilotage de Perl annonce la version 5.36 du langage de programmation, elle apporte une amélioration des performances et de nouvelles fonctionnalités

Le comité de pilotage de Perl pourra-t-il sauver Perl du naufrage ? Des propositions sont en cours d'élaboration pour faire passer Perl de la « vieille école » à une nouvelle base de référence

Perl 7 est annoncé comme Perl 5.32, mais avec des valeurs par défaut différentes, plus sûres et plus modernes, selon l'équipe de Perl

Perl est-il un langage de programmation mourant ? Le langage pourrait s'éteindre d'ici 2023 selon une étude