http://qs321.pair.com?node_id=11120304


in reply to Shouldn't LITERAL references be readonly? (updated)

The {} and [] operators construct new aggregates each time they are evaluated. Why should those values be readonly? They are not literals.

Replies are listed 'Best First'.
Re^2: Shouldn't references be readonly?
by LanX (Cardinal) on Aug 05, 2020 at 02:01 UTC

      Unlike a numeric literal value, [] is compiled into an opcode which calls . . . something (this is where I'm hoping someone more familiar with guts steps in) which returns a new reference value.

      $ perl -MO=Concise,-exec, -E '$a = []; $b = 5' 1 <0> enter v 2 <;> nextstate(main 2 -e:1) v:%,us,{,fea=7 3 <0> pushmark s 4 <@> anonlist sK* 5 <#> gvsv[*a] s 6 <2> sassign vKS/2 7 <;> nextstate(main 2 -e:1) v:%,us,{,fea=7 8 <$> const[IV 5] s 9 <#> gvsv[*b] s a <2> sassign vKS/2 b <@> leave[1 ref] vKP/REFC

      Opcode 4 here is doing something to allocate a new AV* and pushing the SVrv referencing that new arrayref onto the stack which then is assigned into $a. Opcode 8 is pushing the immediate literal value SViv (which is readonly) onto the stack and assigning that into $b.

      Edit: I'm mixing up the layers and perl and C and everything but . . .

      When you have map { $_ = 1 } [] in the underlying runtime what's kind of happening is that something's going:

      my @args; $args[0] = anonlist();

      then when your map EXPR, @args runs, because $_ is aliased to each item in @args something like this happens

      $args[0] = 1;

      The anonymous arrayref went into the temporary array's slot zero when it was initialized; in the map EXPR you're replacing the value in that slot in the array but you're not doing anything to the arrayref which was referenced by the previous value in that same slot. I admit that it's kind of weird that the temporary arglist slots aren't readonly but if they were made readonly then I don't think aliasing like $a = 1;for($a){ $_ = 'foo' } would work so that $a would have 'foo' afterwards (i.e. aliasing of $_ in for to a transient list of arbitrary values).

      Edit 2: while [] is a literal token it doesn't stand for a constant value.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        Im asking about logic and you are arguing with implementation.

        I haven't seen a logical reason why Perl shouldn't throw an error if the alias to a ref is overwritten.

        My suspicion is that the ugly truth is that the readonly flag is (mis)used for indicating if the referenced data structure is "constant" not the reference itself.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      They're constructors for containers, not values. I'm not sure what the value would be to make [] and {} create singleton immutable containers.

        I'm talking about the container not the content.

        I can't see a reason why one would want to change the alias of the container, hence this should throw an error.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      I am considering "literals" as more like constants embedded in the program, using a constant pool, where changing a value would have bizarre effects, like changing the value of "123456" everywhere in the program. Literal strings in C programs are often combined in this way.

      The {} and [] operators are defined to produce distinct mutable aggregates every time they are evaluated. In this sense, they are not literals.

      I am unsure how this behavior of replacing the reference itself is actually useful, but nor do I see any harm here.

        > I am considering "literals" as more like constants embedded in the program,

        I understand your POV ...

        ... BUT literals with the exception of undef are not constant!

        Re^2: Shouldn't references be readonly?

        It's always a new ref, hence constructed.

        The semantics in JS are 100% the same, and they refer to [] and {} as "literal (object) constructors"

        And I can't find any definition claiming literals to be constants, I think that was made up in this thread.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re^2: Shouldn't references be readonly?
by LanX (Cardinal) on Aug 05, 2020 at 19:13 UTC
    > The {} and [] operators construct new aggregates each time they are evaluated.

    This might come as a surprise but literals in Perl are always new as you can see by the references.

    DB<66> p \1 SCALAR(0x335c4a0) DB<67> p \1 SCALAR(0x335c6f8) DB<68> p \1 SCALAR(0x335cae8) DB<69>

    I know there are languages where it's always the same (IMHO do Ruby and Lisp have a syntax for this) but this is not what I mean or asked.

    Alas ... few of the respondents here seem to have read the code in the OP and really have a deep grasp of aliases.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    ) well undef is an exception, but it's debatable if that's a literal or a constant.

    DB<69> p \undef SCALAR(0xfb9098) DB<70> p \undef SCALAR(0xfb9098) DB<71> p \undef SCALAR(0xfb9098) DB<72> p \undef SCALAR(0xfb9098) DB<73> p \"str" SCALAR(0x335d3c0) DB<74> p \"str" SCALAR(0x335d498) DB<75> p \"str" SCALAR(0x335d270)

      That seems to be because a reference to a literal actually constructs a new scalar; note that the examples you gave where an error was thrown at an attempt to modify a read-only value did not involve references, but only aliases to literal values. I suspect that the anonymous scalar you get when you say \1 is probably modifiable. There is no such thing as a literal aggregate in Perl — the {} and [] operators are defined as constructors instead.

        > That seems to be because a reference to a literal actually constructs a new scalar;

        again more theories ...

        see how the ref to a real constant like a stays stable in Re^8: Shouldn't references be readonly? (updated) and please explain the difference to your allegedly constant 1 .

        > There is no such thing as a literal aggregate in Perl the {} and [] operators are defined as constructors instead.

        Defined? ... Source?

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery