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

It definitely doesn't look right that you're doing
dXSARGS; /* ... */ XSRETURN(1);
in your alleged C function, which should either mutate things and let the XS function do all the Perl stack stuff, or return a value but strictly in C-land.

Replies are listed 'Best First'.
Re^9: Puzzled by value of $overload::ops{binary}
by syphilis (Archbishop) on Jun 27, 2024 at 02:30 UTC
    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
      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