I've noticed that when authors validate string values as inputs, they often check that the value is not a reference.
The problem is that it disallows objects that are overloaded to behave like strings.
It's relatively easy to check that an object behaves like a string, and I have some code for testing this (below, for your amusement).
But it's not just a matter of getting module authors to change how they check for strings, but also making it easier for module authors to "stringify" their classes so they behave like strings for comparisons and sorting.
So I have an idea for a module called "Class::Stringify" that would do the following as a base class for a module:
(1) if the class doesn't have the stringification operator overloaded, die
since it's the bare minimum
(2) if the class doesn't have the cmp operator overloaded, define it using
the stringification operator: "$a" cmp "$b"
(3) if the class doesn't have the eq, ne, le, lt, ge, gt operators overloaded,
define them using the cmp operator
There are some variations on this where a class might have lt (or gt) and eq (or ne) defined which can be used to define cmp and the others. And I'm guessing that with some thought I could come up with a smart way to define the operations that need to be defined.
The rationale for such a module is to (1) encourage authors to test things for "stringiness" rather than assume a string is not a reference when strings are required, so that their software becomes much more powerful and (2) assist other authors to make their objects behave like strings where appropriate.
Obvious questions: (1) Is there such a module already? I'd rather not waste my time.... (2) Better namespace? (3) Comments/criticisms/suggestions?
Reference: some code for testing if an argument is string-like:
sub is_string_like { return 1,
unless (defined $_[0] && ref $_[0]);# We don't evaluate whether the "." and ".=" operators are # supported, since for many applications that use strings, the # comparison operators are the most important.
eval {
("$_[0]")
&& (($_[0] cmp $_[0])==0)
&& ($_[0] eq $_[0])
&& (!($_[0] ne $_[0]))
&& (!($_[0] le $_[0]))
&& (!($_[0] ge $_[0]))
&& (!($_[0] lt $_[0]))
&& (!($_[0] gt $_[0]))
} and return 1;# Testing for behavior related to copy constructors is another issue # to be determined....
return; }
