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. Larry