http://qs321.pair.com?node_id=180336

in reply to A better mod (%) operator?

I almost have a working example with overload, but i can't get it to work - wantarray is being fussy with me. The problem with overload though, is that you cannot define some new token such as /% - you have to use an existing one. This should get you started, but like i said, it doesn't work. I have provided a subroutine at the bottom that does work, i would appreciate it if someone could tell me what i did wrong. I chose * as the overloaded operator just to show that the overload sub is being called, i originally used %
```package mod;
use strict;

use overload '*' => sub {
my \$div = int(\${\$_[0]} / \${\$_[1]});
my \$mod = \${\$_[0]} % \${\$_[1]};
return wantarray ? (\$div,\$mod) : \$mod;
};

sub new {
my (\$class,\$val) = @_;
return bless \\$val, \$class;
}

package main;
use strict;

my \$i = mod->new(90);
my \$j = mod->new(60);

my @x = \$i * \$j;
my \$x = \$i * \$j;
print "@x\n";
print "\$x\n";

my @y = mod(90,60);
my \$y = mod(90,60);
print "@y\n";
print "\$y\n";

sub mod {
my \$div = int(\$_[0] / \$_[1]);
my \$mod = \$_[0] % \$_[1];
return wantarray ? (\$div,\$mod) : \$mod;
};

__END__
yields:
30      <-- this should be 1 30
30
1 30
30

jeffa

```L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
```

Replies are listed 'Best First'.
Re: (jeffa) Re: A better mod (%) operator?
by jmcnamara (Monsignor) on Jul 08, 2002 at 23:12 UTC

A bug perhaps?

--
John.

The problem isn't with wantarry, it's something more low level then that, observe a slightly modified version that doesn't use wantarray...

```use overload '*' => sub {
my \$div = int(\${\$_[0]} / \${\$_[1]});
my \$mod = \${\$_[0]} % \${\$_[1]};
return (\$div, \$mod);
};

This still generates "30" for 90/30, regardless of context ... it's as if overloaded operators are allways called in some sort of bizarro scalar context where lists are evaluated as their last element instead of their length...

```package mod;
use strict;
use overload '*' => sub {
return ('yakko', 'wakko', 'dot');
};
sub new {
my (\$class,\$val) = @_;
return bless \\$val, \$class;
}
package main;
use strict;
my \$i = mod->new(90);
my \$j = mod->new(60);

my @x = \$i * \$j;
my \$x = \$i * \$j;
print "@x\n";
print "\$x\n";
__END__
dot
dot

Update: My bad, I totally spaced out on the fact that lists in scalar context evaluate to the last element... i was thinking of it just like an array.

The problem isn't with wantarray

I didn't mean to give the impression that I think the bug is in wantarray(). :-) I doubt that is the case. It is more likely that the overloaded sub is always called in a scalar context.

Whether this is a bug or not I cannot say. In a way it makes sense because non-overloaded arithmetic operators are unaffected by context:

```    @a = 1 + 2;
\$a = 1 + 2;

However, it would be nice if the context was seen by the overloaded operator so that code like jeffa's would work. Also, in relation to overloaded <>, which should have a scalar and list context, it does seem to be a bug.

It's as if overloaded operators are always called in some sort of bizarro scalar context where lists are evaluated as their last element

The fact that the last element is returned is consistent with the observation that the overloaded operators are always called in a scalar context since this is what happens when a list is assigned to a scalar:

```    \$x = (1,2,3);
print \$x;     # prints 3

--
John.

Re^2: A better mod (%) operator?
by particle (Vicar) on Jul 09, 2002 at 00:51 UTC
The problem with overload though, is that you cannot define some new token such as /% - you have to use an existing one.
perl 6 solves this problem. something like:

```my sub operator:%/ is prec(\&operator:%) (\$x, \$y)
{
...
}
i'll be glad i can finally add the ,= operator i've been looking for to replace push.

~Particle *accelerates*

Oooooooo....this is going to be SUCH a boon to the Perl Obfuscators :)

Kickstart

Re: (jeffa) Re: A better mod (%) operator?
by BrowserUk (Pope) on Jul 09, 2002 at 00:03 UTC

Thanks Jeffa.

It looks as if you are being bitten by an "undocumented feature" of wantarray(). Rest assured though your efforts were not wasted, this small sample has assisted my education at least.

With regard to the code. If I understand what I am seeing, the overloaded operator will only be called if the variables to which its applied have been blessed into the package in which the overloading is done by the use of new()?

I assume from this that there is no way to overload an operator such that it will operate without requiring this?

Yep, you have to have a blessed package (an object) in order for overload to work - but who says you can't bless main? ;)
```use strict;

use overload '+' => sub { \${\$_[0]} - \${\$_[1]} };
use overload '-' => sub { \${\$_[0]} + \${\$_[1]} };

my (\$x,\$y) = (90,60);
my \$i = bless \\$x, 'main';
my \$j = bless \\$y, 'main';

print \$i + \$j, \$/; # 30
print \$i - \$j, \$/; # 150

# normal scalars use Perl operators
print \$x + \$y, \$/; # 150
print \$x - \$y, \$/; # 30

jeffa

```L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
```
More operator tokens
by John M. Dlugosz (Monsignor) on Jul 09, 2002 at 20:15 UTC
Too bad Perl doesn't use a few other math symbols from Unicode as operator tokens (with no built-in meaning). I think that would be very easy to add. Often what's needed is a "different flavor" of multiplication etc., so using the circled cross etc. would be good choices, and they can have the same precidence as their ordinary cousins.

Which key would I use to type that operator in vi? :)
Try control-alt-hyperspace-meta buckyball.

FWIW, it looks like "Space Cadet" keyboards are gaining popularity. I just got a "MS Office" keyboard to replace a dead one, as it had the best quality and key-feel of any in the store.

In the superior vim :^), that would be Ctrl-V <numerical character code> (can be any of decimal, octal or hex) - see :help i_CTRL-V_digit

:-)

Makeshifts last the longest.

Maybe you could use an ascii sequence such as (*).