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 |
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 |
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 |
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 |
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
Code : | Sélectionner tout |
use warnings;
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 |
-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 |
#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 |
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 |
1 2 3 | if (m/foo/ || m/bar/) { s//PQR/; } |
peut être réécrit comme suit
Code : | Sélectionner tout |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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