Pathologically Eclectic Rubbish Lister | |
PerlMonks |
Calling an overload::Methodby hv (Prior) |
on Feb 03, 2022 at 18:43 UTC ( [id://11141116]=perlmeditation: print w/replies, xml ) | Need Help?? |
You probably won't need to know this, but here it is just in case you do. I stumbled across it while trying to add some speedups to Math-GMP, which uncovered a bug in Test-Builder; a cpangrep then found 5 other distributions trying to do the same thing, all of which also had the same bug (as well as a few that simply bundle Test::Builder). If you use overload to make your objects behave specially - as Math::GMP does, to make the objects act more like perl's numeric scalars - you provide those behaviours by way of a hash keyed on the (occasionally cryptic) name of the behaviour, providing a coderef or a function name:
That $swap is there to handle asymmetric operations like subtraction: if the caller asks for $super - 12 perl will call that coderef with ($super, 12, 0) as parameters, but if they ask for 34 - $super perl will instead pass ($super, 34, 1) to say that the parameters have been swapped. Now for simplicity perl always calls these overload functions the same way, even for unary operators:
$other and $swap are still passed in when calling this method (as undef and 0), but of course everyone ignores them and writes the function above as if it took only one parameter. And that's all fine until you want to use XS to provide the overloaded method - at the C level you can't just ignore arguments you don't care about, you have to supply a signature that matches how it is called. So you have to write something like this:
.. and that's all fine too - XS writers expect to have to do things in slightly more convoluted ways. However, back in the land of Perl, the overload module also provides a Method function which allows you to ask for the coderef that _would_ be called for a particular overloaded operation. You might use that to check if it's safe to use something as a string, for example:
However you might also use it to invoke that method yourself, and this is the thing that everyone got wrong:
If you invoke the coderef returned by overload::Method without supplying 3 arguments, that may work fine as long as you only interact with objects whose overloads are provided by perl code, but trying to invoke an XS method that way will fall over at runtime with a message like Usage: My::SuperNumber::as_string(left, right, swap) - because they _had_ to write it with that signature to let perl call it. And since use of XS is fairly rare and use of overload is even more so, it may be a long time before you discover there's a bug. So don't do that. :)
Back to
Meditations
|
|