darkomen has asked for the wisdom of the Perl Monks concerning the following question:

I would like to know if it is posible to write a subroutine that modifies a variable passed to it w/o a return... kind of the way chomp works... you dont't have to say $var = chomp($var);, $var just gets chomped... any ideas?
  • Comment on Subroutine that modifies actual variable

Replies are listed 'Best First'.
Re: Subroutine that modifies actual variable
by dimmesdale (Friar) on Jul 11, 2001 at 21:05 UTC
    I believe Perl uses what's called a 'pass by reference' method to give variables to a function (only important to remember the name in other languages, e.g., C/C++, where you have a choice of by value or by reference). Anyway, what this means is that you can actually modify the variable inside the function without doing anything special. E.g.:
    sub delete_first_char { $_[0] =~ s/^.// }

    That code would delete the first character of a string (admittingly not the best way to do it). However, most subroutines you see do this:
    sub whatever { ($var1,$var2,$etc) = @_; ... }

    They do this so that they don't mistakingly alter/change the variable that was passed to them. Usually this is a good coding practice, however, quite certainly situations do arise where you wish to modify the variable that you pass in, in which case you just refer to it directly; i.e., $_[--elm # here--].
      I feel rather silly, since i've been coding perl for around a year and have never tried to modify $_[0] directly, i've always assigned it to another var. Thank you.
Re: Subroutine that modifies actual variable
by tadman (Prior) on Jul 11, 2001 at 21:06 UTC
    You've got to either pass a reference to a variable explicitly, or define the function as something that takes a reference. Here's two examples, with usage:
    # This function takes a value by reference, # which is the responsiblity of the caller. sub fref { my ($var) = @_; $$var = $$var . " Python"; return $$var; } # This function defines a prototype which takes # a reference instead of a scalar. This way the # caller doesn't have to do anything special. sub fprot(\$) { my ($var) = @_; $$var = $$var . " Python"; return $$var; } # The reference version requires a backslash before any # passed parameters. my $test = "Monty"; print fref(\$test),"\n"; print $test,"\n"; # While the prototype means that you don't have to worry # about doing anything special. my $test = "Learning"; print fprot($test),"\n"; print $test,"\n";
      The first answer already showed how to do it without using Perl's (IMHO broken) prototype semantics or with an explicit reference.

      That said, I think it is stylistically a bad idea to modify variables passed in by reference without warning in the usage or the name of the function.