in reply to Puzzled by value of $overload::ops{binary}

but the last 6 operators (ie the ones containing a ".") are not something I'm familiar with

Uhm, good question. Can't remember seeing these in the wild before. But when dealing with objects, you nearly always have to write your own operators overloads.


And now for some fun:

Or is it just something that I can use to do whatever I want ?

As with pretty much every other thing involving the perl parser, the answer is a resounding yes. Mostly thanks to XS and source code filters, the perl interpreter is not limited to a single programming language, syntax, basic concept or even probably the somewhat limited charset available in Unicode. Only your imagination is the limit. The following may or may not be stuff that the Perl core devs intended, but which nevertheless is possible:

#!/usr/bin/env perl use Acme::Brainfuck; print "Just another "; ++++++[>++++++++++++++++<-]> ++.-- >+++[<++++++>-]<.>[-]+++[<------>-]< +.- +++++++++.--------- ++++++++++++++.-------------- ++++++.------ >+++[<+++++++>-]<.>[-]+++[<------->-]< +++.--- +++++++++++.----------- print " hacker.\n";

use JavaScript::Embedded; ## create new js context my $js = JavaScript::Embedded->new(); # set function to be used from javascript land $js->set('write' => sub { print $_[0], "\n"; }); $js->eval(qq{ (function(){ for (var i = 0; i < 100; i++){ write(i); } })(); });

use Lingua::Shakespeare; The Infamous Hello World Program. Romeo, a young man with a remarkable patience. Juliet, a likewise young woman of remarkable grace. Ophelia, a remarkable woman much in dispute with Hamlet. Hamlet, the flatterer of Andersen Insulting A/S. Act I: Hamlet's insults and flattery. Scene I: The insulting of Romeo. [Enter Hamlet and Romeo] Hamlet: You lying stupid fatherless big smelly half-witted coward! You are as stupid as the difference between a handsome rich brave hero and thyself! Speak your mind! etc...

use Acme::ButFirst; # Print a greeting, but first find caffiene. { print "Good morning!\n"; } but first { print "I need a coffee\n"; }

use Inline ASM => <<'END', PROTOTYPES => {JAxH => 'void(char*)'}; .globl JAxH .text # prototype: void JAxH(char *x); JAxH: pushl %ebp movl %esp,%ebp movl 8(%ebp),%eax pushl %eax pushl $jaxhstr call printf movl %ebp,%esp popl %ebp ret .data jaxhstr: .string "Just Another %s Hacker\n" END print JAxH('Perl');

And if you want run a hip AI company without actually writing a lot of code(¹), you can just recycle all the open sourced python stuff within Perl to woo your investors...

print "9 + 16 = ", add(9, 16), "\n"; print "9 - 16 = ", subtract(9, 16), "\n"; use Inline Python => <<'END_OF_PYTHON_CODE'; def add(x,y): return x + y def subtract(x,y): return x - y END_OF_PYTHON_CODE


(¹) Writing actual code for a startup and producing value for the investors is just a waste of money. Money that could be much better spent on Booze, Babes and epic music festivals in the Bahamas featuring the latest in Instagram models...

