Search code examples
perlpdl

How to avoid input modification in PDL subroutines


I would like to avoid the assignment operator .= to modify the user input from a subroutine.

One way to avoid this is to perform a copy of the input inside the subroutine. Is this the best way to proceed? Are there other solutions?

use PDL;use strict;
my $a=pdl(1);
f_0($a);print "$a\n";
f_1($a);print "$a\n";
sub f_0{
    my($input)=@_;
    my $x=$input->copy;
    $x.=0;
}
sub f_1{
    my($input)=@_;
    $input.=0;
}

In my case (perl 5.22.1), executing last script prints 1 and 0 in two lines. f_0 does not modify user input in-place, while f_1 does.


Solution

  • According to the FAQ 6.17 What happens when I have several references to the same PDL object in different variables :

    Piddles behave like Perl references in many respects. So when you say

    $a = pdl [0,1,2,3]; $b = $a;   
    

    then both $b and $a point to the same object, e.g. then saying

    $b++; 
    

    will not create a copy of the original piddle but just increment in place
    [...]
    It is important to keep the "reference nature" of piddles in mind when passing piddles into subroutines. If you modify the input piddles you modify the original argument, not a copy of it. This is different from some other array processing languages but makes for very efficient passing of piddles between subroutines. If you do not want to modify the original argument but rather a copy of it just create a copy explicitly...

    So yes, to avoid modification of the original, create a copy as you did:

    my $x = $input->copy;
    

    or alternatively:

    my $x = pdl( $input );