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

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

Math::GMPz (without the = overload) does have a += overload. This modifies the object. If there is more than one reference to the object, they all get modified. If you implement the = overload, perl notices that there are multiple references and uses the = overload to clone the object, before modifying it with the += overload. This means that += will only create a new object if there are multiple references to the object.

  • Comment on Re: How does Math::GMP overload the assignment operator ?

Replies are listed 'Best First'.
Re^2: How does Math::GMP overload the assignment operator ?
by syphilis (Bishop) on Nov 08, 2020 at 05:59 UTC
    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 ....

      > 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.


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