Replies are listed 'Best First'.
Re^2: Puzzled by value of $overload::ops{binary}
by syphilis (Archbishop) on Jun 25, 2024 at 01:52 UTC
    As with pretty much every other thing involving the perl parser, the answer is a resounding yes

    It seems that there are often limitations regarding the liberties that can be taken regarding overloading.
    I have overloading subs (XSubs) that will overload '++' as:
    void overload_inc($V * object, SV * second, SV * switch) { /* code that adds 1 to the value held by object */ }
    That always works perfectly well.
    I've then considered that I should be able to do the same thing with the overloading of the '+=' operator:
    void overload_plus_eq(SV * object, SV * addon, SV * switch) { /*code that adds the value of addon to the value held by object */ }
    That attempt (in overload_plus_eq), to modify the object in place always fails when called by the '+=' operator - and I have never been able to write that XSub such that it is successfully called via overloading of '+=', unless it returns a new object that overwrites the existing one.
    (Which, BTW, I think is what happens with the overloading of '+=' when only '+' is overloaded.)

    I've assumed the incapacity of '+=' overloading to "modify in place" is related to '+=' NOT being seen as a "mutator" by overload.pm.
    But maybe it's just that I haven't found the right way of doing it.

    I've often wished that overloading of "log2" and "log10" was available ... but not to the extent that I'm going to commandeer a couple of these 'bitwise' operators for that purpose ;-)
    (I doubt that could readily be achievable, anyway.)

    I've noticed that overload.pm recognizes these additional bitwise operators as being valid, even though"feature 'bitwise'" has not been loaded:
    D:\>perl -Mwarnings -Moverload -e "use overload 'fu' => sub {return 1} +;" overload arg 'fu' is invalid at -e line 1. D:\>perl -Mwarnings -Moverload -e "use overload '&.' => sub {return 1} +;" D:\>perl -Mwarnings -Moverload -e "use overload '&.=' => sub {return 1 +};" D:\>
    Seems a bit odd .... but perhaps of little or no importance.

    Cheers,
    Rob
      I'd suggest PDL is the ultimate operator-overloader "source of truth". Mutating overloads is implemented in PDL::Ops, specifically (https://github.com/PDLPorters/pdl/blob/ad2783ad4b00583f14af3a3c24a93bb9f1a4ff33/Basic/Ops/ops.pd#L191-L196):
      $ret .= pp_line_numbers(__LINE__, <<EOF) if $mutator; BEGIN { # in1, in2, out, swap if true \$OVERLOADS{'$op='} = sub { PDL::$name(\$_[0]->inplace, \$_[1]); \$_[0 +] }; } EOF
      Modifying the generated code for += to this:
      #line 192 "ops.pd" BEGIN { # in1, in2, out, swap if true $OVERLOADS{'+='} = sub { use Carp; use Test::More; diag "RUN ", Test::More::explain \@_; PDL::plus($_[0]->inplace, $_[1]); $_[0] }; }
      and running it like this:
      $ perl -MPDL -e '$p=pdl(1); $p+=2'
      gives:
      # RUN [ # bless( do{\(my $o = '94749946365136')}, 'PDL' ), # 2, # undef # ]
      so your XS function should work. Did you make an overload for +=?
        In Math::GMPz, the overloading of '++' is:
        void overload_inc(pTHX_ SV * p, SV * a, SV * b) { mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), *(INT2PTR(mpz_t * +, SvIVX(SvRV(p)))), 1); }
        which is simply doing p = p + 1, with "p" being a Math::GMPz object.
        Then, in the bottom section of the XS file I have:
        void overload_inc (p, a, b) SV * p SV * a SV * b CODE: overload_inc(aTHX_ p, a, b); XSRETURN_EMPTY; /* return empty stack */
        Works fine.
        For the overloading of '+=', it gets a bit drawn out because we might be adding on something other than an IV.
        But if we were just dealing with adding on an unsigned long int we would actually have:
        SV * overload_add_eq(pTHX_ SV * p, SV * a, SV * b) { mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), *(INT2PTR(mpz_t * +, SvIVX(SvRV(p)))), SvUV(a)); SvREFCNT_inc(p); return p; }
        which is just doing p = p + a, and returning p (after increasing the refcount).
        The corresponding code in the bottom section of the XS file would be:
        SV * overload_add_eq (p, a, b) SV * p SV * a SV * b CODE: RETVAL = overload_add_eq (aTHX_ p, a, b); OUTPUT: RETVAL
        Now, it's not hard to work out what that overload_add_eq() would look like if I were to apply the same approach as used by overload_inc():
        void overload_add_eq(pTHX_ SV * p, SV * a, SV * b) { mpz_add_ui(*(INT2PTR(mpz_t *, SvIVX(SvRV(p)))), *(INT2PTR(mpz_t * +, SvIVX(SvRV(p)))), SvUV(a)); }
        and
        void overload_add_eq (p, second, third) SV * p SV * a SV * b CODE: overload_add_eq(aTHX_ p, a, b); XSRETURN_EMPTY; /* return empty stack */
        But I've never managed to get that to work.
        It has, however, been a while since I've tried - so I'll have another crack at it tomorrow (as it's now getting late over here) and see if I can get lucky.
        (I can't actually remember just what the problem is.)

        BTW, I've fiddled about with that code that I've posted, so it might contain one or more typos.

        Cheers,
        Rob