http://qs1969.pair.com?node_id=946670


in reply to Re^8: ref to read-only alias ... why? (notabug)
in thread ref to read-only alias ... why?

Could you please clarify which the "working case" is in your opinion?

It shouldn't matter whether your scalar was created by «my $x» or by «123». The literal «123» should return a modifiable value. The code in \ is specifically there to emulate that without the cost of creating a new scalar every time «123» is evaluated.

I agree with tye that there are good arguments for both perspectives.

I can't find these arguments. Could you give me a link?

Replies are listed 'Best First'.
Re^10: ref to read-only alias ... why? (notabug)
by dk (Chaplain) on Jan 06, 2012 at 21:57 UTC
    The literal «123» should return a modifiable value.

    Could you elaborate on that please? I don't find that neither convincing nor intuitive. If that's true, why error message "Modification of a read-only value" exists at all? By the same logic 123++ should be working fine, no?

      Expected result:
      Expected Current for (1..2) { for (1) { my $r = \$_; ++$$r; say $$r; 2 2 2 2 (threaded) } [die] (non-threaded) } for (1..2) { for (1) { ++$_; say; 2 2 [die] } } for (1..2) { for (1..3) { ++$_; say; 234 234 234 345 } }
        If I'm not mistaken, I believe that there's another issue you're trying to pull it here, namely difference between for(1) and for(1..3). They _do_ behave weirdly, I totally agree. But I believe that's a totally separate issue, probably related to parser even, because this code:

        my $a = 2; $_++ for 1..$a; print "$a\n"; # 2

        shows that $a is not aliased. Therefore I don't see how the original problem that needs a scalar be both aliased and read-only, is relevant here.

      123++ should be working fine, no?

      A "useless" warning would be appropriate.

      ++123 would be equivalent to 1+123, though.

        I don't mind that, but now we're off-topic, and veering into quite another direction. You're welcome to raise this question on p5p, if 123++ should behave as you're suggesting, and even though I see chances on accepting that are small, hopefully you'd be able to achieve the change. That change is not my focus though, sorry, I'd be rather happy to just remove that one small inconsistency from the Perl behavior. And if you could help me with that, I'd be grateful.
Re^10: ref to read-only alias ... why? (notabug)
by LanX (Saint) on Jan 09, 2012 at 22:07 UTC
    > I can't find these arguments. Could you give me a link?

    He didn't list many arguments, thats the link: Re^3: ref to read-only alias ... why? (notabug)

    > It shouldn't matter whether your scalar was created by «my $x» or by «123».

    So your POW is that the standard behavior is wrong, such that in my code-example inc_a() should better also act like inc_b()?

    Without really understanding the opcode-level I'm wondering why you say that either behaviors are difficult to implement if both already exist.

    IMHO there should always be a configurable (i.e. switchable) warning because different people expect different behavior.

    Cheers Rolf

      He didn't list many arguments

      He mentions there are arguments for both ways ("I don't find it hard to imagine cases where either result would be preferred."), but they're not listed.

      So your POW is that the standard behavior is wrong

      My POV is:

      • There is currently no standard. (See Re^11: ref to read-only alias ... why? (notabug).)
      • Many people are currently modifying values from literals where it is possible to do so, and they are very unwilling to give up that feature.
      • Perl is about enabling people to do what they want to do.
      • The two downsides are addressable.
        • Inefficiency of creating a new scalar every time a const op is evaluated. (Use a COW mechanism.)
        • Creation of useless code is possible, e.g. 123++; (Emit warnings when appropriate.)

      Without really understanding the opcode-level I'm wondering why you say that either behaviors are difficult to implement if both already exist.

      There's no denying the current implementation isn't sane.

      • Inconsistent. (For example, for (1) { ++$_; say $_; } is different than for (1) { $r = \$_; ++$$r; say $$r; }.)
      • Buggy. (For example, for (1..2) { for (1..3) { ++$_; say; } }.)

      Hash key vivification has similar problems.

      sub {}->( $h{x} ) # Doesn't vivify sub {}->( @h{x} ) # vivifies for ( $h{x} ) { } # vivifies for ( @h{x} ) { } # vivifies \$h{x} # vivifies \@h{x} # vivifies

      In both case, it's more a question of time than difficulty.

      IMHO there should always be a configurable (i.e. switchable) warning because different people expect different behavior.

      I don't see a point to a switch whose sole purpose is to break working code.

      No argument or example was given to indicate there is another purpose. There probably are some, and I would love to hear them. Until then, the switch makes no sense.

        Thanks for the detailed post!

        I have to admit I'm not too much concerned about aliasing in for-each-loops, because they have a limited scope.

        Loosing the overview about aliases in nested for-eaches implies bad coding practice resp. the need for refactoring.

        So I'm more concentrating on the @_ aliases of subs, the possible effects are not limited to the sub.

        Let's suppose a sub Package_A::trim($a) which uses call-by-reference to delete leading and trailing whitespaces.

        Another sub Package_B::report() might create a report, and needs to trim the entries:

        sub report { trim($_) for @_; return sprintf "...",@_; }

        Some code in Package_C calls report() and passes occasionally a read-only value.

        Now depending on the implementation of trim() the code might

        a) die with "modification of read-only ..." or

        b) continue but silently fail to delete the whitespaces.

        That's why I think there should be at least a warning in case b.

        > I don't see a point to a switch whose sole purpose is to break working code.

        I don't understand why a warning would break existing code.

        In general:

        And I don't see a better coding practice, except avoiding subs like trim() using side-effects by manipulation $_[]

        Clearly the author of report() doesn't expect read-only arguments, but since Perl5 doesn't have signatures like in Perl6 he can't easily enforce them.

        He could rely on the implementation of trim which throws an error in case a). But after the author of Package_A switches to implementation b) of trim() the functionality of Package_B is broken.

        And the different test-suites of packages A,B and C do not report any problem. I hope it's understandable now why aliasing in subs bothers me more than in for-eaches.

        Cheers Rolf

        PS: Sorry for the delay, quite busy ATM.