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

Hi, how can I force a sub that is able to return in scalar and list context to use the scalar context? Without using a method I know already. And without changing the return value. Take into account, that 'right' can also be 0 or undef and should not change. Here is what I have done:
sub xx { wantarray ? ( qw/wrong wrong wrong/ ) : 'right' } # use scalar to force scalar context print scalar (xx()); # use prototypes sub ss($) { return $_[0] } print ss(xx()); # use the . operator but it change my result. ( invalid try ) print xx() . ''; # use || or && did not work since they change my returned value
The Intend for this node is to make something like this look nicer.
$x->zxy( time => scalar( localtime ), 4 => scalar(qw/ 1 2 3 4 /) );
Boris

Replies are listed 'Best First'.
Re: how to force scalar context (without scalar())?
by ihb (Deacon) on Sep 19, 2004 at 11:49 UTC

    The classical trick is to use ~~ which is bitwise negation applied twice. It doesn't work for references or anything slightly magical as it numifies or stringifies its operand.

    Personally though, I have no problems what so ever with scalar() and the indent of its use can't be any clearer. I advocate for the use of scalar().

    Update:
    You can also do (my $whatever = ...) but that's also ugly and not a perfect equivalent to scalar(), which I must emphazise is the perfect function for this with no pitfalls. The scalar assignment operator returns the LHS, i.e. e.g. \(my $whatever = ...) references $whatever and not the expression you wanted in scalar context.

    Your sub ss ($) { $_[0] } function isn't either a perfect equivalent to scalar() since it returns a copy of the value.

    my $foo; print \$foo eq \scalar($foo); # true print \$foo eq \ss($foo); # false

    I can see this as a fun exercise or quiz but I really have to question practicing using anything but scalar() as a general scalar context enforcing operator for anything except obfuscation.

    ihb

    Read argumentation in its context!

      I used scalar too, but searching for alternate solutions.
      ~~ is not really what I was after, since it does not play well enough with undef's.
      perl -we 'my $x = ~~undef'
      Boris
Re: how to force scalar context (without scalar())?
by Aristotle (Chancellor) on Sep 19, 2004 at 13:33 UTC

    scalar is the advertised way to do this and the only one that offers these exact semantics. (Even your prototyped function is simply exactly the same as scalar itself.) What do you have against it?

    Makeshifts last the longest.

      I search for a way to list parameter to a function nicely.
      function( aa => otherfunction(), bb => anotherone() );
      but sometimes these functions return a list even if I'm only interested in the scalar value. so I write:
      function( aa => otherfunction(), bb => scalar( anotherone() ) );
      or
      function( aa => otherfunction(), bb => anotherone() || '' );
      but scalar() is a bit ugly and || something may change my return value. So I end up in using scalar or
      my $another = anotherone(); <code> function( aa => otherfunction(), bb => $anotherone );
      I just search for a nicer look for a scalar like function. Using a sub ss ($) { $_[0] } is not a real option for me. But perhaps something other can provide the same functionality.
      Boris

        Ah, assignment… of course. You can inline it:

        function( aa => ( my $aa = otherfunction() ), bb => ( my $bb = anotherone() ), );

        That's all the options available.

        Makeshifts last the longest.

Re: how to force scalar context (without scalar())?
by iblech (Friar) on Sep 19, 2004 at 15:37 UTC
    The following won't help you, but I had to say it ;)
    # Perl 6 $obj.method( foo => +some_number_returning_func(), bar => ~some_string_returning_func(), );
    Unary + (~) forces Number (String) context to its argument.
Re: how to force scalar context (without scalar())?
by Anonymous Monk on Sep 19, 2004 at 22:46 UTC