Why is the return variable value of a subroutine not assigned to the $ _ variable by default

I have a Perl routine that updates an RSS feed. I want to check the return value, but the function is used in many places, so I wanted to just check the default variable $_

, which I understand should be assigned to the return value if no variable is specified.

The code is too long to include it all, but essentially it does the following

sub updateFeed {
  #....
  if($error) {
    return 0;
  }
  return 1;
}

      

Why then

$rtn = updateFeed("My message");
if ($rtn < 1) { &Log("updateFeed Failed with error $rtn"); }

      

DO NOT log error

then

updateFeed("myMessage");
if ($_ < 1) { &Log("updateFeed Failed with error $_"); }

      

logs an error " updateFeed Failed with error

"? (Note that there is no value at the end of the message.)

Can anyone tell me why the default variable is empty string or undef?

+3


source to share


4 answers


Because Perl doesn't work that way. $_

does not automatically get the result of functions called in the void context. There are built-in operators that read and write $_

and by default @_

, but your own routines will only do this when you write code to make it happen.



+9


source


A normal function call is not one of the $_

implicitly used contexts .

Here's what perldoc perlvar

(as of version 5.1.14) has to say about $_

:

$ _
By default, enter and search by pattern. The following pairs are equivalent:



    while (<>) {...}    # equivalent only in while!
    while (defined($_ = <>)) {...}

    /^Subject:/
    $_ =~ /^Subject:/

    tr/a-z/A-Z/
    $_ =~ tr/a-z/A-Z/

    chomp     
    chomp($_) 

      

Here are the places where Perl will accept $ _ even if you're not using it:

  • The following functions use $ _ as their default argument:

    abs, alarm, chomp, chop, chr, chroot, cos, defined, eval, exp, glob, hex, int, lc, lcfirst, length, log, lstat, mkdir, oct, ord, pos, print, quotemeta, readlink, readpipe, ref, require, inverse (only in scalar context), rmdir, sin, split (on second argument), sqrt, stat, study, uc, ucfirst, unlink, unpack.

  • All tests are files ( -f

    , -d

    ) except -t

    , which is STDIN by default. See -X

    at perlfunc

  • Pattern matching operations m//

    , s///

    and tr///

    (aka y///

    ) when used without an operator =~

    .

  • The default iterator variable in a loop foreach

    unless another variable is specified.

  • Implicit iterator variable in functions grep()

    and map()

    .

  • Implicit variable given()

    .

  • The default place to enter an input record is when the result of an operation is <FH>

    verified by itself as the only test criterion while

    . Outside the test, while

    this will not happen.

Since $ _ is a global variable, this can lead to unwanted side effects in some cases. As of perl 5.9.1, you can now use the lexical version of $ _ by declaring it in a file or in a block with my

. Moreover, the declaration our $_

restores the global $ _ in the current scope.

Mnemonic: Underline is understood in certain operations.

+7


source


You have never assigned a flag $_

, so why should it contain your flag? It seems to contain an empty line (or perhaps undef

that builds on an empty line with a warning).

+5


source


$_

by default not set by routines in void context. You can write your own subsets to set $_

when it's empty context. You will start by checking the value wantarray

and set $_

when wantarray

undefined.

sub updateFeed {
  ...
  my $return
  ...

  if($error) {
    $return = 0;
  }else{
    $return = 1;
  }
  # $return = !$error || 0;

  if( defined wantarray ){ # scalar or list context
    return $return;
  }else{ # void context
    $_ = $return;
  }
}

      

I would recommend not doing this as it might come as a surprise to someone using your routine. Which can make it difficult to debug their program.

The only time I will do this is when emulating an inline routine .

0


source







All Articles