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!!

by blazar (Canon)
on Jul 17, 2008 at 22:32 UTC ( [id://698464]=note: print w/replies, xml ) Need Help??


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

The nicer approach with a ternary:

my @part = ( 'http://example.net/app', ( 'admin' ? $is_admin_link : () ), ( defined $subsite ? $subsite : () ), $mode, ( defined $id ? $id : () ), ( defined $submode ? $submode : () ), ); my $uri = join '/', @part;

Only now did I get at this very nice node of yours, brought here from some other recent one, and of course it's unusual to reply to a years old node, nor am I discussing the "boolean list squash operator" which is actually a good technique. (And I think I must have used it every now and again, even if not that regularly, and... I wouldn't have thought of giving it a name.)

I'm here just to discuss, for our beloved TIMTOWTDIness sake, how I would have probably done the damned thing in a reasonably real world situation. To be precise, I'm assuming here that it's isolated enough as a task not to warrant a separate sub, and that performance is not an issue. (Even if it were, you'll see I'm playing dereferentiation tricks, but I doubt that they could become that relevant wrt other factors...)

Said all this, probably I wouldn't have thought of the boolean list squash operator. I would have tried to "encapsulate" the component data and map it through some suitable code. Of course the problem is: which code? Of course, the answer is that there are tons of ways that work, but I also want something which is visually clear at a glance, and unobtrosive. I considered some possibilities involving nested ternaries which would e.g. distinguish refs from non-refs, and then arrayrefs with two elements from ones with one. Then I considered as an alternative chained map()s achieving the same effect for clarity at the expense of multiple looping where a single one would suffice. But then I wouldn't want two or three "header" lines of code only to suck up say other six. I really want at most one, and simple enough. Eventually, the best alternative I could think of is:

my @part = map defined $_->[-1] ? $_->[0] : (), ['http://example.net/app' => 1], ['admin' => $is_admin_link], [$subsite], [$mode => 1], [$id], [$submode];

Here:

  1. the additional visual "encapsulation" given by square parens allowed me to put several params on one line with no risk of confusing them;
  2. I forced a => 1 on elements that you were originally unconditionally inserting: since these were supposedly true, it's completely useless but possibly as a visual reminder that they are, and in turn this is silly for the constant item but may be sensible for $mode.

As a sort of counter-example, if I wanted the unconditionally inserted elements to be included in the list without the burden of the square parens, then it's obvious how to do it:

my @part = map +(ref) ? (defined $_->[-1] ? $_->[0] : ()) : $_, 'http://example.net/app', ['admin' => $is_admin_link], [$subsite], $mode, [$id], [$submode];

Here, the first line is getting long and confusing, and the absence of square parens around $mode also degrades readability.

--
If you can't understand the incipit, then please check the IPB Campaign.

Replies are listed 'Best First'.
Re^2: Secret Perl Operators: the boolean list squash operator, x!!
by grantm (Parson) on Jul 18, 2008 at 03:19 UTC

    Wouldn't it make more sense to have the contents of the square brackets the other way around? e.g:

    @part = map defined $_->[0] ? @{$_}[(@$_>1?1:0)..$#{$_}] : (), [1 => 'http://example.net/app', 'extra'], [$is_admin_link => 'admin'], [$subsite], [1 => $mode], [$id], [$submode];

    To my eyes, [ $condition => $value ] reads better.

    Also allows you to do: [ $condition => $list, $of, $values ]

      To my eyes, [ $condition => $value ] reads better.

      I personally believe that it's not that important: I gave a... wild shot, if you know what I mean. Of course one may want some sort of full fledged solution taking care of all possible cases. For the present situation, your expression is fine enough, but just that little much too complex wrt "mine." I may have used something like that too, of course.

      However, as a sort of justification, I was thinking much of the postponed condition in analogy with an if statement modifier, that can be thought of as an optional parameter and be there or not...

      Also allows you to do: [ $condition => $list, $of, $values ]

      And then again, one may want to do [ $value => @conditions ] instead: again It depends on the actual situation and there's not a clear-cut, all-encompassing answer. (There may be, if we wanted to make it into a real module, with a well thought API, and so on, but that's not the case...)

      --
      If you can't understand the incipit, then please check the IPB Campaign.
Re^2: Secret Perl Operators: the boolean list squash operator, x!!
by Aristotle (Chancellor) on Jul 19, 2008 at 09:54 UTC

    I find that a lot harder to read. It decouples the logic from the individual parts of the list so it only works at all for lists where nearly every part is conditional, like the example I gave. If you want to conditionally include only one thing in a much larger unconditional list it really breaks down. Contrast:

    join '/', 'foo', 'bar', $baz, 'quux', ( @qux ) x!! $somecond, $wibble, + $wobble; # vs join '/', map { defined $_->[-1] ? $_->[0] : () } ( [ 'foo' ], [ 'bar' ], [ $baz ], [ 'quux' ], [ @qux, $somecond ], [ $wibble ], [ $wobble ], );

    Maybe you find the second one easier to read than the first, but I don’t. It gets a little clearer with each element on its own line (in particular, the $somecond gets completely lost in the noise if you put several elements on each line), but then you’ve gone from a single line to 10.

    Your proposed solution is worth considering, but is useful only in limited circumstances. I was trying to find an option that would work in a wide range of cases.

    I have to note that my proposed composite operator ()x!! is not that option, either: it doesn’t shortcircuit (nor do any of the clever alternatives given, yours included), and that has killed it in every case I might have used it since writing this node. I might find the syntactical requirements of the ternary onerous, but another option – not even a better one, but any option at all – has yet to show up. Sigh.

    Makeshifts last the longest.

      I find that a lot harder to read. ... If you want to conditionally include only one thing in a much larger unconditional list it really breaks down.

      I personally believe that ease of reading is in the eye of the beholder, but as far as the second remark is concerned, of course it's fully seconded++. Long story made short - IMHO: no clear-cut, all encompassing solution. Just many different situations. (And incidentally, nothing which will take our sleeping away, I hope! ;)

      --
      If you can't understand the incipit, then please check the IPB Campaign.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-04-19 20:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found