Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re: What are multiple $_[0] =~ operations doing?

by davido (Cardinal)
on Apr 01, 2005 at 09:44 UTC ( #444130=note: print w/replies, xml ) Need Help??


in reply to What are multiple $_[0] =~ operations doing?

Let me answer your last question first.

The =~ binding operator binds the scalar on its left with the regexp (or transliteration) operator on the right, so that the regexp operator may examine and act upon the scalar on the left.

The = assignment operator assigns the value of the expression on the right hand side to the variable on the left.

The == equality operator evaluates the numeric equality of the items to its left and right. It has nothing to do with assignment.

Now for your first question:

$_[0] is a sort of alias to the first argument passed to the enclosing subroutine. In fact, perlsyn states, "The array @_ is a local array, but its elements are aliases for the actual scalar parameters." As the documentation also states, modifying $_[0] will attempt to modify the value held in the variable passed in the sub's arg list. For example:

my $value = 100; changeit( $value ); print "$value\n"; sub changeit { $_[0]++; } __OUTPUT__ 101

As you can see, incrementing $_[0] increments $value too (because they're basically the same thing).

Now as the docs say, if you attempt to modify the value of an unmodifiable scalar, you get an error. For example:

changeit( 100 ); sub changeit { $_[0]++; }

If you run this, you'll get an error. This is because $_[0] is aliased to a value, not a variable, in this case, and you can't change a hard-coded value. 100 cannot be 101 :)

As a matter of maintainable style, it's often discouraged to allow your subroutines to modify the values of their parameters. But as with most things Perlish, this rule of thumb only applies where convenient. After all, chomp modifies its parameter list. So does chop.

I hope this helps.


Dave

Replies are listed 'Best First'.
Re^2: What are multiple $_[0] =~ operations doing?
by jhourcle (Prior) on Apr 01, 2005 at 13:02 UTC
    As a matter of maintainable style, it's often discouraged to allow your subroutines to modify the values of their parameters. But as with most things Perlish, this rule of thumb only applies where convenient. After all, chomp modifies its parameter list. So does chop.

    I'd like to add that this style recommendation will probably be affected by your background (or the background of the senior people in your department) (as davido said, 'where convenient'). For those with a C background, it make perfect sense to modify the arguments, as they can only return one value from a function. So it's common practice to have the function return a success or failure flag, and modify what was passed in. (it's part of the whole issue if you're going to pass by value, or pass by reference), as if you pass by value, there's no chance to modify the values. PL/SQL has a similar concept called 'in/out' parameters which work like pass by reference.

    There is, however, the expectation in almost all languages that you're not going to modify the references that were passed in, unless that was part of the plan, and it's well documented. The local style guide might have recommendations on function naming, so it's readily apparent to people that the function does modifications on its args. The following would be an example of bad code:

    sub sum { my $list = shift; my $sum = 0; while (my $i = shift @$list) { $sum += $i; } return $sum; } my @values = qw(1 2 3 4 5 6 7); print sum(\@values), " ; '@values'\n";

    You should always be suspicious when there's only one argument to the function, and it's an arrayref, not an array ... there might be some time savings by not pushing everything to the stack, but it introduces the possibility of someone messing with your values. Two or more arrayrefs isn't so much a sign to worry, as arrayrefs are the only way to pass more than one array to a function.

    Depending on the audience, something such as the following might be considered acceptable:

    sub add_two { my $arrayref = shift; $_ += 2 foreach @$arrayref; return 1; } my @values = qw( 1 2 3 4 5 6 7 ); print add_two(\@values), " ; '@values'\n";

    Okay, that might be a bad example. You might do it when you wanted to make sure that the original wasn't left around, though. Such as:

    sub sanitize_strings { my $arrayref = shift; s/[^a-zA-Z0-9_\-]/_/g foreach @$arrayref; return 1; } my @strings = qw( abc 123 a&21 j**!k ); print sanitize_strings(\@strings), " ; '@strings'\n";

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://444130]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2021-01-27 09:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?