in reply to Re^7: chopping a string into slices - is there a more elegant way to do it?
in thread chopping a string into slices - is there a more elegant way to do it?

> The parens in ($a)=@_ don't affect context. They cause a list assignment operator (aassign) to be used instead of a scalar assignment operator (sassign).

I can't follow your interpretation ... aassign implies listcontext!

DB<54> $a= join ",",(1..5) DB<55> p $a 1,2,3,4,5 DB<56> print scalar split /,/,$a 5 DB<57> ($A)=split /,/,$a DB<58> print $A 1
split is executed in listcontext!

Cheers Rolf

  • Comment on Re^8: chopping a string into slices - is there a more elegant way to do it?
  • Download Code

Replies are listed 'Best First'.
Re^9: chopping a string into slices - is there a more elegant way to do it?
by ikegami (Patriarch) on Nov 30, 2008 at 19:01 UTC

    Yes, operators determine the context in which their operands are evaluated, and the aassign operator unconditionally evaluates its operands in list context. It's not based on the presence or absence of parens.

    You previously said that the operand ("($a)") determined the context. An expression never decides the context in which its evaluated. The context in which its evaluated is always imposed upon it by its caller.

    Even at the abstract level, the reason for using "($a)=" instead of "$a=" isn't to evaluate $a in list context. After all, $a evaluates to the same thing in both list and scalar context. The goal is to use the list assignment operator.

      I'm not so sure about that. My recollection was that assignment determined it's context by the left-hand side of the operation. A quick test

      sub which { if(wantarray) { print "list\n"; (); } else { "scalar\n"; 0; } } my $a = which(); my ($b) = which();

      seems to confirm this suspicion. The first prints scalar and the second prints list. This seems to imply that the subroutine is evaluated in scalar context in the first assignment.

      Is there something I'm missing?

      G. Wade

        My recollection was that assignment determined it's context by the left-hand side of the operation.

        That's impossible for two reasons.

        • The assignment type is always known at compile-time, but the context is not necessarily.
        • The type of assignment determines the context of the operands, so the context of the operands cannot determine the type of assignment. Chicken and egg.

        Your code shows that the type of assignment is determined by its LHS, but noone's disputing that.

        This seems to imply that the subroutine is evaluated in scalar context in the first assignment.

        It is.
        Scalar assignment evaluates both its LHS and RHS in scalar context.
        List assignment evaluates both its LHS and RHS in list context.

      Sorry many words I don't understand...

      ($a)= puts the RHS in listcontext,

      $a= puts the RHS in scalarcontext

      it's alway the same "=" and of course $a is a scalar.

      you said

      > The parens in ($a)=@_ don't affect context

      > Except when empty, parens never do more than control precedence. Except when empty, they never create a list context.

      The code shows your wrong that perl syntax is more complex. But if I'm wrong, please give me a reference to a perldoc defining "listcontext" the way your understanding it!

      Cheers Rolf

      UPDATE: to make it clear, I'm not saying that $a is evaluated in list-context, but I think it's reasonable to say that the LHS ($a) is a one element list, where commas were saved, like () is a null element list. If not please show me code that showes that ($a) is not a list.

        it's alway the same "="

        No, there are two different "=" operators, the scalar assignment operator (sassign) and the list assignment operator (aassign)

        >perl -MO=Concise -e"$a=1" 6 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 5 <2> sassign vKS/2 ->6 <-- 3 <$> const[IV 1] s ->4 - <1> ex-rv2sv sKRM*/1 ->5 4 <#> gvsv[*a] s ->5 -e syntax OK >perl -MO=Concise -e"($a)=1" 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 7 <2> aassign[t2] vKS ->8 <-- - <1> ex-list lK ->5 3 <0> pushmark s ->4 4 <$> const[IV 1] s ->5 - <1> ex-list lK ->7 5 <0> pushmark s ->6 - <1> ex-rv2sv sKPRM*/1 ->- 6 <#> gvsv[*a] s ->7 -e syntax OK

        ssassign evaluates its RHS in scalar context, then evaluates its LHS in scalar context, then performs the assignment, then returns the value returned by the RHS.

        asassign evaluates its RHS in list context, then evaluates its LHS in list context, then performs the assignment, then returns either the value returned by the RHS (in list context) or the number of scalars returned by the RHS (in scalar context).

        >perl -le"print( scalar( $a=5 ) );" 5 >perl -le"print( scalar( ($a)=5 ) );" 1

        If not please show me code that showes that ($a) is not a list.

        I didn't say it wasn't. The list assignment operator forces its arguments to be lists. For example, there are two lists in @a = 4.

        >perl -MO=Concise -e"@a=4" 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 8 <2> aassign[t3] vKS ->9 - <1> ex-list lK ->5 <--- 3 <0> pushmark s ->4 4 <$> const[IV 4] s ->5 - <1> ex-list lK ->8 <--- 5 <0> pushmark s ->6 7 <1> rv2av[t2] lKRM*/1 ->8 6 <#> gv[*a] s ->7 -e syntax OK

        Notice how the LHS is a list even though there's no parens? You're confusing cause and effect.
        "($a)" is a list because "=" is a list assignment operator.
        "=" being a list assignment operator isn't caused by "($a)" being a list.

        The parens only *indirectly* causes the change in context.