Perl: change variable passed as parameter to subroutine

I need to change a variable inside a procedure, so it saves the changes after the procedure exits. Here's an example:

$text = "hello";
&convert_to_uppercase($text);
print $text;

      

I want to see "HELLO" on the screen, not "hello".

The subroutine will look like this:

sub convert_to_uppercase($text){
  <something like $text = uc($text);>
}

      

I know how to do this in PHP, but it seems that the parameters don't change the same way. And I searched everywhere and I couldn't find a specific answer.

Any help would be appreciated. Thank!

+3


source to share


2 answers


You really shouldn't use an ampersand &

when calling a Perl subroutine. This is only necessary when processing code as a data item, for example, when using a link, for example \&convert_to_uppercase

. Using it in a call hasn't been necessary since version 4 of Perl 5, and it does some secret things that you probably don't need.

It is not necessary for the routines to change their parameters, but the elements @_

are aliases for the real parameters, so you can do what you ask by changing this array.

If you write your subroutine like this

sub convert_to_uppercase {
    $_[0] = uc $_[0];
}

      

then he will do what you ask. But it is generally best to return the changed value so that the call code can decide whether to overwrite the original value. For example, if I have

sub upper_case {
    uc shift;
}

      



then it can be called either

my $text = "hello"; 
$text = upper_case($text);
print $text;

      

which does what you want and changes $text

; or how

my $text = "hello";
print upper_case($text);

      

which leaves $text

unchanged but returns the changed value.

+5


source


Passing the reference and modifying the original variable inside the subroutine would be done like this:

$text = 'hello';
convert_to_uppercase(\$text);  #notice the \ before $text
print $text;

sub convert_to_uppercase {       #perl doesn't specify arguments here

    ### arguments will be in @_, so @_ is now a list like ('hello') 
    my $ref = shift;             #$ref is NOT 'hello'. it '$text'

    ### add some output so you can see what going on:
    print 'Variable $ref is: ', $ref, " \n";  #will print some hex number like SCALAR(0xad1d2)
    print 'Variable ${$ref} is: ', ${$ref}, " \n"; #will print 'hello'

    # Now do what this function is supposed to do:
    ${$ref} = uc ${$ref};  #it modifying the original variable, not a copy of it
}

      

Another way is to create the return value inside the subroutine and change the variable outside the subroutine:



$text = 'hello';
$text = convert_to_uppercase($text);  #there no \ this time
print $text;

sub convert_to_uppercase {
    # @_ contains 'hello'
    my $input = shift;    #$input is 'hello'
    return uc $input;    #returns 'HELLO'
}

      

But the convert_to_uppercase procedure seems like overkill because that's what uc does. Skip it all and just do this:

$text = 'hello';
$text = uc $text;

      

+3


source







All Articles