in reply to 'or' versus '||' - Unexpected Results

It is not only functioning as documented, but as intentionally and thoughtfully designed.

Replies are listed 'Best First'.
Re^2: 'or' versus '||' - Unexpected Results
by ikegami (Patriarch) on Jun 24, 2008 at 16:45 UTC

    Given the above, here's a step by step breakdown of what Perl does.

    c: When the code is compiled. r: When the code is run. my @list = x() | (1,2,3); c => my @list = scalar(x()) | scalar(1,2,3); c => my @list = scalar(x()) | scalar(2,3); <<void warn>> c => my @list = scalar(x()) | scalar(3); <<void warn (supressed)>> c => my @list = scalar(x()) | 3; r => my @list = undef | 3; r => my @list = 0 | 3; <<uninit warning>> r => my @list = 3; my @list0 = x() || (1,2,3); c => my @list0 = scalar(x()) || (1,2,3); r => my @list0 = undef || (1,2,3); r => my @list0 = (1,2,3); my @list1 = x() or (1,2,3); c => ( my @list1 = x() ) or (1,2,3); c => ( my @list1 = x() ) or (2,3); <<void warn>> c => ( my @list1 = x() ) or 3; <<void warn (supressed)>> c => my @list1 = x(); <<void warn>> r => my @list1 = (); my @list2 = $c->bbox('all') || (1,2,3); c => my @list2 = scalar($c->bbox('all')) || (1,2,3); r => my @list2 = [ ... ] || (1,2,3); r => my @list2 = [ ... ]; my @list3 = $c->bbox('all') or (1,2,3); c => ( my @list3 = $c->bbox('all') ) or (1,2,3); c => ( my @list3 = $c->bbox('all') ) or (2,3); <<void warn>> c => ( my @list3 = $c->bbox('all') ) or 3; <<void warn (supressed)>> c => my @list3 = $c->bbox('all'); <<void warn>> r => my @list3 = ( ... );
Re^2: 'or' versus '||' - Unexpected Results
by cmv (Chaplain) on Jun 24, 2008 at 16:47 UTC
    ikegami++ for the quick reply! Update: Thanks for answering some of this while I was typing it in

    My areas of confusion span the far reaches of the known universe, however for this problem, I can live with just 3 :-)

    I'm interested to understand why the '|' math operation decided to return a 3 for me, when given two non-numbers to operate on. This was the fun part.

    Thanks for the precedence pointer - I always seem to forget about that (duh - basic stuff)...

    The context confusion is the key - thanks for untangling my knotted mind. I see that this works:

    my @list2 = @{$c->bbox('all') || (1,2,3)};
    However, this won't work when the canvas is empty. Is there a way to write this that will work for both empty and non-empty canvas?

    Thanks

    -Craig

      I'm interested to understand why the '|' math operation decided to return a 3 for me, when given two non-numbers to operate on. This was the fun part.

      (3,4,5) | (7,8,9) === ((3,4),5) | ((7,8),9) === (4,5) | ((7,8),9) === 5 | ((7,8),9) === 5 | (8,9) === 5 | 9 === 13

      It's a common misconception that (..., ..., ...) is a list. It's simply two instances of the binary operator ",". In list context, "," returns a list consisting of both operands (which are evaluated in list context). In scalar context, "," returns its RHS operand (after evaluating both sides in scalar context).

      Is there a way to write this that will work for both empty and non-empty canvas?

      Close. Since you're dereferencing ("@{}") the result of the "||", you need to return an array reference on both sides of the "||".

      my @list2 = @{ $c->bbox('all') || [ 1,2,3 ] };

      Or if you want to avoid creating an array and a reference to it just so it can be derefenced and listed,

      my @list2 = $c->bbox('all'); @list2 = (1,2,3) if !@list2;

        In scalar context, "," returns its RHS operand (after evaluating both sides in scalar context).

        That's true except when it's not. See Re^2: ||= oddity

        my @list2 = @{ $c->bbox('all') || [ 1,2,3 ] }; does not work because [] evaluates as true in boolean context.
      As I posted below, '||' will not return the (true) left-hand-side in list context; you can use:
      my @t; my @list = (@t = $c->bbox()) ? @t : (1, 2, 3);
      and it'll work.