Quoth szr <s...@sREzMOrVEoman.com>:
> On 5/17/2013 12:35 PM, Ben Morrow wrote:
> > The handling of the closing terminator is what I was referring to. The
> > first unbalanced, unescaped } will close the s{}{}e, and \} will be
> > converted to } before the read-this-as-Perl parser sees it. Fortunately
> > there are relatively few real situations where this matters, though it's
> > easy to create artificial situations with bizarre results, like
> >
> > s{...}{ { "foo" \} # } }e
> >
> > It's also worth noting that \\ is*not* converted to \, even though \\}
> > prevents the backslash from escaping the }. As I said, slightly strange
> > rules...
>
> The same also seems to be true of eval( expr ), such as in:
>
> eval qq{ { "foo" \} # } };
>
> Remove the closing curly brace immediately after the # and you get a
>
> Can't find string terminator "}" ...
>
> error, not unlike what happens when the same is done in a substitution
> like yours above.
Yep, and for much the same reason: the RHS of a s/// is basically a
qq//-quoted string. The most important difference is that, unlike eval,
s///e compiles its RHS at compile time, which I think accounts for the
differences you point out below.
> Also, keep in mind, in the substitution, you can use other delimiters
> besides { ... }, such as:
>
> $s =~ s{ ... }< { "foo" } # } >e
You can, but it's usually a bad idea with /e. < and > in particular
often appear alone, so the chance of accidentally closing the s///e is
much higher. Also, code blocks in Perl are usually brace-delimited, so
it's clearer if that applies to s///e as well.
> In which case escaping that } that comes before the # actually cases an
> error:
>
> syntax error at line ..., near ""foo" \"
>
> Although, the same is no completely true of qq<...>, as both
>
> eval qq< { "foo" \} # } >;
>
> and
>
> eval qq< { "foo" } # } >;
>
> yield no errors or warnings and return the string: foo
>
> Not sure what exactly accounts for this difference though.
toke.c :). The Perl string-parsing rules are *terrifying*; there's one
place in toke.c where the code takes a weighted average of probabilities
to guess whether {...} in a regexp is a hash-subscript or a {1,2}
construction. If it weren't for the fact that it actually seems to do
what you expect almost all the time it would make me thoroughly nervous.
In this case, I think the difference is that s///e sees the string at
compile time, as it was written in the source, and just applies an extra
rule about unescaping escaped closing delimiters. eval sees the string
at runtime, after it's been parsed by the qq// parser, by which point
the backslash has already disappeared.
There are other differences because of this; for instance
perl -E'$_ = "f"; s/f/\\$x/e; say; say eval qq/\\\$x/'
In fact, the RHS of s///e is more like q// than qq//, except that even
q// converts \\ -> \ which s///e doesn't.
Ben