web-dev-qa-db-fra.com

Pourquoi certains utilisateurs citent-ils des noms de classe en Perl?

Regarder Type::Tiny , je vois que le nom de la classe dans l'appel à Type::Tiny->new est cité dans les documents officiels,

my $NUM = "Type::Tiny"->new(
   name       => "Number",
   constraint => sub { looks_like_number($_) },
   message    => sub { "$_ ain't a number" },
);

Pourquoi est-ce? Est-ce un simple style? Y a-t-il des ramifications de performances pour cette pratique?

12
Evan Carroll

Citer explicitement le nom de la classe plutôt que d'utiliser un mot nu (qui est traité comme une chaîne) est l'une des trois façons d'éviter l'ambiguïté syntaxique. La section Appel des méthodes de classe de la documentation perlobj explique.

Parce que Perl vous permet d'utiliser des mots nus pour les noms de packages et les noms de sous-programmes, il interprète parfois incorrectement la signification d'un mot nu. Par exemple, la construction Class->new() peut être interprétée comme 'Class'->new() ou Class()->new(). En anglais, cette deuxième interprétation se lit comme "appelez un sous-programme nommé Class(), puis appelez new() comme méthode sur la valeur de retour de Class(). ” S'il existe un sous-programme nommé Class() dans l'espace de noms courant, Perl interprétera toujours Class->new() comme la deuxième alternative: un appel à new() sur l'objet retourné par un appel à Class().

Voir ce cas étrange en action avec la démo ci-dessous.

#! /usr/bin/env Perl

use strict;
use warnings;

sub Type::Tiny { print "Returning Bogus\n" ; return "Bogus" }

sub Type::Tiny::new { print "Type::Tiny::new\n" }

sub Bogus::new { print "Bogus::new\n" }

my $class = "Type::Tiny";

Type::Tiny->new;
Type::Tiny::->new;
"Type::Tiny"->new;
$class->new;

Sa sortie est

Retour Bogus 
 Bogus :: new 
 Type :: Tiny :: new 
 Type :: Tiny :: new 
 Type :: Tiny :: new

Le reste de la section de documentation susmentionnée montre comment se protéger contre un comportement surprenant ou des erreurs involontaires.

Vous pouvez forcer Perl à utiliser la première interprétation ( c'est-à-dire , comme appel de méthode sur la classe nommée "Class") de deux façons. Tout d'abord, vous pouvez ajouter un :: au nom de la classe:

Class::->new()

Perl interprétera toujours cela comme un appel de méthode.

Alternativement, vous pouvez citer le nom de la classe:

'Class'->new()

Bien sûr, si le nom de la classe est dans un scalaire Perl fera aussi la bonne chose:

my $class = 'Class';
$class->new();

S'appliquant à votre question, tous les appels ci-dessous sont équivalents.

Type::Tiny::->new( … );

"Type::Tiny"->new( … );

my $class = "Type::Tiny";
$class->new( … );

Ajout de :: à la fin a l'avantage de produire un avertissement utile. Dites que vous avez accidentellement tapé

Type::Tinny::->new;

Cela produit

Le mot nu "Type :: Tinny ::" fait référence à un package inexistant à la ligne ./try 15. 
 Impossible de localiser la méthode d'objet "nouveau" via le package "Type :: Tinny" (vous avez peut-être oublié de charger "Type :: Tinny "?) À ./try ligne 15.
0
Greg Bacon