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

In Perl 5.8.8, I run the following whole program:
use strict; use warnings; no warnings 'uninitialized'; sub A { return 10, 20; } print (my $a = A());
I expect it to give a 'Useless use of a constant in void context' warning, as the 10, 20 expression is being evaluated in scalar context. But it doesn't. Why is the last line in a function (with or without the return keyword) seemingly spared the warning? Thanks!
  • Comment on no expected 'Useless use of a constant in void context' warning for expression in return statement
  • Select or Download Code

Replies are listed 'Best First'.
Re: no expected 'Useless use of a constant in void context' warning for expression in return statement
by LanX (Saint) on Dec 14, 2012 at 21:37 UTC
    Calling a sub in scalar context means the last (returning) expression will be evaluated in scalar context.

    (see return and also Context propagation into subs and evals )

    scalar of a list is defined as it's last element, here 20.

    To catch calls in scalar context you may wanna use wantarray.

    Cheers Rolf

      right - isn't the 10 in the return 10, 20; statement being evaluated in a void context then? And so shouldn't it trigger a warning?

        No, the expression is  10, 20 and it as a whole is evaluated in scalar context

        Obvious mistakes (from Useless use of %s in void context )

        $foo = 1, 2;
        Useless use of a constant (2) in void context at -e line 1 (#1)

        assignment(=) binds tighter than comma(,) so $foo is 1

        $ perl -MO=Deparse,-p -e " $foo = 1, 2; " (($foo = 1), '???'); -e syntax OK
        $one, $two = 1, 2;
        Useless use of a variable in void context at -e line 1 (#1)

        $ perl -MO=Deparse,-p -e " $one, $two = 1, 2; " ($one, ($two = 1), '???'); -e syntax OK
        Another obvious one: $one, $two = foo();
        Useless use of private variable in void context at -e line 1 (#1)

        $ perl -MO=Deparse,-p -e " sub foo { 1, 2 } $one, $two = foo(); " sub foo { (1, 2); } ($one, ($two = foo())); -e syntax OK

        Since the behavior of comma operator in list/scalar context is well defined,
        since the behaviour of a list in scalar/list context is well defined (see If you believe in Lists in Scalar Context, Clap your Hands ),
        perl doesn't warn about : $two = foo();
        because it is predictable/guaranteed/you're expected to know what it means

         sub foo{1,2}  ($f)= foo(); is like  ($f) = (1,2); # no warn, $f is 1

         sub foo{1,2}  $f = foo(); is like  $f = (1,2); # no warn, $f is 2
        perl won't warn you, scalar context guarantees rightest most(last), list context guarantees leftest most (first)

        I meant the "returned expression" not the "return statement"!

        it's effectively

        return scalar(10,20);

        so no warning

        DB<100> print scalar (10,20) 20

        UPDATE: maybe the following is clearer,

        DB<113> sub tst { 2..10 } => 0 DB<114> ($a)=tst() => 2 DB<115> $a=tst() => "" DB<116> sub tst { /2/../10/ } => 0 DB<117> $_=2 => 2 DB<118> $a=tst() => 1 DB<119> $a=tst() => 2 DB<120> $_=10 => 10 DB<121> $a=tst() => "3E0"

        as you can see the range-op transforms to flip-flop-op in scalar context.

        So we are not returning a list but an expression which is evaluated according to the callers context.

        Cheers Rolf

Re: no expected 'Useless use of a constant in void context' warning for expression in return statement
by tobyink (Canon) on Dec 15, 2012 at 07:51 UTC

    This warning is a compile-time warning; not a run-time warning. At compile time, perl cannot tell what contexts the function A() will ever be called in. If A() is ever called in list context (perhaps even from within another module that hasn't been loaded yet) then 10 won't be useless.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'