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

In the interest of obfuscation, I looked to create a nonsensical scalar, and I settled on this: q{+\//}. Much to my delight, I found that eval'ing a few of those appended together creates a large number! I worked that into a trick and was about to post it, but it fails on Windows because a different number is generated. So, at the risk of spoiling, I ask two questions:
  1. What does this do: perl -e 'print eval(+\//+\//+\//);'?
  2. And why might it behave differently on different OS's or Perl versions? Perl 5.8.0 on Solaris gives me 3338748. Perl 5.8.6 on Windows gives me 6742212.

Replies are listed 'Best First'.
Re: eval'ing strange scalar
by ikegami (Patriarch) on Jan 23, 2009 at 17:20 UTC

    +\//+\//+\//
    is the same as
    + \( // ) + \( // ) + \( // )

    The leading (unary) "+" is a no-op used to affect parsing in some situations, but it does nothing here.

    \ is the reference taking operator. When used as a number, a reference returns the referenced memory address.

    // is a match operator (m/.../).

    It sums the memory addresses of the values returned by the three calls to the match op.

    And since it returns a number, passing it to eval does nothing but return the same number.

    I can't fathom find a use for it.

    Update: Added a couple of details.

      Your explanation is fantastic; referring to \ as "the reference taking operator" really helps. Thanks!

      I don't envision a real use for it either, just experimenting.

      Update: Below was my experimentation. As mentioned earlier, it proved to be not portable as the references lead to different numbers on different systems.

      use strict; use warnings; $/=q{+\//}; # my silly scalar for(@{[31,60,66,68,73]}){ # magic numbers ($-=>$_)=($_=>$!); # set $- to magic number and $_ to empty $_.=$/while--$-; # append silly scalar to $_ <magic number> times $_=eval; # eval it for an eight-digit number... s+......$++; # whose first two digits push(@_,$_) # are the ASCII for '!', 'A', 'H', 'J', 'P' }die map{chr}@_[eval join(q{,},3,1,4,2,0)]=>10; # die with 'JAPH!\n'

Re: eval'ing strange scalar
by kyle (Abbot) on Jan 23, 2009 at 17:25 UTC

    To expand on the answer from ikegami, you're getting three references and treating them as numbers. As numbers, they're just memory addresses, and they'll add up to something, but you'll get different memory addresses between different platforms. That's why it behaves differently on Windows vs. Solaris, etc.

Re: eval'ing strange scalar
by jvector (Friar) on Jan 23, 2009 at 19:43 UTC
    Perl 5.8.0 on Solaris gives me 3338748. Perl 5.8.6 on Windows gives me 6742212.
    5.10.0 on Ubuntu 8.10 gives 451354452 B-) My thanks also to ikegami for the elucidation, but I am left wondering:

    - what is it that m// is matching? The null string, presumably... so would that be different on the same machine at different times?

    Answer: yes.

    victor@pan:~$ perl -e 'print eval(+\//+\//+\//)."\n";' 411098964 victor@pan:~$ perl -e 'print eval(+\//+\//+\//)."\n";' 436080468 victor@pan:~$ perl -e 'print eval(+\//+\//+\//)."\n";' 415780692 victor@pan:~$


    This signature was ready by Christmas. Where were you?
      Evidently, the // are matching $_, which even though it is undefined is treated as the null string, which happens to match. The \ is also providing a scalar context. Note that the eval is somewhat superfluous, try
      perl -e '$_="."; $r=\-d; print $r, "\n", $r + 0, "\n", $$r, "\n";'
      Also, your perl or OS appears to have address space randomization (security feature); some machines return the same numbers every time.

      It kinda looks to me like 0+\ might be able to distinguish values depending on how they were arrived at.