in reply to Re^3: Operator overloading with returning lists?
in thread Operator overloading with returning lists?

since when does scalar context of a list result in a join???
DB<88> p Dumper (('x') x 5) $VAR1 = 'x'; $VAR2 = 'x'; $VAR3 = 'x'; $VAR4 = 'x'; $VAR5 = 'x'; DB<89> p Dumper scalar (('x') x 5) $VAR1 = 'xxxxx'; DB<90> p Dumper scalar (@x=('x') x 5) $VAR1 = 5; DB<91> p Dumper (scalar qw/x x x x x/) $VAR1 = 'x';

mysterious perl ... 8(

Cheers Rolf

UPDATE:

DB<97> p Dumper scalar ( (1,2) x 5 ) $VAR1 = '22222'; DB<98> p Dumper ( (1,2) x 5 ) $VAR1 = 1; $VAR2 = 2; $VAR3 = 1; $VAR4 = 2; $VAR5 = 1; $VAR6 = 2; $VAR7 = 1; $VAR8 = 2; $VAR9 = 1; $VAR10 = 2;

The scalar is applied to the list before the x-op can act. The parens are ignored...

Thats a bug or a feature?

Replies are listed 'Best First'.
Re^5: Operator overloading with returning lists?
by ikegami (Patriarch) on Dec 01, 2008 at 16:33 UTC

    Perl doesn't see things as left-to-right as you do.

    "scalar" in "scalar ( (1,2) x 5 )" acts on "x", not "(1,2)".
    The return value of "()x" in scalar context is (join '', map LHS, 1..RHS).

    Similarly, "scalar" in "scalar ( ($a) = 5 )" acts on "=", not "($a)".
    The return value of "()=" in scalar context is the number of items returned by its RHS.

    Not a bug. In both case, the code works as designed and as intended.

Re^5: Operator overloading with returning lists?
by Anonymous Monk on Dec 01, 2008 at 15:01 UTC
    Neither.
    C:\>perl -MData::Dumper -le"print Dumper scalar ( 1, 2 ) " $VAR1 = 2; C:\>perl -MData::Dumper -le"print Dumper scalar ( 1, 2 ) x 5" $VAR1 = '22222'; C:\>perl -MData::Dumper -le"print Dumper 2 x 5" $VAR1 = '22222';
    "List" Is a Four-Letter Word
      Thx for the link, but the only thing that might explain what happens is lists do not exist in scalar context .

      such that

      DB<97> p Dumper scalar ( (1,2) x 5 ) $VAR1 = '22222';
      transforms to
      DB<101> p Dumper scalar(1,2) x 5 $VAR1 = '22222';

      Cheers Rolf

      UPDATE: after reading: http://perldoc.perl.org/perlop.html#Multiplicative-Operators I understand that the scalar context inhibits the parens around (1,2) !
        So which is it, bug or feature ?
Re^5: Operator overloading with returning lists?
by JavaFan (Canon) on Dec 01, 2008 at 15:54 UTC
    since when does scalar context of a list result in a join???
    It does? Which of your examples do you think supports this notion?
    The scalar is applied to the list before the x-op can act. The parens are ignored...
    I do not know what you mean by this.
    Thats a bug or a feature?
    From 'man perlop':
           Binary "x" is the repetition operator.  In scalar context or if the
           left operand is not enclosed in parentheses, it returns a string
           consisting of the left operand repeated the number of times specified
           by the right operand.  In list context, if the left operand is enclosed
           in parentheses or is a list formed by "qw/STRING/", it repeats the
           list.  If the right operand is zero or negative, it returns an empty
           string or an empty list, depending on the context.
    
      The scalar is applied to the list before the x-op can act. The parens are ignored...
      I do not know what you mean by this.
      Context is not a function applied after the parens are evaluated. In other words: Precedence is weaker than context!

      Cheers Rolf

        I've no idea what you mean by "precedence is weaker than context", but if you look into the perl source code, you'll notice that there's a special case for the 'x' operator in list context where the LHS of the operator has parens.
        PP(pp_repeat) { dVAR; dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN); { register IV count; dPOPss; SvGETMAGIC(sv); if (SvIOKp(sv)) { if (SvUOK(sv)) { const UV uv = SvUV(sv); if (uv > IV_MAX) count = IV_MAX; /* The best we can do? */ else count = uv; } else { const IV iv = SvIV(sv); if (iv < 0) count = 0; else count = iv; } } else if (SvNOKp(sv)) { const NV nv = SvNV(sv); if (nv < 0.0) count = 0; else count = (IV)nv; } else count = SvIV(sv); if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) { dMARK; static const char oom_list_extend[] = "Out of memory during li +st extend" ; const I32 items = SP - MARK; const I32 max = items * count; MEM_WRAP_CHECK_1(max, SV*, oom_list_extend); /* Did the max computation overflow? */ if (items > 0 && max > 0 && (max < items || max < count)) Perl_croak(aTHX_ oom_list_extend); MEXTEND(MARK, max); if (count > 1) { while (SP > MARK) { if (*SP) SvTEMP_off((*SP)); SP--; } MARK++; repeatcpy((char*)(MARK + items), (char*)MARK, items * sizeof(const SV *), count - 1); SP += max; } else if (count <= 0) SP -= items; } else { /* Note: mark already snarfed by pp_list */ SV * const tmpstr = POPs; STRLEN len; bool isutf; static const char oom_string_extend[] = "Out of memory during string extend"; SvSetSV(TARG, tmpstr); SvPV_force(TARG, len); isutf = DO_UTF8(TARG); if (count != 1) { if (count < 1) SvCUR_set(TARG, 0); else { const STRLEN max = (UV)count * len; if (len > MEM_SIZE_MAX / count) Perl_croak(aTHX_ oom_string_extend); MEM_WRAP_CHECK_1(max, char, oom_string_extend); SvGROW(TARG, max + 1); repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - + 1); SvCUR_set(TARG, SvCUR(TARG) * count); } *SvEND(TARG) = '\0'; } if (isutf) (void)SvPOK_only_UTF8(TARG); else (void)SvPOK_only(TARG); if (PL_op->op_private & OPpREPEAT_DOLIST) { /* The parser saw this as a list repeat, and there are probably several items on the stack. But we're in scalar context, and there's no pp_list to save us now. So drop the rest of the items -- robin@kitsite.com */ dMARK; SP = MARK; } PUSHTARG; } RETURN; } }
        The flag OPpREPEAT_DOLIST is set in op.c:
        OP * Perl_ck_repeat(pTHX_ OP *o) { PERL_ARGS_ASSERT_CK_REPEAT; if (cBINOPo->op_first->op_flags & OPf_PARENS) { o->op_private |= OPpREPEAT_DOLIST; cBINOPo->op_first = force_list(cBINOPo->op_first); } else scalar(o); return o; }
        As you can see, it's here where list context is forced upon the LHS operand.

        This is one of the few cases in Perl where parens do create lists.

        Precedence is weaker than context!
        You're drawing too many conclusions from an edge case