Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

strange usage of s/// [solved: Perl 5.14 and 5.16 bug]

by brx (Pilgrim)
on Sep 03, 2013 at 14:52 UTC ( #1052121=perlquestion: print w/ replies, xml ) Need Help??
brx has asked for the wisdom of the Perl Monks concerning the following question:

*update* : bad link corrected

*update2* : reply to myself using B::Deparse => Re: strange usage of s/// -- I'm still confused :)

*update3* : problem solved, it's a Perl 5.14 and 5.16 bug.


Thanks, contributors, especially slms. As explained in slms's post(Re^2: strange usage of s///), Perl 5.18 behavior is correct :
Perl v5.18.1 handles them as one would expect:
perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K$"//; print' $_ = 'abcdef'; s[@{[s/.././gr];}\K$"][]; print $_; -e syntax OK
perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K //; print' $_ = 'abcdef'; s[@{[s/.././gr];}\K ][]; print $_; -e syntax OK

With Perl 5.14 and 5.16, there is a bug and some quantum tunnelling in s/// (yep! ;):

perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K$"//; print' $_ = 'abcdef'; s[@{[s/.././rg];}\K][$"]; print $_; -e syntax OK
perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K //; print' $_ = 'abcdef'; s[@{[s/.././rg];}][\\K ]; print $_; -e syntax OK

original post:

Dear Monks,

Could you, please, help me to understand one mysterious golf solution posted by "tails" at http://golf.shinh.org/p.rb?Bisection . (problem: read line, eg "abcdef", and print bisection, ie "abc def")

This is not the best answer (shortest) but it seems very strange... Here is the code (http://golf.shinh.org/reveal.rb?Bisection/tails_1377006056&pl => http://golf.shinh.org/reveal.rb?Bisection/tails+%28%3F%29_1377006539&pl):

#!perl -pl s/@{[s".."."gr]}\K$"//

*update* : why $" is different from literal space character in this regex? how this regex can add something to $_?

My other strange tests

$_="abcdef"; s/@{[s".."."gr]}/$& /;print # "...abcdef" $_="abcdef"; s/@{[s".."."gr]}//;print # "...abcdef" $_="abcdef"; s/@{[s".."."gr]}\K //;print # "\K def"

FYI, "tails" also wins the contest with:

#!perl -p s/.(?0).|\K/ $&/

Nice usage of (?0), tails! :)

English is not my mother tongue.
Les tongues de ma mère sont "made in France".

