in reply to Useless unless

What I was trying to get at was an 'else' for statement-modifier 'if'. The idea is to avoid the (quasi)equivalent
foo() if $x; bar() unless $x;
because that has serious potential problems. Namely, the conditional expression ($x) could be non-idempotent, or it could be expensive to evaluate. (Note that simply being a scalar variable doesn't avoid this problem: it could be tied.)

The workaround is to use a temporary variable:

{ | for my $b ( $x ) | for $x -> my $b my $b = $x; | { | { foo() if $b; | foo() if $b; | foo() if $b; bar() unless $b; | bar() unless $b; | bar() unless $b; } | } | }
but that's getting ugly. You may as well use the standard if/else and avoid a temporary.

As for the suggestion of using the trinary operatory, I would just point out that the intended purpose of the trinary operator is as a selector between two expressions rather than two statements — that is, between data rather than code. Of course you can use it to select between expressions which are there for their side-effects... but using the trinary operator in void context is — or should be, to seasoned Perl programmers — as distasteful as using map in void context: Sure, it works, and has no ill effects, but as a matter of style, it's just bad.

Another approach to 'otherwise' would be
foo() else bar() if $x;
but that has the disadvantage of putting the "false" action right next to the 'if', so that a human might (mistakenly) see "... bar() if $x;" which is completely wrong.

Anyway, I really like 'otherwise', though I'm not seriously proposing it as an addition to the language. It's too late for such things. :-)

Replies are listed 'Best First'.
Re^2: Useless unless
by Anonymous Monk on Aug 09, 2005 at 09:06 UTC
    Sure, it works, and has no ill effects, but as a matter of style, it's just bad.
    That's just a matter of opinion. A piece of opinion that doesn't come with a rational. Knowing you find the style bad is interesting for census takers, programmers will find it more interesting why you find it bad style.

    I rank using the trinary in void context on the same level as using 'or' or 'and' in void context:

    /^#/ and next; open ... or die ...; -d $_ ? handle_directory($_) : handle_file($_);
    and those are almost on the same level as using statement modifiers:
    next if /^#/; die ... unless open ...; parse_file($_) for @files;
    Either they are all bad, or none of them are. And for me, none of them are.
Re^2: Useless unless
by Anonymous Monk on Aug 09, 2005 at 09:17 UTC
    You may as well use the standard if/else and avoid a temporary.
    No temporary variable, and no if/else, replacing
    EXPR1 if $x; EXPR2 unless $x;
    can be done as:
    ((sub {EXPR1}, sub {EXPR2})[!!$x || 0])->();
    except that EXPR1 and EXPR2 in the latter have their own scopes - but you have that with an if/else construct as well.

    If EXPR1 and EXPR2 are function calls using the same arguments, as in:

    foo($arg, @args) if $x; bar($arg, @args) unless $x;
    one could write:
    ((\&foo, \&bar)[!!$x || 0])->($arg, @args)