Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Re^2: How does Math::GMP overload the assignment operator ?

by syphilis (Bishop)
on Nov 08, 2020 at 05:59 UTC ( #11123482=note: print w/replies, xml ) Need Help??

in reply to Re: How does Math::GMP overload the assignment operator ?
in thread How does Math::GMP overload the assignment operator ?

The + overload constructs a new object. Perl uses that overload, and then overwrites the stored value. This means every += op creates a new object

Thanks for the explanation - helps me understand what's going on, and also helps me understand the overload documentation.
Not that it needed to be checked, but with the help of Devel::Peek::Dump() I was able to verify that, with Math::GMP, the address of the object does indeed change with every +=
And I was also able to verify that the same is not true of Math::GMPz.

I find this overloading of '=' to be a bit of a headache, in that it provides a lot more rope than I would like.
WRT Math::GMP, if you have a Math::GMP object ($x) to which you wish to add, say, 4 then there's 2 ways you can do that:
$x += 4; or $x->add_ui_gmp(4);
They both do the same thing in that they increase the value held in $x by 4.
But they don't do the same thing if they were preceded by $x = $orig; where $orig is a Math::GMP object:
$x = $orig; $x += 4; # $orig remains unchanged # $x has been incremented by 4
$x = $orig; $x->add_ui_gmp(4); # Both $x and $orig have # been incremented by 4
AFAIK, the same sort of trap occurs in every math module that overloads '=', including my own Math modules, along with Math::BigInt and Math::BigFloat. (This is not limited to Math::GMP, and I'm not singling it out.)
Although it doesn't really fit with the title I've given this thread, a second question is "Should the documentation of the module (eg Math::GMP) draw attention to this trap ?".
Or is it acceptable to say nothing and put the onus of dodging the trap upon the user ?

BTW, this all started with this Math::MPFR bug report, which is about this same trap in a different module. I keep changing my mind about what, if anything, should be done ....


Replies are listed 'Best First'.
Re^3: How does Math::GMP overload the assignment operator ?
by LanX (Sage) on Nov 08, 2020 at 10:43 UTC
    > I find this overloading of = to be a bit of a headache,

    Me too. For the same reasons

    1. it's a misnomer because not overloading assignment but only a special Copy-On-Write behavior. (you need tied variables to control assignment)
    2. it assumes that copying on assignment is the DWIM behavior, but only when one of the values is changing. I for my part would be very surprised. an explicit ->clone method (or operator?) might have been the better choice.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      There's no denying that being able to do $clone = $orig is very convenient if you both understand the limitations, and make sure you work around them.
      It's quicker to type, and also easier to remember, than $clone = $orig->gmp_copy()
      But, as an author who has enabled this convenience in his modules, is it acceptable that I don't document the traps that users might fall into when they avail themselves of this option ?

      With Math::GMP (which I've neither authored or maintained), I initially considered it smart of them to not explicitly overload '=', and to also not mention that this option exists.
      I thought that, in doing this, they were taking advantage of the fact that there's no onus upon them to document anything at all about this option.
      And I also thought that I might take the same path with my modules.
      However, I'm no longer so sure about the validity of that thinking - and I think, in my modules, I will make some brief mention of the traps, along with a recommendation to read the overload documentation carefully.

      It occurs to me that, if one wanted to code defensively, doing $clone = $orig + 0 is safer than doing $clone = $orig.


        The real solution to this is to make your objects immutable. Don't provide any methods that change the value of your object, and instead return new objects. You could then remove your += and similar overloads and = overload, and just rely on creating new objects from your + overload.

        It would actually be possible to still provide the += overload as an optimization if you were providing the = overload. Since the only way to trigger mutation of the object would be via the overload, perl would protect you from ever modifying a shared object by cloning using the = overload. I'm not sure that the extra complexity here would really be worth it.

      Operator overloading make objects behave like primitive types, and you wouldn't use 3->clone() or "abc"->clone()

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11123482]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (7)
As of 2021-10-25 10:28 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (89 votes). Check out past polls.