in reply to How does ~~ force string interpolation of code into scalar context?

I've looked in perlop and find no mention of ~~. A single ~ is the bitwise negation operator. But I don't think that has anything to do with ~~.

Actually, that's exactly what it has to do with. The ~~ is two bitwise negations. The first one forces its argument to be evaluated in scalar context and negates it. The second one undoes the first's negation.

Note that it won't work on references.

Update: It won't work with floating point numbers either, as bart rightfully points out.

-sauoq
"My two cents aren't worth a dime.";
  • Comment on Re: How does ~~ force string interpolation of code into scalar context?

Replies are listed 'Best First'.
Re: Re: How does ~~ force string interpolation of code into scalar context?
by bart (Canon) on Oct 25, 2003 at 10:03 UTC
    Note that it won't work on references.
    Or floating point numbers.
    sub PI { 4 * atan2 1, 1 } print "The value of PI is ${\~~PI}\n";
    Result:
    The value of PI is 3
    
    Ouch. That's a bit coarse.

    The truth is: bitwise not only works on strings, and on integers. It works differently on both, though the net result of double not is pretty the same: restoration of the original string, or the original integer.

Re: Re: How does ~~ force string interpolation of code into scalar context?
by davido (Cardinal) on Oct 25, 2003 at 16:35 UTC
    Hmm, stacking unary operators. I hadn't considered that as even being a possibility except for things like $$ and \\ for multiple levels of referencing/dereferencing.

    Thanks for pointing out a new idiom for me (which may not be all that necessary but is definately interesting to understand).

    In the spirit of exploration I found that the following will also at least compile and force scalar context. Some of them will mangle return values though. ;)

    sub context { print wantarray ? "List\n" : "Scalar\n"; } my $string; $string = "Test ${\~~context()} string"; $string = "Test ${\!!context()} string"; $string = "Test ${\+-+context()} string"; $string = "Test ${\-+-context()} string"; $string = "Test ${\&\&context()} string";

    Thanks again...


    Dave


    "If I had my life to live over again, I'd be a plumber." -- Albert Einstein
      I found that the following will also at least compile and force scalar context. Some of them will mangle return values though. ;)

      Actually, of the four additional combinations you tried, only -+- would be at all useful. It avoids mangling integers and floats. The three others mangle everything.¹ Also, with 5.6.1 and 5.8.0 at least, using this will cause warnings about ambiguity unless warnings are explicitly disabled.

      Still, it may have some golf merit in being a short way to impose scalar context on functions that return floating point numbers. For strings or ints, though, I think ~~ is still preferable. For golf or obfuscation that is. Of course, scalar() is far better for "real" code.

      By the way, -+- might also be written as - -, the plus or space only being necessary to differentiate it from a decrement.

      1. In fact, &\& will, I think, always fail under strict checking.

      -sauoq
      "My two cents aren't worth a dime.";
      

      I think these CAN be useful ... for decorative purposes ...

      $arg1 = "arg1"; $arg2 = "arg2"; $arg3 = "arg3"; sub f1 { return "1"; } sub f2 { return "0"; } sub f3 { return "3"; } print "${\-+- f1( $arg1 )}"; print "${\+-+ f2( $arg2 )}"; print "${\-+- f3( $arg3 )}"; print "\n"

      isn't that far better than the undecorated print statements? ( Same f1(), f2(), f3(), $arg1, $arg2, $arg3. )

      print f1( $arg1 ); print f2( $arg2 ); print f3( $arg3 );

      And FAR superior to the boring and mundane:

      print "103\n";

      --
      TTTATCGGTCGTTATATAGATGTTTGCA

        Far better indeed, as your "undecorated print statements" don't interpolate the function f1, f2 and f3; they just print the literal text f1( ... ).

        The "decorative" version executes f1() with $arg1 as its parameter.

        Of course neither approach is better than print "@{[f1( $arg1 )]}";, and that method is, itself, usually worse than print f1( $arg1 ); (without unnecessary interpolation).


        Dave


        "If I had my life to live over again, I'd be a plumber." -- Albert Einstein