On Tue, Sep 29, 2009 at 03:49:31PM +0200, Christoph Bussenius wrote:
: Hi,
: I read is S03,
:     The && and || operators are smarter about list context and return ()
:     on failure in list context rather than Bool::False. The operators
:     still short-circuit, but if either operator would return a false
:     value, it is converted to the null list in list context so that the
:     false results are self-deleting.
: For "&&", wouldn't it be a better idea to return an empty list only if
: the *first* operand is false?  In other words, I suggest that "$a && $b"
: behave in list context like this:
:     * If $a is false, return ()
:     * Otherwise, return $b
: Here's a use case that would benefit from this behaviour:
: Suppose you want to generate an argument list for an external command.
: For some reason you have a boolean value $include_arg3 and you want to
: include $arg3 only if $include_arg3 is true:
:    my @args = $arg1, $arg2, $include_arg3 && $arg3, $arg4;
: Here you probably want to include $arg3 even if it is a false value like
: "0", provided that $include_arg3 is true.

Hmm, well, I see your point, but there are some arguments for the current
behavior as well:

    * Changing && without changing || would introduce a strange asymmetry.

    * Changing && to be pure conditional kinda undoes the list associative
        meaning of 'return the first false value or the last value'.

    * It would imply propagating list context to the left side but not
        the right side, which is time-travelishly problematic in a
        lazy language.

    * Alternately, it would mean that the result would have to be marked
        as to whether it came from the left or the right so that binding
        into a list context would know whether to throw it away or not.

    * Or one could return Nil instead of the left value, but then you
      lose any interesting value of false.

    * If one wants it to mean

           my @args = $arg1, $arg2, ($arg3 if $include_arg3), $arg4;

      one can write it that way, since C<if> already knows it's about
      control flow, not data selection, and returns Nil on false.  Or
      you can write:

           my @args = $arg1, $arg2, (if $include_arg3 {$arg3}), $arg4;

      if you want them in the other order.

    * If you know you're generating *positional* arguments ahead
      of time, you probably don't want list processing anyway; you
      probably want to put the args into a parcel/capture anyway to
      delay the application of context until binding time:

        my $args = \($arg1, $arg2, $include_arg3 && $arg3, $arg4);

      In this case the result of the && is its own parcel/capture
      that waits until binding time to decide how to behave.

But I agree that it's a trap of sorts.  My gut feeling is that it
won't happen often enough to become a FAQ, but I could be wrong.


Reply via email to