tkil has asked for the wisdom of the Perl Monks concerning the following question:
Does anyone else think that adding /e to qr// would
be a good idea? I recently found myself doing something
like this:
my @days = qw( Sun Mon Tue Wed Thu Fri Sat );
my $days_re = qr/join '|', @days/e;
And was quite surprised that it didn't just work. There
are obvious workarounds, but they feel awkward:
my $days_re = do { my $tmp = join '|', @days; qr/$tmp/ };
(Yes, in this particular case, I could abuse $"... but that still takes a do BLOCK and a local.)
Update
-
Yes, I know that this is not how the language
works right now. What I was trying to ask is
whether others thought this might be an
interesting or useful or non-damaging feature.
-
Note that I am only suggesting /e apply to the
regex guts in qr//. Not in m//, not in s///.
-
I tried to demonstrate in my example that I
would like the /e to apply exactly once, at
the time the qr// is evaluated. I understand
that this is not how the other qr// modes
work (as they are applied at time of use).
This is exactly the sort of wart that I was
hoping people would point out, and it is
appreciated.
-
I also discussed this on at least one PM list,
so I might be confused about what I clarified there
vs. what I clarified here. :) Apologies!
So far, people (including myself! :) have demonstrated
that this is not a necessary feature. The
opinion seems mostly against whether this
would be a desirable feature.
It is just a pattern that I've found myself using
quite often lately. My preference for a one-line
approach is that I like the most important things
to be closer to the left side: what I really want
to know is that I'm compiling a regex object. Whether
I'm building it via a perl expression or by string
expansion or by literal is less important to me.
Re: qr// with /e?
by kvale (Monsignor) on Apr 23, 2004 at 22:05 UTC
|
//e is used for replacement, not matching, so it doesn't seem natural to me. This seems pretty simple:
my $patt = join '|', @days;
my $days_re = qr/$patt/;
But if you insist on putting it all on one line, try
my $days_re = qr/@{ [join '|', @days] }/;
| [reply] [d/l] [select] |
|
My main objection to the two-line method is that it leaves the first value in scope for no good reason. This is exactly why I used the do BLOCK construct in my "workaround", so that the temporary value is never seen outside the assignment.
And qr// is a bit of an odd duck, anyway; it isn't doing actual matching. In a sense, it is replacing a string with a regex. So I don't find /e all that unnatural.
But one of the reasons I asked here was to get others' opinion on the matter. Thanks for the feedback, and I'm curious what others will have to say about it. :)
| [reply] |
|
my $days_re = join('|', @days);
$days_re = qr/$days_re/;
Of course, I'd like some way to aggregate regular expressions and nicely apply operations like "concatenate" or "alternative" to them without having to drop back into string representations - that is, I'd like to be able to do:
my @days = qw( Sun Mon Tue Wed Thu Fri Sat );
my $days_re = re_alternative(map {qr/\Q$_\E/} @days);
Right now you have to do this, which is ok I guess, but I wonder if there are efficiency issues with the regular expression constructed this way:
my @days = qw( Sun Mon Tue Wed Thu Fri Sat );
my $days_re = join("|", map {qr/\Q$_\E/} @days);
$days_re = qr($days_re);
--
@/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/
map{y/X_/\n /;print}map{pop@$_}@/for@/
| [reply] [d/l] [select] |
|
|
|
Re: qr// with /e? (E)
by tye (Sage) on Apr 23, 2004 at 23:04 UTC
|
I like the idea. I think it could lead to confusion because it would mean that qr/foo/e will be quite different from s/foo/bar/e. But why restrict this useful idea to just qr//. Call it /E and support it on m//, qr//, and s///!
| [reply] |
Re: qr// with /e?
by davido (Cardinal) on Apr 24, 2004 at 06:14 UTC
|
The fact is that /e is only applicable to the right-hand-side of a s/// operator. In other words, you can't use /e to evaluate code on s/this side//e. It only affects s//this side/e.
qr//, builds up the RE that can be used on s/this side// of the s/// operator. Thus, just as /e has no relevance to m//, it has no relevance to qr//, nor to s/this side//.
perlretut discusses this briefly: "A modifier available specifically to search and replace is the s///e evaluation modifier. s///e wraps an eval{...} around the replacement string and the evaluated result is substituted for the matched substring. s///e is useful if you need to do a bit of computation in the process of replacing text."
You're talking, it seems, about allowing the actual RE portion to be eval{...}'ed prior to the execution of the RE. That is going to be a tough sell and my suspician is that it's going to be nearly impossible to implement correctly. After all, if you eval m/$var+1/ prior to using it as a regexp, is it "$var plus one", or is it "$var repeated one or more times, followed by a 1 character"? And should $var be interpolated prior to the eval, or after the eval but prior to the execution of the RE? Things are tricky enough when it comes to getting it right with the quoted version of eval. Imagine trying to deal with the affects of the RE quote-like operator on top of your eval!
| [reply] [d/l] [select] |
|
The fact is that /e is only applicable to
the right-hand-side of a s/// operator.
Please see my clarification(s) to my original post on
this thread. I'm quite aware of (although I was
somewhat taken aback by) the current behavior.
I was looking for others' opinions on this idea. And
I've gotten some (mostly indifferent to negative, alas).
It seems that what I really want is a way to apply
qr to an expression without having to stick
it into a variable first. Upthread someone suggested
an explicit Regex->new( EXPR ) syntax; my
response was to just use qr->( EXPR ).
(Sigh, that would break if someone used hyphens as
the non-alphanumeric delimiters...)
(This is, in my mind, a similar situation that \Q and \E
found themselves in; being able to escape metacharacters
is useful even outside of double-quoted interpolation,
so quotemeta is available as a standalone. Hm.
Maybe quoteregex is where it's at? Although
introducing a new keyword is probably not going to
happen...)
You're talking, it seems, about allowing the actual RE portion to be eval{...}'ed prior to the execution of the RE.
I realize that it could seem that way, but my request
for /e is much closer in spirit to /o
than to any of the other match modes. I would only
want the /e to apply when qr// is
compiling the expression: it would tell qr
that the text inside the brackets should be
evaled to return a string, as opposed to
interpreting the text between the brackets as a value
to be double-quote interpolated to return a string.
(This is why it seems to resonate with s///e,
as the modifier is saying exactly the same thing about
the replacement text.)
Anyway. It's absolutely not necessary, I was just
curious what other people thought of the idea. Thanks
for your feedback!
| [reply] |
|
I'm starting to gain a better understanding of your point. But just remember this: According to the "Gory details of parsing quoted constructs", the following steps take place:
- Finding the end. (Compiletime)
- Removal of backslashes before delimiters. (Compiletime)
- Interpolation. (Compiletime)
- Interpolation of Regular Expressions. (Runtime)
- Optimization of RE Code (Runtime)
My question is how would you suggest /e be implemented: Before step 3, or after it? I don't know the answer to this, and I'm not sure what the ramifications would be. Currently the quoted version of eval interpolates variables in step 3, and that's why you sometimes have to escape variable names to delay their evaluation until execution time. It seems that it's destined to be a convoluted road to travel.
| [reply] |
|
Re: qr// with /e?
by Fletch (Bishop) on Apr 24, 2004 at 01:17 UTC
|
I'd be more for a Regexp->new( ... ) which stringifies its argument and then does the qr//. None of the other of the quotelike operators (q// et al) have suffixes so it doesn't seem regular (although it would be orhtogonal to the usage with s///).
Update: Ooh, good point davido. Of course one might say that the trailing flags are really just syntactic sugar for embedded flags a la qr/(?imosx:...)/.
| [reply] [d/l] [select] |
|
"None of the other quotelike operators (q// et al) have suffixes so it doesn't seem regular..."
But qr// already does have other suffixes. See perlop under "Regex Quote Like Operators". qr// allows for qr//imosx. So the reason for not adding /e can't be because other quote-like operators don't have modifiers. The main reason is that it doesn't make sense since /e only causes an eval{} block to wrap around the right-hand portion of a s/// operator, and qr// doesn't construct that right-hand portion in the first place.
tie probably had it; don't call it /e. Call it /E or something else to avoid confusion with the longstanding function of the /e modifier.
| [reply] |
|
| [reply] |
Re: qr// with /e?
by duff (Parson) on Apr 23, 2004 at 22:53 UTC
|
| [reply] |
Re: qr// with /e?
by Anomynous Monk (Scribe) on Apr 25, 2004 at 04:59 UTC
|
I can think of a couple ways to do that now:
$re = qr/${\do{join '|', @days}}/
(as you would interpolate any expression in to any double-quotish construct), or
$re = qr/(??{join '|', @days})/
which only evaluates the code when the regex is actually
executing (and indeed may evaluate it more than once if
backtracked over).
Both forms may have problems with finding the end of the code given e.g. an unmatched } within the code; the latter
currently has unfortunate interaction with lexical vars. | [reply] [d/l] [select] |
|
|