David W.
David W.

Reputation: 107040

How do you override substitution operations?

I'm playing around with Perl and creating a string object. I know that this is a very bad idea to do in the real world. I'm doing it purely for fun.

I'm using overload to overload standard Perl string operators with the standard operators you would find in most other languages.

use strict;
use warnings;
use feature qw(say);

my $obj_string1 = Object::String->new("foo");
my $obj_string2 = Object::String->new("bar");
my $reg_string1 = "foobar";
my $reg_string2 = "barfu";

# Object::String "stringifies" correctly inside quotes

say "$obj_string1 $obj_string2";

# Use "+" for concatenations

say $obj_string1 + $obj_string2;                # Works
say $obj_string1 + $reg_string1 + $reg_string2  # Works

say $reg_string1 + $obj_string1                 # Still works!
say $reg_string1 + $obj_string1 + $reg_string2; # Still works!
say $reg_string1 + $reg_string2 + $obj_string1; # Does't work, of course.

# Overload math booleans with their string boolean equivalents

my $forty = Object::String(40);
my $one_hundred = "100";

if ( $forty > $one_hundred ) {    # Valid
   say "$forty is bigger than $one_hundred (in strings!)";
}

if ( $one_hundred < $forty ) {    # Also Valid
   say "$one_hundred is less than $forty (In strings!)";
}

# Some standard "string" methods

say $forty->length      # Prints 5
say $forty->reverse;    # Prints "ytrof"
say $forty;             # Prints "ytrof"

Now comes the hard part:

my $string = Object::String("I am the best programmer around!");
say $string;               # Prints "I am the best programmer around"
say $string->get_value;    # Prints "I am the best programmer around" with get_value Method

# But, it's time to speak the truth...

$string =~ s/best programer/biggest liar/;
say $string;               # Prints "I am the biggest liar around"
say $string->get_value;    # Whoops, no get_value method on scalar strings

As you can see, when I do my substitution, it works correctly, but returns a regular scalar string instead of an Object::String.

I am trying to figure out how to override the substitution operation. I've looked in the Perldoc, and I've gone through various Perl books (Advance Perl Programming, Intermediate Perl Programming, Perl Cookbook, etc.), but haven't found a way to override the substitution operation, so it returns an Object::String.

How do I override the substitution operation?

Upvotes: 3

Views: 171

Answers (1)

LeoNerd
LeoNerd

Reputation: 8532

Unfortunately Perl's overload support isn't very universal in the area of strings. There's many operations that overloading isn't party to; and s/// is one of them.

I have started a module to fix this; overload::substr but as yet it's incomplete. It allows you to overload the substr() function for your object, but so far it doesn't yet have power to apply to m// or s///.

You might however, be able to use lvalue (or 4-argument) substr() on your objects as a way to cheat this; if the objects at least stringify into regular strings that can be matched upon, the substitution can be done using the substr()-rewrite trick.

Turn

$string =~ s/pattern/replacement/;

into

$string =~ m/pattern/ and substr($string, $-[0], $+[0]-$-[0]) = "replacement";

and then you'll have some code which will respect a substr() overload on the $string object, if you use my module above.

At some point of course it would be nice if overload::substr can perform that itself; I just haven't got around to writing it yet.

Upvotes: 5

Related Questions