Is there a better way to follow the link in Perl?

I am doing pass-by-reference as follows:

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); 

Is there a cleaner way to do this?

Prototypes do not work because I use a function reference (believe me that there is a good reason for using a function reference).

I also don't want to use $_[0] everywhere in repl because it is ugly.

+6
parameter-passing pass-by-reference parameters perl perl-module
source share
4 answers

Have you looked at Data :: Alias ? It allows you to create aliases with a lexical scope with pure syntax.

You can use it to create pass-by-reference semantics as follows:

 use strict; use warnings; use Data::Alias; sub foo { alias my ($arg) = @_; $arg++; } my $count = 0; foo($count); print "$count\n"; 

Pin 1 indicating that calling foo changed its argument.

+9
source share

There are several ways to do this. Pass the scalar link to $foo explicitly or use the Perl built-in pass on link semantics.

Explicit Link:

 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); } 

Follow this link:

 my $foo = "old value"; doRepl( \&repl, $foo ); print $foo; # prints "new value"; sub repl { $_[0] = "new value"; } sub doRepl { my $replFunc = shift; $replFunc->(@_); } 

Even an amateur follows the link:

 my $foo = "old value"; doRepl( \&repl, $foo ); print $foo; # prints "new value"; sub repl { $_[0] = "new value"; } sub doRepl { my $replFunc = shift; &$replFunc; } 

The first uses regular perl hard links to do the job.

The first pass through the ref method takes advantage of the fact that Perl passes arguments to all functions as references. The @_ elements are actually aliases for the values ​​in the argument list when calling the subroutine. By changing $_[0] to foo() , you will actually change the first argument to foo() .

The second pass by the ref method takes advantage of the fact that sub, called with & sigil and no parens, gets the @_ array of its caller. Otherwise, it is identical.

Update: I just noticed that you want to avoid $_[0] . You can do this in repl if you want:

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

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

I do not think there is something wrong with using local to create an alias in this case.

The dynamic area, of course, is a powerful function, but so far you know about side effects (a new value is visible in the functions called from its scope, if the vocabulary of the same name is in scope, it cannot be localized, ...) , then this is a useful addition to the already crowded Perl toolbox.

The main reason for warnings in Perl docs about local is to make people inadvertently use it instead of my and make it easier to switch from perl4. But there are certain points when local is useful, and this is one.

Using for to create your alias is also an option, but I find the explicit syntax with local clearer in my intent. It is also slightly faster if performance is a problem.

0
source share

All Articles