Comment on strange usage of s/// [solved: Perl 5.14 and 5.16 bug]
Select or Download Code
Re: strange usage of s///
by smls (Friar) on Sep 03, 2013 at 16:16 UTC

    Try YAPE::Regex::Explain

    PS: The s/@{[s".."."gr]}\K$"// solution does not work for me at all. Does it actually work for you?

      Neigher \K nor /r existed in Perl 5.6.x, which is the latest version of the regexp syntax that YAPE::Regex::Explain supports. (This is documented, and would have been pretty easy to test.)

      perl -MYAPE::Regex::Explain -E 'say YAPE::Regex::Explain->new(q/@{[s". +."."gr]}\K$"/)->explain'

      ...produces the following output (assuming a Perl that is recent enough to understand \K and /r):

      The regular expression: (?-imsx:@{[s".."."gr]}\K$") matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- @{ '@{' ---------------------------------------------------------------------- [s".."."gr] any character of: 's', '"', '.', '.', '"', '.', '"', 'g', 'r' ---------------------------------------------------------------------- } '}' ---------------------------------------------------------------------- \K 'K' ---------------------------------------------------------------------- $ before an optional \n, and the end of the string ---------------------------------------------------------------------- " '"' ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------

      ...which obviously is totally wrong. It completely misses that @{[.....]} interpolates code into a string (it instead thinks it's looking at a character class), it mistakes \K for literal "K", and mistakes $" for an end of line/string metacharacter, followed by a literal ", when it really should see the Perl special variable. Add to that the fact that it couldn't possibly understand the /r semantics, and the fact that we're using the regexp engine re-entrantly (which I don't think used to be possible), and it's a hopeless case for poor old YAPE::Regex::Explain.

      I too am confused by why he demonstrated /@{[s".."."gr]}\K$"//; I don't see it mentioned among the submissions I viewed, and I don't see any mechanism for it actually doing what it's supposed to. It certainly doesn't match the code in the link provided.


      Dave

        Neigher \K nor /r existed in Perl 5.6.x, which is the latest version of the regexp syntax that YAPE::Regex::Explain supports. (This is documented, and would have been pretty easy to test.)

        Yes, my bad.

        I made up for it by providing a proper, detailed answer below... :)

      PS: The s/@{[s".."."gr]}\K$"// solution does not work for me at all. Does it actually work for you?

      Sure. This solution was accepted on anarchy golf site.

      perl -e '$_="abcdef";s/@{[s".."."gr]}\K$"//;print"$_\n";' abc def
      English is not my mother tongue.
      Les tongues de ma mère sont "made in France".
Re: strange usage of s///
by smls (Friar) on Sep 03, 2013 at 17:21 UTC
    $_="abcdef"; s/@{[s".."."gr]}/$& /; print;

    This variation of yours does in fact work (prints "abc def"), and so do the following ones (which are closer to the original solution by "tails"):

    s/@{[s".."."gr]}\K/ /;
    s/@{[s".."."gr]}\K/$"/;

    Thus I conclude that the original "solution" is the result of a typo (separator '/' put in the wrong place), and cannot work.

    As for how the corrected variations listed above work, lets break it down:

    1)

    s".."."gr;

    If the input string in $_ has an even number of characters (which seems to be implicitly assumed here), then this expression will return a string consisting of only dots, of half the length of the input string. E.g. for the input string "abcdef" it returns "...".

    2)

    @{[ ]}

    This is a common trick to execute a piece of code, and insert the code's return value directly into a string without introducing a temporary variable. It works because Perl interpolates anything that looks like an array variable inside a string.

    3)
    The above two expressions combined, will effectively produce the following substitution command in case of the input string "abcdef" (for the three different variations listed above):

    s/.../$& /;
    s/...\K/ /;
    s/...\K/$"/;

    All of them do the same thing: Insert a space after the third character of the original string, i.e. right in the middle.
    (If you're still confused, see perlreref for an explanation of \K and $&.)

    ------
    why $" is different from literal space character in this regex?

    It isn't, unless you've manually changed that variable.
    Maybe the author just liked a little obfuscation, or wanted to make it more "generic".

      s/.././gr will convert each consecutive pair of any character (aside from newline) to single dots. If there's an extra (odd) character at the end, this won't be converted, but we don't worry about that because the input seems always to be strings of even numbered length.

      Also, don't forget the importance of /r here, as it causes the substitution to return its result without modifying the original string, which is important since we're still working with the original string in the outer layer.


      Dave

        #!perl -pl s/@{[s".."."gr]}\K$"//

        I understand the regex like this:

        s/....\K // (with the good number of '.')

        ...but in facts it works like this:

        s/....\K/ /

        I don't understand why. The usage of $" seems magic too...

        English is not my mother tongue.
        Les tongues de ma mère sont "made in France".
      $_="abcdef"; s/@{[s".."."gr]}/$& /; print; [download]
      This variation of yours does in fact work (prints "abc def"), and so do the following ones (which are closer to the original solution by "tails")

      Not for me. It prints "...abcdef" (with perl v5.14.4).

      Thus I conclude that the original "solution" is the result of a typo (separator '/' put in the wrong place), and cannot work.

      No typo. Code is good. You can test it on: http://golf.shinh.org/p.rb?Bisection

      English is not my mother tongue.
      Les tongues de ma mère sont "made in France".
Re: strange usage of s///
by brx (Pilgrim) on Sep 03, 2013 at 21:01 UTC

    B::Deparse seems to understand and to see difference between variants:

    1) Original:

    perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K$"//; print' $_ = 'abcdef'; s[@{[s/.././rg];}\K][$"]; print $_; -e syntax OK

    Do the rigth thing, but why?!

    2) Litteral space char (not $"):

    perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K //; print' $_ = 'abcdef'; s[@{[s/.././rg];}][\\K ]; print $_; -e syntax OK

    Strange, isn't it? :). I'm confused...

    English is not my mother tongue.
    Les tongues de ma mère sont "made in France".
      Perl v5.18.1 handles them as one would expect:
      perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K$"//; print' $_ = 'abcdef'; s[@{[s/.././gr];}\K$"][]; print $_; -e syntax OK
      perl -MO=Deparse -e '$_="abcdef"; s/@{[s".."."gr]}\K //; print' $_ = 'abcdef'; s[@{[s/.././gr];}\K ][]; print $_; -e syntax OK

      PS: With Perl v5.14.2 I get the same result as you.

      (Testing environment was 64bit Linux in both cases.)

      So yeah, strange indeed...

        Thank you very much, smls. Original post updated.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1052121]
Approved by hdb
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (20)
As of 2014-07-24 16:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (162 votes), past polls