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

if (... and do { ($result) = func($param); $result })

if (... and (($result) = func($param)))

I think the 2nd form is much nicer,

is there any special reason for using the 1st form?

Replies are listed 'Best First'.
Re: Is there any difference between these two statement?
by ikegami (Patriarch) on Dec 05, 2011 at 07:52 UTC
    sub func { return (0, 1, 2) } if (1 and do { ($result) = func($param); $result }) { print "1\n"; } else { print "0\n"; } if (1 and ($result) = func($param)) { print "1\n"; } else { print "0\n"; }
    outputs
    0 1

    ($result) = func($param)

    is a list assignment, and it happens to be in scalar context. List assignment in scalar context returns the number of elements returned by its RHS. (See Mini-Tutorial: Scalar vs List Assignment Operator.)

    If func returns three values, the second snippet is equivalent to

    if (... and do { ($result) = func($param); 3 })

    which is different than

    if (... and do { ($result) = func($param); $result })

    As shown above, the difference will matter when func returns more than one value and the first is false.


    You can avoid the do using a list slice.

    if (... and $result = (func($param))[0])

    Scalar assignment returns its LHS.

Re: Is there any difference between these two statement?
by GrandFather (Saint) on Dec 05, 2011 at 07:17 UTC

    I can't think of any excuse for either form. There is a balance between terseness and obfuscation. Both those statements are rather more toward the obfuscation side of the balance than toward the useful terseness side (at least in my view - YMMV).

    True laziness is hard work
Re: Is there any difference between these two statement?
by Corion (Patriarch) on Dec 05, 2011 at 07:25 UTC

    The only reason I imagine for the first form is when autogenerating code. If a code fragment consists of more than a simple expression, the do-block will always convert that fragment to an expression.

    Update: Also see ikegami's advice about list context below!

Re: Is there any difference between these two statement?
by JavaFan (Canon) on Dec 05, 2011 at 08:00 UTC
    The first form creates an additional scope, the second form. It doesn't matter for the example snippet you gave, but it may matter if you substitute something else.
Re: Is there any difference between these two statement?
by TJPride (Pilgrim) on Dec 05, 2011 at 13:42 UTC
    As ikegami pointed out, the second form does not work as probably intended (this was actually a new one on me!) But how about this version?

    if (1 and ($result = (func($param))[0])) { print "1\n"; } else { print "0\n"; } print "$result\n"; sub func { return (0, 1, 2); }

    Prints two 0's, which seems to be what is wanted here - and with syntax that makes more direct sense than form #1 (at least in my opinion).