perlparametersreadonlysubroutine

How to check if an element of @_ is read-only in a Perl sub?


When my sub needs to pass back some output thru one of the parameters (return value is already used to pass back another output), a run-time error occurs when that parameter holds a constant from the caller. Example:

# Increases the input by 1 and reports if the new value is bigger than 10.
sub IncreaseByOne {
    $_[0] ++;
    return ($_[0] > 10 ? 1 : 0);
}

my $x = 1;
IncreaseByOne($x);  # This is OK.
IncreaseByOne(1);   # This is not OK.

My question: Is there a way within the sub to tell if $_[0] is read only? (I understand that many would say it is not a good practice to return information thru one of parameters. But I really need to in my situation.)


Solution

  • If the sub is supposed to increment the value, then it should fail if that's not possible: don't surprise users by silently ignoring a problem. That error is a good thing!

    But if really necessary, you can test whether the scalar is readonly:

    use Scalar::Util 'readonly';
    
    sub IncreaseByOne {
      readonly($_[0]) or $_[0]++;
      ...
    }
    

    Note that instead of using out-parameters (which leads to unexpected problems like you experienced), it is often better to return a list of multiple values:

    sub IncreaseByOne {
      my ($x) = @_;
      $x++;
      my $more_than_ten = ($x > 10);
      return $x, $more_than_ten;
    }