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

I wonder if anyone can shed some light on this issue. I have an object that behaves as a regular expression. As I toy with overload strategies, I have stumbled up against a wall. Consider the following package definition:

package Foo; use strict; use overload '""' => \&interp; sub new { my $class = shift; bless { str => $_[0], re => qr/^$_[0]$/, }, $class; } sub as_string { $_[0]->{str}; } sub re { $_[0]->{re}; } sub interp { my $self = shift; my $condition = 1; # 1 if called in qr{} context # 0 otherwise $condition ? $self->re : $self->as_string; } 1;

You might use the above package in the following way:

use Foo; my $r = Foo->new( '[aeiou]+\\d+' ); my $super_re = qr/[A-Z]+$r/; print <<OUT; r = /$r/ super = /$super_re/ OUT for( @ARGV ) { my $match = ($_ =~ /$r/) ? 1 : 0; print "$_ match=$match\n"; }

That may sound a little insane, that's the trouble with a contrived example, but the gist is this: I have an object that contains a compiled regular expression as an attribute, and sometimes I'd like to be able to return the compiled expression, and other times the original text. And, most of all, make perl make the right choice as to when.

So, if the object is interpolated in a qr{} context, the idea is to return the underlying string that was used for the RE, so that it can be included into a larger RE built in the client code (e.g. building the $super_re pattern. Otherwise, if it's used in another context (e.g. /$r/ in the loop), then it should return the compiled regular expression).

As a result, I would like to see

r = /(?-xism:^[aeiou]+\d+$)/ super = /(?-xism:[A-Z]+[aeiou]+\d+)/

but of course it gives

r = /(?-xism:^[aeiou]+\d+$)/ super = /(?-xism:[A-Z]+(?-xism:^[aeiou]+\d+$))/

I'm not sure if there's a use for it (I'm thinking more along the lines of +imsx modifiers rather than outright additions to the RE in Foo::new), but it might come in handy. I thought about caller, but these sorts of shenanigans are invisible to it.

- another intruder with the mooring of the heart of the Perl

Replies are listed 'Best First'.
Re: Distinguishing between // and qr{} interpolation
by demerphq (Chancellor) on Nov 08, 2004 at 19:11 UTC

    Have a look at Data::Dump::Streamer where there is a function called (unimaginatively) 'regex'. The function works as follows:

    #!perl -l use Data::Dump::Streamer qw(:util); for ('(foo)',qr/(foo)/, qr/bar/x,bless qr/baz/i,'ARRAY') { print "Got: /$_/"; print "list regex() =\t",join "\t/\t",regex $_; print "scalar regex() =\t",scalar regex $_; print ""; } __END__ Got: /(foo)/ list regex() = scalar regex() = Got: /(?-xism:(foo))/ list regex() = (foo) / scalar regex() = (?-xism:(foo)) Got: /(?x-ism:bar)/ list regex() = bar / x scalar regex() = (?x-ism:bar) Got: /ARRAY=SCALAR(0x1acf014)/ list regex() = baz / i scalar regex() = (?-xism:baz)

    That last one is the main reason this subroutine exists, but it also solves the problem of getting the pattern the user provided back instead of the wrapped one that normally is returned (this way you can have both).

    Anyway, I hope this is useful to you, it seemed like it might be.

    ---
    demerphq

Re: Distinguishing between // and qr{} interpolation
by diotalevi (Canon) on Nov 08, 2004 at 18:32 UTC

    qr// interpolation is regular string interpolation. They use the same operation internally and you have to alter the compiled program's optree to change this.

    Make your rx/string decision at compile-time and you have to alter your program's optree so every regular string concatenation is replaced with a function which will handle your objects in a special way and everything else in a normal way. That is, every instance of concat that is not also matched by regcomp/regcreset/concat should be replaced with concat/entersub/etc.

    Please bear in mind that if you alter your +imsx modifiiers that you must discard the compiled regex and compile it again with the new flags.

Re: Distinguishing between // and qr{} interpolation
by dragonchild (Archbishop) on Nov 08, 2004 at 18:40 UTC
    What about not compiling your regexes? Granted, you don't get the speed boost, but Rule#1 is "Does your program work correctly?" ...

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.