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

Dear Monks,

my question today is of utter importance for my project. Probably the answer to it will be "you'll have to code it yourself". That'll be ok for me, but I hope I understand all aspects of the problem before I do so. Hence my question:

The Set::Scalar module provides nifty set-functionality. One of the methods is has which returns true if a given element (you give it as a parameter to that method) is member of the set.

my $s = Set::Scalar->new('a','b','c(d)'); print $s->has('a'); # returns true
The functionality I desperatedly need would be:
my $s = Set::Scalar->new('a','b','c(d)'); if($s->has(/c\((.+)\)/)) { print $1; # prints 'd' }
My concrete questions are: I owe you much.

Bye
 PetaMem

Replies are listed 'Best First'.
Re: Set::Scalar - Regexp as method parameter?
by broquaint (Abbot) on Apr 27, 2002 at 17:47 UTC
    You could overload the has method (which is actually in Set::Scalar::Base), or just add something similar to it like so
    use Set::Scalar; sub Set::Scalar::Base::has_re { my $self = shift; my @has; foreach my $el (keys %{$self->{'elements'}}) { push @has, $el =~ /$_/ for @_; } return wantarray ? @has : "@has"; } my $s = Set::Scalar->new('a','b','c(d)'); if(my $sub_el = $s->has_re(qr/c\((.+)\)/)) { print "found it $sub_el\n"; } __output__ found it d
    That's not the greatest example of well-tested code but I'm sure you get the idea. Also make sure you quote your regexes or you won't get what you expect (the qr// operator is your friend!).
    HTH

    _________
    broquaint

Re: Set::Scalar - Regexp as method parameter?
by Kanji (Parson) on Apr 27, 2002 at 17:56 UTC
    Does this already work [...] ?

    Taking a peek at the source, apparently not, so you'd need to augment has with your own functionality, either be redefining it directly or via a subclass.

    [...] and I'm doing something wrong to achieve my goal ?

    Trying to pass a bare regex isn't going to work, as you'll end up passing it's return value against (in your example anyway) whatever $_ is before you even get to the sub.

    Instead, you should use qr (my personal preference) or pass the string you want to use (ie, the regex minus the enclosing //'s) so that the regex gets evaluated when you really want it to: inside the function/method...

    foo( qr/ba[rz]|quux/ ); foo( 'ba[rz]|quux' ); sub foo { my $regex = shift; # //'s not necessary if $regex # was built with qr. return grep /$regex/ => @foo; }
    [...] How to alternatively implement that?

    Depending on your needs, you might be able to use Quantum::Superpositions' any function...

    any(@set) =~ /c\((.+)\)/;

    ... although I note I couldn't get it working with Q::S's all, so be sure to test for yourself.

        --k.


      //'s not necessary if $regex was built with qr.

      Actually, if you leave out the slashes, the regex is put in string context, and the speed gain is lost.

      $foo =~ '^string literal$'; # Does not equal /\Q^string literal$/ $foo =~ $string; $foo =~ subroutine(); $foo =~ bareword; # Unless $INC{'strict.pm'} $foo =~ $precompiled_regex; # Is stringified first! $foo =~ /$precompiled_regex/; # Faster
      I've even seen people do bizarre things because they think qr//s are faster without slashes:
      # Bad: (well, it works, but not the way you want it to) $foo =~ $qr; $foo =~ s//bar/; # Good: $foo =~ s/$qr/bar/;

      - Yes, I reinvent wheels.
      - Spam: Visit eurotraQ.
      

Re: Set::Scalar - Regexp as method parameter?
by 2shortplanks (Initiate) on Apr 30, 2002 at 09:48 UTC
    Have you considered using Quantum::Superposition?

    This module will allow a scalar to be many values at the same time (i.e. a set of values) and you can perform matches on it that will return true if any or all (depending on the config) of the values that scalar represents match

    Just an idea - obviously how useful this will be will depend on the rest of programs.