Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

How does Math::GMP overload the assignment operator ?

by syphilis (Bishop)
on Nov 07, 2020 at 04:36 UTC ( #11123464=perlquestion: print w/replies, xml ) Need Help??

syphilis has asked for the wisdom of the Perl Monks concerning the following question:


I've read the overload documentation and I understand the basics of overloading the '=' operator.
I also understand that it's not really an overloading of the '=' operator - rather there's a process, that begins with doing $copy = $orig, whereby $copy ultimately becomes a separate copy of the Math::GMP object $orig just prior to taking on a new value.

In Math::GMP this can be demonstrated as:
use strict; use warnings; use Math::GMP; my $orig = Math::GMP->new(2); my $copy = $orig; # At this point $copy and $orig refer to # one and the same Math::GMP object. $copy += 5; # At this point, $copy refers to a newly # created Math::GMP object that holds a # value of 7; $orig still refers to the # original object, holding a value of 2. print "$orig\n"; # prints 2 print "$copy\n"; # prints 7
I have implemented the exact same thing in my Math::GMPz module - just replace all occurrences of "GMP" with "GMPz" and that little demo will behave in exactly the same way.
But now to the bit that I don't understand:

In Math::GMPz that overloading only works because, in, I've done:
use overload ... , '=' => \&overload_copy, ... ;

If I remove that key-value pair from then that particular overloading ceases to work. In that demo, both $copy and $orig will then end up referring to the very same (original) object, but with the new value of 7 - and the script crashes on termination.

OTOH, does not supply with an '=', sub{} key-value pair at all.
How come this overloading still works for Math::GMP ?


Replies are listed 'Best First'.
Re: How does Math::GMP overload the assignment operator ?
by Haarg (Curate) on Nov 07, 2020 at 13:29 UTC

    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.

      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

Re: How does Math::GMP overload the assignment operator ? (more guessing)
by LanX (Sage) on Nov 07, 2020 at 09:44 UTC
      "0+" => sub { $_[0] >= 0 ? uintify($_[0]) : intify($_[0]) },

      I don't think it's related to my particular problem, but it's an interesting case.
      Which operator is being overloaded here ? Is it overloading 'int' ?
      I actually wonder if that's a useful feature, but I won't rush to an assessment on that until I've found out a bit more about it.


        That is overloading numeric conversion.

        That sub will be called whenever an object is used in a context that expects a number.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11123464]
Approved by Athanasius
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2021-10-19 23:51 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (78 votes). Check out past polls.