in reply to Re^8: Puzzled by value of $overload::ops{binary}
in thread Puzzled by value of $overload::ops{binary}

I think that the overloading procedure views '+=' as an assignment operation ($x = $x + $addon), not as an inplace mutation ($x += $addon).
The former requires a value to be returned; the latter does not.
At least, it's behaving as though that's the case.

That's why that documentation snippet I posted goes on to say:
The subroutine for the assignment variant of an operator is required only to return the result of the operation. It is permitted to change the value of its operand (this is safe be +cause Perl calls the copy constructor first), but this is optional +since Perl assigns the returned value to the left-hand operand anyw +ay.
Note that it's specifically stating that it's "permitted" (but not mandatory) "to change the value of its operand ".
If it was being deemed to be an inplace mutation, then it would have to change the value of its operand.

AFAICS, there aren't many modules that overload '+=', but Math::BigFloat does:
'+=' => sub { $_[0] -> badd($_[1]); },
which I manually altered to:
'+=' => sub { $_[0] -> badd($_[1]); 42 },
I then get:
D:\>perl -MDevel::Peek -MMath::BigFloat -le "$x = Math::BigFloat->new( +20); $x += 100; print $x; Dump $x;" 42 SV = PVIV(0x1bc99137430) at 0x1bc9913a450 REFCNT = 1 FLAGS = (IOK,pIOK,pPOK) IV = 42 PV = 0x1bc9b44fbe0 "42"\0 CUR = 2 LEN = 16
In that pure perl environment it's clearly the returned result, not the result of the inplace addition, that's being seen.

I'm now feeling more confident that the need for '+=' overloading to return the new value is intended (though unexpected) behaviour.

Cheers,
Rob

Replies are listed 'Best First'.
Re^10: Puzzled by value of $overload::ops{binary}
by etj (Priest) on Jun 27, 2024 at 10:01 UTC
    Glad to hear it works properly when you do what the documentation says is necessary.

    I was talking about the division of labour between your XS function, which quite rightly does Perl-stack and SV stuff, and your C function, which also does both but is wrong to do so. I am saying you should either incorporate the C function into the XS function entirely, or make the C function operate only on C values, and return those to the XS function to use for Perl stuff.

      I was talking about the division of labour between your XS function, which quite rightly does Perl-stack and SV stuff, and your C function, which also does both but is wrong to do so.

      Generally, I just write the C functions and then let Inline::C generate the XS file - though I have strayed from that practice in the hacks that I've presented in this thread.
      This means that (generally speaking) all required functionality has to be written into the C functions, and it's a practice that has served me well.
      If there's something wrong with that, then I take your point - and I certainly make no argument against that view.

      However, at this stage of the game, it's quite possible that I won't get around to doing anything about it.

      Cheers,
      Rob
        If you end up with something that works, that's a good thing. My thinking is that the direction I'm suggesting above is extremely clearly good practice, and there's a reason that good practice is considered desirable: it avoids errors and/or unnecessary maintenance work.

        If the C functions you wrote and then let Inline::C do its stuff with take/return SVs, I'd suggest that's a category error, and they should instead take/return mpz_t values (or pointers thereto). With the right typemap entries, you could just write XS functions that take/return mpz_t values, and omit the Inline::C stuff, which isn't as necessary as you might think, once you have all the typemap, CODE: and OUTPUT: stuff working, which you evidently do.

        Having had a very quick look at https://github.com/sisyphus/math-gmpz/blob/master/typemap, is there a reason all those identical "types" aren't just the one? If you gave an OUTPUT clause as well, that would significantly facilitate the idea above. PDL's typemap can be used as a quite good template.