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

I'm curious how hard would it be to hack perl so =~ operator would be overload(.pm)able ... I noticed that ~~ is overloadable in 5.9.4, but that's not quite what I want. I can try to hack it myself, however, before boing so, I though I'd ask here, probably it was done before or on the contrary cannot be done without major blood loss. What I want is basically this:

$my_object_of_class_A =~ $my_object_of_class_B

or

$my_object_of_class_A =~ qclassB/$string/

where

sub qclassB { My::Class::B->new(@_) }

and something like

use overload '=~' => \&match_class_a_to_class_b;

any ideas?

Replies are listed 'Best First'.
Re: overload =~ operator
by diotalevi (Canon) on Sep 27, 2006 at 13:04 UTC

    =~ is not overloadable in bleadperl either. Perhaps you thought of ~~ which is. As for adding it, why not just look at the diff that Robin submitted?

    [Added: See also Robin's Hacking perl.]

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: overload =~ operator
by madbombX (Hermit) on Sep 27, 2006 at 16:21 UTC
    I'm not sure if this is what you are looking for, but there is a perl module Class::Comparable where a base class is created for comparable objects. In the same respect, it overloads operators to achieve it goal. Your question was very generic, so this module may or may not apply.

    Another possibility is, depending on the structure of your objects (or classes), you can use List::Compare, Array::Compare, etc, and make methods for comparing different parts of your objects (or classes). This allows you more control over the comparisons and allows them to be more granular should you have the need to dig deeper to see where the differences are.

    Eric

Re: overload =~ operator
by ambrus (Abbot) on Sep 28, 2006 at 12:17 UTC

    As far as I know, you can't introduce a new quotelike operator akin to your example

    $my_object_of_class_A =~ qclassB/$string/
    only redefine the meanings of existing ones or create your objects with an explicit function/method call.

    I think, however, within some limits, you can create an object you can apply to a string with the =~ operator but behaives in a custom way. For this, you have to use the /(?{})/ regexp feature. The code inside this construct can access the matched string from the $^N provided you put a /\A(?=.*\z)/s capture before the construct that captures the entire string. Then, the code can do whatever computations with the string to decide if it wants to return a match or a non-match.

    Here's a simple proof-of-concept example.

    use warnings; use strict; sub len_3mult { my($s) = @_; 0 == length($s) % 3; } my $len_3mult = qr/\A(.*)\z(?(?{ len_3mult($^N) })|(?!))/s; for my $s (qw"my his your their socket connect protocol terminate") { if ($s =~ /$len_3mult/) { print "<<$s>> matches\n"; + } else { print "<<$s>> does not match\n" } }

    As you can see, the regexp $len_3mult matches only if the length of the string is a multiply of three or more characters. You could replace this condition with arbitary perl code.

    I don't know if you can return arbitary captures ($1, $2, ..., @-, @+) from such a regexp.

Re: overload =~ operator
by chromatic (Archbishop) on Sep 27, 2006 at 21:34 UTC

    Perhaps you might have more luck with Class::Trait. I realize this has nothing to do with regular expressions, but if you're trying to solve the problem I think you're trying to solve, try this.

    If that's not the problem you're trying to solve, please clarify.

      Eh well, it seems that I shouldn't have mentioned the word 'class' at all, because the problem I'm trying to solve has little to do with classes: I've implemented a very simple two-dimensional regex engine, which can now be called with the ugly syntax

      match2('\v1(\h2(\v3(\h4)))', ['13', '24'])

      but I want it to look like

      ['13','24'] =~ m2/\v1(\h2(\v3(\h4)))/

      sure I could wait until 5.10 and the use feature ~~ but I'd rather overload =~ now.

Re: overload =~ operator
by MonkE (Hermit) on Sep 27, 2006 at 12:58 UTC
    I know this doesn't answer your question, but a more concrete example showing what form you envision class B taking would be helpful to anyone who might answer.
      Not necessarily a class, just overloading a binary operator like '+' or '*' would be fine. For example, it's easy to write

      use overload '+' => sub { Class->new($_[1])-> add($_[0]) };

      but impossible to

      use overload '=~' => sub { Class->new($_[1])-> match($_[0]) };

      ... and of course, I want my own implementation of match() here, unrelated to perl5 regexes.

Re: overload =~ operator
by demerphq (Chancellor) on Oct 11, 2006 at 23:31 UTC

    Perls regex engine is very closely bonded to the perl internals, so writing a plug in replacement isnt going to be easy. However, as of Perl 5.9.5 it should be much easier, as the framework has been totally changed. In earlier versions of perl the swap of regex engines was interpreter wide, which meant that patterns compiled with one engine could and would be handed over to another for processing. As long as the engine being plugged in was just a "debug" build of the original this didnt lead to problems, but if you were to plug in a set of empty handlers all hell would break loose.

    The new interface involves binding the internal structures with a dispatch table so that regexp's are executed using the same engine as they were compiled with. As abyproduct the use re 'debug'; pragma is now properly lexically scoped.

    So the short of it is, its not easy to do, and requires advanced C/perl internals skills. However, in comparison to earlier perls it is actually possible.

    One of my personal ambitions for 5.10 is to include a module that implements a plug in of another regex library. I dont know if ill acomplish it, but it is something id like to do.

    ---
    $world=~s/war/peace/g