2009/9/11 Steve Bertrand <st...@ibctech.ca>: > Uri Guttman wrote: >> it is actually very simple to understand. the key point to knowing it >> and how to use it is that the 2 value expressions SHOULD NOT have side >> effects. that means changing something by assignment or other >> modification. your example below is one exception to that. > > Since I use functions/methods to perform side effects frequently, I > believe what you mean is that in *most* cases, the conditional op > shouldn't ever have anything that must be evaluated in one of the > either/or fields. > > For example, this: > > my $num = 1; > my $add_to = 2; > > my $ret = ( $foo == 1 ) ? ( $num + $add_to ) : 2; > > ...SHOULD _always_ ( where possible ) be written as: > > my $expr_result = ( $num + $add_to ); > > my $ret = ( $foo == 1 ) ? $expr_result : 2;
No, that's not it. ($num + $add_to) is an expression with no side-effects. The only purpose of the expression is to calculate a value, which can then be assigned to a variable (or passed to a function, or used to index an array, or whatever). In this case, you can't actually tell whether or not ($num + $add_to) was evaluated if the false branch was taken, because even if it were it has no side-effects and you've discarded its value. (shift) is an expression with side-effects. The expression returns a value, the first element of @_, *and also* removes that element from the front of @_. This modification of @_ is known as a side-effect, because it changes the state of something rather than just calculating a value for the expression. After evaluating the expression (shift) to find its value, @_ has changed. If you throw away the result of shift, it still has an effect on the state of the program. [Nitpick: shift returns the first element of @_ within a subroutine, but outside it uses @ARGV instead] Uri's point about side-effects is one of style. Generally ?: is used for calculating a value to be used in an expression, most often in the form: $target = <condition> ? <trueval> : <falseval>; The expressions <trueval> and <falseval> are primarily used to calculate a value. Other examples of using the ?: to calculate a value are: myfunc( $cond ? $foo : $bar); $target += $cond ? $foo : $bar; # or -= or *= or any other modify-assignment operator You *could* use the ?: operator differently, as a control-flow statement: $push_to_left ? push @left, $value : push @right, $value; but this is really, really bad style. Note how we are no longer using the ?: operator to choose between different values, but instead to choose between different side-effects: either @left changes, or @right does. When you are choosing between functionality and not values, you should use a proper "if" or "unless": if ($push_to_left) { push @left, $value; } else { push @right, $value; } You could, in theory, do this: push @{ $push_to_left ? \...@left : \...@right }, $value; but the mucking about with references to make it work makes it less readable than the if() version, IMO. In your original example: my $args = ( ref $_[0] eq 'HASH' ) ? shift : {} ; the ?: operator chooses between two values, but one of the expressions has a side-effect (of changing @_). The side-effect is actually good, and should be kept in the conditional. If we took it out: my $val = shift; my $args = ( ref $val eq 'HASH' ) ? $val : {} ; then we've changed the meaning, since the shift will always happen now, and if $val is not a hashref its value still gets removed from @_, probably not what you want. This is why your original example is an exception to the "avoid side-effects" rule. I actually think the style rule regarding ?: is slightly different to what Uri said: ** Don't use ?: for control-flow. Only use it to select between two values. ** If one of the values is gotten using a side-effect, that can be ok. But if the side-effect of the trueval or falseval is the only purpose of the ?: statement, you should rewrite it, either in the form '$target = condition ? foo : bar;' or as an if statement. Philip -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/