Question

Je fais un passage par référence comme ceci :

use strict;
use warnings;

sub repl {
    local *line = \$_[0]; our $line;
    $line = "new value";
}

sub doRepl {
    my ($replFunc) = @_;
    my $foo = "old value";
    $replFunc->($foo);
    print $foo; # prints "new value";
}

doRepl(\&repl);

Existe-t-il une manière plus propre de procéder ?

Les prototypes ne fonctionnent pas parce que j'utilise une référence de fonction (croyez-moi, il y a une bonne raison d'utiliser une référence de fonction).

Je ne veux pas non plus utiliser $_[0] partout dans repl parce que c'est moche.

Était-ce utile?

La solution

As-tu regardé Données : Alias?Il vous permet de créer des alias de portée lexicale avec une syntaxe propre.

Vous pouvez l'utiliser pour créer une sémantique de passage par référence comme celle-ci :

use strict;
use warnings;

use Data::Alias;

sub foo {
    alias my ($arg) = @_;
    $arg++;
}

my $count = 0;

foo($count);

print "$count\n";

La sortie est 1, indiquant que l'appel à foo a modifié son argument.

Autres conseils

sub repl {
    my $line = \$_[0];     # or: my $line = \shift
    $$line = "new value";
}

Il y a deux façons de le faire. passer explicitement une ref scalaire à $foo, ou profiter du passage intégré de Perl par la sémantique de référence.

Référence explicite:

my $foo = "old value";
doRepl( \&repl, \$foo );
print $foo; # prints "new value";

sub repl {
    my $line = shift;
    $$line = "new value";
}

sub doRepl {
    my ($replFunc, $foo) = @_;
    $replFunc->($foo);
}

Passe par référence:

my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";

sub repl {
    $_[0] = "new value";
}

sub doRepl {
    my $replFunc = shift;
    $replFunc->(@_);
}

Même colombophile passe par référence:

my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";

sub repl {
    $_[0] = "new value";
}

sub doRepl {
    my $replFunc = shift;
    &$replFunc;
}

La première utilisation normale perl références difficiles à faire le travail.

Le premier passage par la méthode ref utilise le fait que Perl transmet des arguments à toutes les fonctions en tant que références. Les éléments de @_ sont des alias réellement aux valeurs dans la liste des arguments lorsque le sous-programme est appelé. En modifiant $_[0] dans foo(), vous modifiez en fait le premier argument à foo().

La seconde passe par la méthode ref utiliser le fait qu'un sous appelé avec un sceau de & et aucun parens obtient la matrice de @_ de son appelant. Sinon, il est identique.

Mise à jour: Je viens de remarquer que vous désirez éviter $_[0]. Vous pouvez le faire en rempl si vous voulez:

sub repl {
    for my $line( $_[0] ) {
        $line = 'new value';
    }
}

Je ne pense pas qu'il y ait quelque chose de mal à utiliser local pour créer l'alias dans ce cas.

portée dynamique est bien sûr une fonctionnalité puissante, mais aussi longtemps que vous êtes au courant des effets secondaires (nouvelle valeur est visible dans les fonctions appelées de son champ d'application, si un lexique du même nom est portée, il ne peut pas être localisé, ...) alors il est un complément utile à la boîte à outils Perl déborde déjà.

La raison principale pour les mises en garde dans la documentation Perl sur local doivent empêcher les gens d'utiliser par inadvertance au lieu de my et pour faciliter la transition de perl4. Mais il y a certainement des moments où local est utile, ce qui est un.

Utilisation for pour créer votre alias est également une option, mais je trouve la syntaxe explicite avec local plus claire dans son intention. Il est également un peu plus rapide si la performance est une préoccupation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top