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

Monks- I'm trying to modify directly, a subroutine's passed-in variable. I've distilled it to the following (but had to hand-type; I hope I didn't introduce new errors!)
my $data = 3; foo { my ($data) = @_; $$data++; }
Perl throws an error at the $$data++ line.

I've looked at some sample Perl scripts that appear to operate this way.

I've looked over Common Causes for "Modification of a read-only value attempted" but it hasn't helped me.

Thanks!

Replies are listed 'Best First'.
Re: Modifying passed-in variables (named aliases)
by LanX (Saint) on Nov 02, 2015 at 18:50 UTC
    It's   $_[0]++; that's called an "alias" and realizes what's named "call by reference" in computer science.

    (The array @_ is magic and you need indices to access these aliases. A simple assignment will only copy values)

    If you want to address the alias by name you need an indirect perl reference, like

    $data = \$_[0]; $$data ++;

    Be careful to not confuse perl references and perl aliases.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

    updates

    Heavily expanded

Re: Modifying passed-in variables
by mr_ron (Deacon) on Nov 02, 2015 at 19:32 UTC

    Please remember to "use strict;" and "use warnings;". I reproduced the error "Modification of a read-only value" based on the incomplete code fragments you provided by commenting out "use strict;". Once you apply strict you get a more informative message that might have avoided this post.

    use strict; use warnings; my $d = 3; sub foo { my ($data) = @_; $$data++; } eval {foo($d);}; print $@; # prints informative message provided by strict foo(\$d); print "$d\n"; __END__ Can't use string ("3") as a SCALAR ref while "strict refs" in use ... 4
    Ron
      Thanks for the relies.

      Rolf: The code I posted (more or less) is being used in some sample code I'm looking at. Is that an old Perl construct - i.e., no longer valid?

      Ron: I did try with "strict" and "warnings" on. And I got a more verbose message, but to this noob, it wasn't more informative. LOL

      tonto: Close, yes; I forgot to include (apologies) the function call in the post, however I still wanted the intended functionality of the $$data++ (double "dollar sign") statement (IOW, modifying the value of $data as the calling function would see it). That's the whole point of my post. Thanks again for your time.

        I'm prepared to bet the error you got was: Can't use string ("3") as a SCALAR ref while "strict refs". This is one reason why your function isn't very friendly.

        What your function is doing is _expecting_ a reference, then modifying the value referenced. So you can call it by:

        foo ( \$data );
        Which is passing in a reference, that then "foo" alters. Because otherwise what you're doing is: ${'3'}++ which doesn't make a lot of sense.

        Action at a distance like that is generally considered bad form - you don't know what what the subroutine "foo" is doing to your local variable. So normally, what you would expect to pass in a value, and get back a result.

        You should probably note - you _do_ get a result back from your subroutine, that's the initial (pre-increment) value of $data. That can be confusing

        Here are some guesses at what the proprietary code you have may resemble (more or less). Two have been discussed,  bar() is new. All are valid constructs in the sense that they are not deprecated as of 5.14. Whether they are good ideas or not is another question. Please pick one of these as the closest to what you have:

        c:\@Work\Perl>perl -wMstrict -le "print qq{perl version $]}; ;; sub foo { my ($data) = @_; $$data++; } ;; my $x = 3; foo(\$x); print $x; ;; sub bar (\$) { my ($data) = @_; $$data++; } bar($x); print $x; ;; sub bof { $_[0]++; } bof($x); print $x; " perl version 5.008009 4 5 6


        Give a man a fish:  <%-{-{-{-<

Re: Modifying passed-in variables
by tonto (Friar) on Nov 02, 2015 at 18:58 UTC
    Maybe you meant to write:
    use strict; use warnings; my $data = 3; foo ($data); sub foo { my ($data) = @_; $data++; print $data; print "\n"; }