7
votes

Perl encapsuler une variable simple en guillemets doubles

en Perl, y a-t-il une raison d'encapsuler une seule variable dans des guillemets doubles (pas de concaténation)?

Je trouve souvent ceci à la source du programme que je travaille (écrit il y a 10 ans par des personnes qui ne font pas ' t Travaillez ici plus): P>

my $sql_host = "something";
my $sql_user = "somethingelse";

# a few lines down
my $db = sub_for_sql_conection("$sql_host", "$sql_user", "$sql_pass", "$sql_db");


1 commentaires

C'est une bonne question car les réponses ici montrent à quel point vous devriez être prudent lors de la ré-adapter le code ancien - il peut s'agir d'une bonne raison de quelque chose qui apparaît au début comme un mauvais style.


5 Réponses :


6
votes

Dans ce cas, les citations doubles sont inutiles. De plus, les utiliser sont inefficaces car cela provoque une copie des chaînes d'origine.

Cependant, vous pouvez parfois utiliser ce style pour "Stringifier" un objet. Par exemple, Uri code> Ojects Soutien Strictification: P>

my $uri = URI->new("http://www.perl.com");
my $str = "$uri";


10 commentaires

Il tournera également tranquillement un Undef dans une chaîne vide si des avertissements n'ont pas été activés, n'est-ce pas? Je n'appellerais pas qu'une utilisation valide cependant, je ne considérerais probablement que rien sans avertissement vécu pour être valide.


@mu est trop court: oui, Undef deviendra "" (quel que soit que des avertissements étaient activés)


Mais cela ne va pas aller tranquillement avec des avertissements, vous obtiendrez la plainte "valeur non initialisée dans la concaténation".


@mu est trop court, $ x // = ''; est meilleur à stringifiant undef que $ x = "$ x"; parce que vous n'avez pas à tourner des avertissements pour le faire.


Tout ce qui nécessite qu'une chaîne résoudrait automatiquement un objet, ce n'est donc pas quelque chose qui aurait normalement besoin d'être fait.


@ikegami: Mais nous examinons le code historique des olden jours avant // . Et VI bat emacs, Linux Beats Freebsd et 11 Angels peuvent danser sur la tête d'une épingle :)


Je peux imaginer une collision malheureuse d'interfaces nécessitant une stricification explicite d'un objet. Compte tenu de telles circonstances, je serais enclin à faire un appel explicite à la méthode de la chaîne sous-jacente de la classe: mon $ str = $ foo-> as_string (); il peut y avoir des cas où le stringifier est anonyme ( Ne faites pas ça!) Ou vous comptez sur le polymorphisme entre des objets qui ne partagent pas une méthode de stringification commune dans leurs interfaces (soupir). Dans ce cas, vous n'avez pas d'autre choix que de faire mon $ str = "$ foo"; # Intentionnellement stringify $ FOO - FOO :: Bar a besoin de caillé mais pas de lactosérum Notez le commentaire.


@Mu est trop court, dis-tu passer "" pour un DSN est meilleur que le passage undef ?


@ikegami: Je dis que vous manquez que le point en vous concentrant sur l'exemple spécifique plutôt que le principe général de "existe-t-il une raison pour encapsuler une seule variable dans des guillemets doubles".


@mu est trop court, hein? « $ x // = ''; est meilleur à stringifidifier UNDEF que $ x =" $ x "; " n'est pas un exemple spécifique. Vous êtes celui qui a élevé un exemple. Et si vous le souhaitez, $ x || = ''; était généralement meilleur avant // existé, et si non, vous pouvez utiliser défini ($ x) ? $ x: '' .



6
votes

Je ne sais pas pourquoi, mais c'est un motif couramment utilisé par les nouveaux arrivants à Perl. C'est généralement un gaspillage (comme dans l'extrait que vous avez posté), mais je peux penser à deux utilisations.


Il a pour effet de créer une nouvelle chaîne avec la même valeur que l'original, et cela pourrait être utile dans des circonstances très rares. p>

Dans l'exemple suivant, une copie explicite est effectuée pour protéger $ x de la modification par le sous car le sub modifie son argument. P>

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib $lib;
   use DBI;
   say "ok";
'
Can't locate object method "INC" via package "Path::Class::Dir" at -e line 4.
BEGIN failed--compilation aborted at -e line 4.

$ perl -MPath::Class=file -E'
   BEGIN { $lib = file($0)->dir; }
   use lib "$lib";
   use DBI;
   say "ok";
'
ok


2 commentaires

Le premier cas peut être décrit comme "contournement @_ aliasing avec copie explicite". Je recommanderais d'ajouter des commentaires dans le code qui fait de telles choses.


@Dolmen, une description supplémentaire des exemples.



0
votes

Ma théorie a toujours été que ce sont des gens qui arrivent d'autres langues avec de mauvaises habitudes. Ce n'est pas qu'ils pensent "j'utiliserai des guillemets doubles tout le temps", mais qu'ils ne pensent tout simplement pas!

Je serai honnête et dis-je que je tombais dans ce piège parce que je suis venu à Perl de Java, alors la mémoire musculaire était là et tenait juste à tirer.

Perlritic m'a enfin sorti de l'habitude!

Cela rend certainement votre code plus efficace, mais si vous ne pensez pas si vous voulez que vos cordes soient interpolées, vous êtes très susceptible de faire des erreurs stupides, alors j'irais plus loin et dire que c'est dangereux. < / p>


0 commentaires

7
votes

Tout cela est explicitement stringifiez les variables. Dans 99,9% des cas, il s'agit d'une erreur de novices de quelque sorte.

Il y a des choses qui peuvent arriver comme un effet secondaire de ce style d'appel: xxx

ici, Stringification a créé une copie et a transmis que sur le sous-programme, contournant la réussite de Perl par la sémantique de référence. Il est généralement considéré comme une mauvaise manifestation à des variables d'appel Munge, de sorte que vous allez probablement bien.

Vous pouvez également régler un objet ou une autre valeur ici. Par exemple, Undef strindifie à la chaîne vide. Les objets peuvent spécifier du code arbitraire à exécuter lorsqu'ils sont stricts. Il est possible d'avoir des scalaires à valeur à des valeurs numériques et chaînes distinctes. C'est un moyen de spécifier que vous voulez le formulaire de chaîne.

Il y a aussi une chose fantasmagorique profonde qui pourrait se passer. Si vous travaillez avec le code XS qui examine les drapeaux définis sur des arguments scalaires vers une fonction, Stringifier le scalaire est un moyen simple de dire à Perl, «Faites-moi une belle nouvelle valeur de chaîne propre» avec seulement des drapeaux stricts et Pas de drapeaux numériques.

Je suis sûr qu'il existe d'autres exceptions étranges à la règle de 99,9%. Ce sont quelques-uns. Avant de retirer les citations, prenez une seconde pour vérifier une merde étrange comme celle-ci. Si vous arrivez sur une utilisation légitime, veuillez ajouter un commentaire qui identifie les citations en tant que KLUDGEKEDGEKAIRE, et donne leur raison d'existence.


1 commentaires

Re "Si vous travaillez avec XS code qui examine les drapeaux définis sur des arguments scalaires vers une fonction", j'ai déjà montré un exemple pur PERL. Tout ce qui utilise ref () suffirait.



2
votes

Dans vos citations de cas sont complètement inutiles. Nous pouvons même dire que c'est faux parce que ce n'est pas idiomatique, car d'autres ont écrit.

Toutefois, citer une variable peut être nécessaire: cela déclenche explicitement la limitation de la valeur de la variable. Stringification peut donner un résultat différent pour certaines valeurs si ces valeurs sont à double variation ou si elles sont bénies de valeurs avec surcharge Stringification ED.

Voici un exemple avec Dual Vars: xxx

sortie: xxx < / p>


0 commentaires