Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Secret Perl Operators: the boolean list squash operator, x!! (grep)

by tye (Cardinal)
on Jul 31, 2006 at 20:59 UTC ( #564872=note: print w/ replies, xml ) Need Help??


in reply to Secret Perl Operators: the boolean list squash operator, x!!

Comparing:

( list ) x!! cond ( grep cond, list ) cond ? ( list ) : ()

I think I'd rather "reuse" the well-known grep for this case than adopt the more cryptic idiom you've invented. For your example case, I much prefer something that uses:

join '/', grep defined $_, ...

Rather than repeating most of the terms twice (and repeating x!! and defined).

- tye        


Comment on Re: Secret Perl Operators: the boolean list squash operator, x!! (grep)
Select or Download Code
Re^2: Secret Perl Operators: the boolean list squash operator, x!! (grep)
by Aristotle (Chancellor) on Jul 31, 2006 at 21:16 UTC

    How does that work out if $is_admin_link is either 0 or 1, but never undefined?

    Makeshifts last the longest.

      $is_admin_link isn't in your list so it being defined doesn't matter. The second part of my node addresses most of your example while the first part of my node addresses the $is_admin_link part:

      my $uri = join '/', grep defined $_, 'http://ex­ample.net/­app', ( grep $is_admin_link, 'admin' ), $subsite, $mode, $id, $submode;

      - tye        

Re^2: Secret Perl Operators: the boolean list squash operator, x!! (grep disqualified)
by Aristotle (Chancellor) on Aug 02, 2006 at 15:51 UTC

    OK, so my example only used single-element lists, and most conditions were similar, so it was an insufficiently ornery problem to show that only the ternary and push are generically appropriate. Here’s an example to disqualify grep:

    my $name = join '-', ( @prefix, ( $do_use_path ? split /:/, $path : () ), $name, $suffix, );

    The only way I can think of to write that with grep is thus:

    my $name = join '-', ( @prefix, ( map @$_, grep { $do_use_path } [ split /:/, $path ] ), $name, $suffix, );

    D’oh, I see it now. Hmm…

    That looks a lot worse than the ternary to me. grep is fine for problems with enough regularity, but when regularity is absent (here trivially achieved by having only a single conditional sublist, so there’s nothing to abstract), ternary/push/x!! is necessary – and of these, only x!! requires no unnecessary verbiage:

    my $name = join '-', ( @prefix, ( split /:/, $path ) x!! $do_use_path, $name, $suffix, );

    I wish modifiers could be applied to expressions, then this would be crystal clear to write:

    my $name = join '-', ( @prefix, ( split /:/, $path ) if $do_use_path, $name, $suffix, );

    Makeshifts last the longest.

      Update: You appear to be updating your reply significantly without noting the updates so this reply does not yet reflect any of these updates. I may choose to update or reply again after your node content appears to have settled down. I've now quoted your entire original response as seen when I started replying to it:

      OK, so my example only used single-element lists, so it was an insufficiently ornery problem to show that only the ternary and push are generically appropriate. Here’s an example to disqualify grep:
      my $name = join '-', @prefix, ( defined $path and length $path ) ? ( s +plit /:/, $path ) : (), $suffix;

      Not at all. Where did you get the idea that grep can't handle more than one item in a list?

      To repeat myself, the following three constructs are interchangeable:

      ( LIST ) x!! COND ( grep COND, LIST ) COND ? ( LIST ) : ()

      except that only the middle one doesn't require an extra set of parens in some rare cases and only the last one short-circuits evaluation of LIST if COND is false (and perhaps some other more subtle differences, I suspect, though none occur to me at the moment).

      (Update: And the second may evaluate COND more than once.)

      So, I don't see much recommending the first choice over the second (two keystrokes is hardly a worthy deciding factor) and find the less-than-typical use of grep to be less confusing than the invention of an "x!!" "operator". So I'd use grep rather than x!! if I had reason to not use the third option or even the clearer conditional use of push or some other solution (such as filtering out undefined values as already demonstrated).

      So your new example can be rewritten as:

      my $name = join '-', @prefix, ( grep { defined $path and length $path } split /:/, $path ), $suffix;

      to demonstrate the use of the second option on a list that might contain more than one item.

      Trying to rewrite that using the first option will likely cause you new problems because of your use of "and" (which I wouldn't use in a such a simple Boolean expression, since "&&" is better suited for that task). Perhaps your new idiom needs to be renamed "( ()x!!() )" to not make it error-prone? (:

      And note that $path being undefined would result in a warning (if enabled) in both my grep construct and your x!! construct. So I doubt I'd use either in that particular case.

      Since split on an empty string returns an empty list, for this particular case I'd likely instead use:

      ( split /:/, $path || '' ),

      but replacing "||" with "//" (or a suitable replacement) if $path might be "0".

      Update: And I find it telling that when your update added an actual use of "x!!", you went and removed your use of "and" to avoid demonstrating this weakness in your idiom. :)

      - tye        

        You appear to be updating your reply significantly without noting the updates

        Yes, I do that relatively frequently on non-root nodes within the first couple minutes of their existence. In this case –

        I find it telling that when your update added an actual use of "x!!", you went and removed your use of "and" to avoid demonstrating this weakness in your idiom.

        – it was to remove easy ways of just using split unconditionally, as in your ( split /:/, $path || '' ) suggestion.

        Grmf.

        Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://564872]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2014-07-25 23:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (175 votes), past polls