perl - universal operator overload

Tag: perl , overloading , operator-keyword Author: lilitower Date: 2011-10-31

I have an idea for perl, and I'm trying to figure out the best way to implement it.

The idea is to have new versions of every operator which consider the undefined value as the identity of that operation. For example:

$a = undef + 5;     # undef treated as 0, so $a = 5
$a = undef . "foo"; # undef treated as '', so $a = foo
$a = undef && 1;    # undef treated as false, $a = true

and so forth.

ideally, this would be in the language as a pragma, or something.

use operators::awesome;

However, I would be satisfied if I could implement this special logic myself, and then invoke it where needed:

use My::Operators;

The problem is that if I say "use overload" inside My::Operators only affects objects blessed into My::Operators.

So the question is: is there a way (with "use overoad" or otherwise) to do a "universal operator overload" - which would be called for all operations, not just operations on blessed scalars.

If not - who thinks this would be a great idea !? It would save me a TON of this kind of code

if($object && $object{value} && $object{value} == 15)

replace with

if($object{value} == 15)  ## the special "is-equal-to" operator
This pragma already exists. It is called no warnings;
I`m assuming you meant to say $object->{value} instead of $object{value}.

Other Answer1

It is possible. It would take a lot of work, but you could write an "op checker" that replaces the ops for && with custom op that's your reimplementation of &&.

But it would be a very bad idea. For starters,

if ($a && $b) {
   ...
}

would stop being equivalent to

if ($a) {
   if ($b) {
      ...
   }
}

To take your own example,

if ($object && $object{value} && $object{value} == 15) {
   ...
}

With your requested model, it would have to be written

if ($object{value}) { if ($object{value} == 15) {
   ...
}}

You actually want the exact opposite of what you asked for. You actually want the current behaviour. Without your module, you can write:

if ($object{value} && $object{value} == 15) {
   ...
}

or

no warnings 'uninitialized';
if ($object{value} == 15) {
   ...
}

or

if (($object{value} // 0) == 15) {
   ...
}

comments:

you're right that no warnings 'uninitialized' does MOST of what I'm talking about. Care to give some more details about the "custom op checker" idea though? I don't know how perl allows you to hook operators between, say, two literal numbers.
@Todd Freed, The op checker visits every op, and can replace them with others. This is how autovivification (the module) works.
the autovivification module appears to be implemented entirely in xs. So I guess you can't overload operators in this sense in pure-perl?
@Todd Freed, "Pure Perl" just means you're using someone else's XS, so you're asking if someone has exposed all the necessary parts of the API to the Perl symbol table. I don't know. Why are you still trying to fill this insane goal of yours when all it does it make the code you have to write more complicated?
You claim this is possible but you won't say HOW. Let me boil it down for you. "my $a = 5 + 5" how do you overload the plus operator in this case? I do not believe 'use overload' can do it. I want to know because I want to know, not necessarily because I intend to rewrite any code to use this.

Other Answer2

As mob said, your pragma already exists. It's spelled no warnings 'uninitialized';. Perl already treats undef as either 0 or the empty string (depending on context). This just suppresses the warning you usually get (assuming you have warnings turned on, which you should).

If you want to create a package that does this automatically, you can:

package operators::awesome;

use strict;
use warnings;

sub import {
  warnings->unimport('uninitialized');
}

Now use operators::awesome; will turn off warnings about uninitialized values.

Here's a fancier version of import that turns on strict and warnings, but turns off warnings about uninitialized values:

sub import {
  strict->import;
  warnings->import;
  warnings->unimport('uninitialized');
}

comments:

How is this different from just using no warnings 'uninitialized'?
@TLP, it isn't. I was just pointing out that you can write a package that does the equivalent of no warnings 'uninitialized' for you. It can also do other things, like turn on strict and other warnings. It could even export functions if you want, although that would be more complicated.
Fails for $a = undef && 1;
@ikegami, I just noticed his description is inconsistent. He says "undef treated as false, $a = true", but false && true is false, not true.

Other Answer3

All of those operations already work the way you expect them to:

  • In the context of numbers, undef is 0.
  • In the context of strings, undef is the empty string ''.
  • In the context of booleans, undef is 0.

If you use warnings, then perl will let you know that the value is uninitialized, but it will still work just fine.

comments:

short, and to the point. Thanks! I should've thought of this.