Re: overloading '0+'
by CountZero (Bishop) on Sep 02, 2007 at 22:10 UTC
|
The documentation of the module overload says:
# Transcendental functions
"atan2", "cos", "sin", "exp", "abs", "log", "sqrt", "int"
If abs is unavailable, it can be autogenerated using methods for "<" or "<=>" combined with either unary minus or subtraction.
Note that traditionally the Perl function int rounds to 0, thus for floating-point-like types one should follow the same semantic. If int is unavailable, it can be autogenerated using the overloading of 0+.
# Boolean, string and numeric conversion
'bool', '""', '0+',
If one or two of these operations are not overloaded, the remaining ones can be used instead. bool is used in the flow control operators (like while) and for the ternary ?: operation. These functions can return any arbitrary Perl value. If the corresponding operation for this value is overloaded too, that operation will be called again with this value.
As a special case if the overload returns the object itself then it will be used directly. An overloaded conversion returning the object is probably a bug, because you're likely to get something that looks like YourPackage=HASH(0x8172b34).
Overloading '0+' is really overloading numification. So everytime you use $soldier1 in a context where it is used as a number, you call truncate and since as per the docs, int is autogenerated out of '0+' (unless you provide for its own routine), you get to call truncate twice: once to numify $soldier1 and once to take the integer value.You therefore really should provide a separate definition for the numification (returning the SERIAL number) and then "overload" int
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] [select] |
|
So if we add function to handle the conversion to an integer there should be one call to truncate and other call to the overload integer function.
#!/usr/bin/env perl
#
use strict;
use warnings;
package Soldier;
use overload '0+' => \&truncate,
'int' => \&my_int;
my $soldier1 = { NAME => 'BENJAMIN',
RANK => 'PRIVATE',
SERIAL => 151.11 };
bless $soldier1;
print int($soldier1), "\n";
sub truncate {
print "sub truncate called: ", $_[0]->{SERIAL}, "\n";
return $_[0]->{SERIAL};
}
sub my_int {
print "sub my_int called: ", $_[0]->{SERIAL}, "\n";
return int($_[0]->{SERIAL});
}
Produces the (unexpected) output;
sub my_int called: 151.11
151
Thoughts? | [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Thanks for all of the replies, guys.
I had read the documentation (numerous times) but found it difficult to understand.
Overloading '0+' is really overloading numification. So everytime you use $soldier1 in a context where it is used as a number, you call truncate ...
That's the bit I was failing to understand. Things now start to fall into place.
If I understand correctly, there's really no advantage in overloading '0+' unless one has a single subroutine that caters for a variety of overloadable numeric operations ?
Cheers, Rob
| [reply] |
Re: overloading '0+'
by blokhead (Monsignor) on Sep 02, 2007 at 21:23 UTC
|
I don't know the answer to your first question.. But in general, the answer to your other questions is that when perl evaluates an overloaded object in some context (numeric, boolean, string, etc), or as an argument to certain core functions (abs, int, log, sqrt, etc), and there is no specific method for that context, it will "fall back" to other methods in order to find a reasonable value (see perldoc overload).
In the first example, there is no overload method defined for the int function. However, you have defined one for numeric context. So perl is smart enough to use that and pass the resulting number to the builtin int.
In the second example, you evaluate the object in boolean context, but no boolean overload method is defined. Perl has a standard way to evaluate numbers in boolean context, so it calls your numeric context method, and interprets the result as a boolean in the normal perl way.
Most of the time you want an overloaded object to be "consistent" with perl scalars in how they are evaluated in different contexts.
So overload.pm is nice and lets you define the minimal number of overloaded methods, and the rest is handled automatically, following perl's rules for regular scalars.
| [reply] [d/l] [select] |
Re: overloading '0+'
by bruceb3 (Pilgrim) on Sep 02, 2007 at 21:24 UTC
|
0+ is used whenever the variable is used as a number. 0+ is the conversion to a number not just to an integer. So in the line;
my $int = int($soldier1);
The call to int is one call to truncate and then the assignment is the other.
If you don't have bool overloaded and 0+ is overloaded then, 0+ will be used in a boolean context, which is why truncate is being called in this code;
$soldier ? 1: 0;
See overload for the all the gory details. (perldoc overload) The sections titled "Boolean, string and numeric conversion" and "Transcendental functions" answer your questions. | [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Your right. My bad. How about this for an explanation;
The argument to int is evaluated in numeric context, which calls truncate. Then when there isn't an overload for int, 0+ is used, which calls truncate again ???
| [reply] |