-
Notifications
You must be signed in to change notification settings - Fork 601
perlop: properly document s///e modifier #23656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
If it behaves as a |
Yes: use v5.36;
sub Honk::DESTROY {
say "$_[0] destroyed";
}
my $string = "hello";
$string =~ s{([eo])}{
say "replacing '$1'";
my $obj = bless {}, 'Honk';
"_"
}eg;
say "done: $string";
say '$obj is ', eval('$obj') // "not in scope: $@";Output:
Only in the sense that every |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This p.r. is a huge improvement IMO
| result. | ||
| e Evaluate the right side as a block of code. | ||
| ee Evaluate the right side as a block of code, then eval() | ||
| the resulting string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where exactly in the source code does this evaluation of the RHS as a block of code rather than as either an expression or a string is enforced? (I'm asking this not to quibble, but just to know your reference point.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know this beforehand. This PR was written from a Perl programmer POV; I just know how /e behaves in practice. You can put multiple statements separated by ; in the replacement part; it acts as a block scope; etc.
But I looked it up. The relevant part of the perl source is S_scan_subst in toke.c. It has special handling for EXEC_PAT_MOD flags (defined as 'e'), which it keeps a count of in es. If es is non-zero, it turns on the PMf_EVAL flag on the op and literally wraps do { ... } around the replacement part. Then, for every e beyond the first one, it prepends eval to the replacement part. In other words, it doesn't even act on op trees; it literally generates source code of the form ("eval " x ($es - 1)) . "do { $RHS }". I didn't expect that.
And I wrote a perfect example years ago: |
- s///e is not limited to expressions. The replacement part can contain
any number of statements, like 'do { ... }'.
- s///ee does not treat the RHS as a string. The RHS is parsed as a
block (like s///e), but then the resulting string is eval()'d.
- You can have more than two e's. Each additional 'e' wraps another
eval() around the result.
417ee0c to
b8322d9
Compare
s///eis not limited to expressions. The replacement part can contain any number of statements, likedo { ... }.s///eedoes not treat the RHS as a string. The RHS is parsed as a block (likes///e), but then the resulting string iseval()d.es. Each additionalewraps anothereval()around the result.