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

If I want to define a operator "_=" for which $t(1:2,0) _= $p(0,1:2) equals to $t(1:2,0) .= $p(0,1:2)->reshape($t(1:2,0)->dims), How should I do? Thanks!

Replies are listed 'Best First'.
Re: how to self define a operator
by choroba (Cardinal) on Oct 22, 2019 at 06:26 UTC
    See Sub::Infix for a safe way to define your own operators (but not exactly what you requested).

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Thanks, It is interesting!
Re: how to self define a operator
by vr (Curate) on Oct 22, 2019 at 10:26 UTC

    It's not clear how hypothetical operator should behave in case of multi-D slices. Your "reshape" solution simply fills new container with existing data regardless of row/column/plane boundaries, just like pouring liquid from one vessel to another of different shape, under normal gravity, and it's only exact volume that matters. Should 2-D matrix be perhaps transposed? Anyway, existing facilities can solve these tasks without repeating a slice expression twice -- if that's what you want to avoid.

    E.g., for "liquid data to fill new vessel", both RHS and LHS piddles can be flattened, and since the latter is virtual, changes will flow to original multi-D piddle:

    pdl> p$p = sequence 2,5 [ [0 1] [2 3] [4 5] [6 7] [8 9] ] pdl> p$t3 = $t2 = ($t1 = zeroes 4,3) .= -1 [ [-1 -1 -1 -1] [-1 -1 -1 -1] [-1 -1 -1 -1] ] pdl> $t1(0:2,1:2)->(;_) .= $p(0:1,1:3)->(;_); p$t1 [ [-1 -1 -1 -1] [ 2 3 4 -1] [ 5 6 7 -1] ] pdl> $t2(0:2,1:2)->flat .= $p(0:1,1:3)->flat; p$t2 # the same [ [-1 -1 -1 -1] [ 2 3 4 -1] [ 5 6 7 -1] ] pdl> $t3(0:2,1:2) .= $p(0:1,1:3)->transpose; p$t3 [ [-1 -1 -1 -1] [ 2 4 6 -1] [ 3 5 7 -1] ] pdl>
      Thanks! Your answer is much better than what my want! I have seen some guys using so many clump and dummy(0,1) making the code very ugly and obscure. Your method is very good!
Re: how to self define a operator (private method)
by LanX (Saint) on Oct 22, 2019 at 09:21 UTC
    Not exactly what you want, but since $p and $t seem to return objects, you are able to either

    • overload another operator for this task
    • or define a new method for their classes

    If that's too much of interference you can also define a private method

    my $meth = sub { $_[0] .= $_[1]->reshape($_[0]->dims) };

    And call it with

    $t(1:2,0)->$meth( $p(0,1:2) )

    from inside the same scope (untested)

    This should come close to what you want.

    HTH!

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    update

    demo

    DB<9> $op = sub { $_[0] + $_[1] } DB<10> p 4->$op(5) 9 DB<11>
      Great! It is a good method. Thanks!
Re: how to self define a operator
by LanX (Saint) on Oct 22, 2019 at 14:27 UTC
    no one mentioned it yet, but in case you don't really need a binary operator, you can go for a normal function, because arguments are "passed by alias" in Perl.

    DB<11> sub op { $_[0] += $_[1] } DB<12> $x=4 DB<13> op($x,5) DB<14> p $x 9 DB<15>

    as you can see, you can change the states of passed variables.

    That's normally the most maintainable approach, especially when combined with a good name for the operation.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Thanks, it is a good idea.
Re: how to self define a operator
by rjt (Curate) on Oct 22, 2019 at 06:19 UTC

    What you want to do would require modifying the language with new syntax. Hopefully needless to say, such endeavors are difficult, dangerous, and likely to be a waste of time, even if you are already a language specialist. To wit, the ~~ (smartmatch) binary operator was added to a public release almost 12 years ago, and it's still not stable.

    You might be able to hack something together with source filters that sort of works in limited cases, but please don't. Odds of something like that breaking in simultaneously spectacular and sneaky fashion are unacceptably high for anything other than toy programs.

    Would you mind sharing more details on what you are actually trying to accomplish (apart from inventing syntax)? A proper description of what you are actually working on would help us help you. There may well be an easy, elegant solution in pure Perl.

      Thank you very much for your reply!

      What I want to do is making the PDL more simple, as simple as matlab :D.

      for example, if we want to transfer the values from $t(1:4,0,0) to $d1(0,0:3), we can not write as below, because the dimensions are not same.

      $d1(0,0:3) .= $t(1:4,0,0);

      We have to write as this:

      $d1(0,0:3) .= $t(1:4,0,0)->reshape($d1(0,0:3)->dims);

      So I think if I can generate a "_=" which equal to .= $t(1:4,0,0)->reshape($d1(0,0:3)->dims or using a new method "rp" as $d1(0,0:3)->rp($t(1:4,0,0));

Re: how to self define a operator
by ikegami (Patriarch) on Oct 22, 2019 at 14:27 UTC

    Why not just overload the . operator for that class and use .=?

      Interesting, I will learn that, thanks.