Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Ternary vs. Sort vs. Max

by QM (Parson)
on Aug 10, 2015 at 09:23 UTC ( #1137981=perlmeditation: print w/replies, xml ) Need Help??

A line in BrowserUK's post reminded me of one of my cobwebs that I'm always chasing, namely, whether the Conditional Operator, ?:, is preferable over sort. In the end I should import a max function when possible, but I don't always do so.

Conditional operator:

my $n = $x > $y ? $x : $y;

I find this awkward to read, and it also duplicates the variable names.


my $n = (sort {$a <=> $b} $x, $y)[-1];

But because sort needs a numeric sort function, that's a bit long winded.

And the max function:

use List::Util qw(max); my $n = max($x, $y);

Which seems to be the laziest and preferred way.

Quantum Mechanics: The dreams stuff is made of

Replies are listed 'Best First'.
Re: Ternary vs. Sort vs. Max
by GrandFather (Sage) on Aug 10, 2015 at 09:30 UTC

    The max version has the huge advantage that it actually says what the intent of the code is. The other variants require at least some pattern recognition or, worse, some thought to interpret.

    Premature optimization is the root of all job security
      worse, some thought

      Dog forbid that programmers should expend some thought.

        The wetware also only has a certain capacity, why waste it on something that can easily be made cheaper to process?

        Enoch was right!
        Enjoy the last years of Rome.

Re: Ternary vs. Sort vs. Max
by Tux (Abbot) on Aug 10, 2015 at 09:44 UTC

    I personally prefer the ternary as it involves no overhead of extra scopes, loading modules and/or function calls: it is fast, obvious and clear (at least if you are acquainted with ternary syntax).

    Your worry about duplicating the value is only important if the implementation of ternary is such that it actually invokes the FETCH on the variable twice (in any language), which can be problematic is the value is overloaded and does magic on fetch.

    Calling sort could suffer the same, depending on the implementation.

    Enjoy, Have FUN! H.Merijn
Re: Ternary vs. Sort vs. Max
by BrowserUk (Pope) on Aug 10, 2015 at 10:38 UTC

    That sort construction is (IMO) far more obscure and obfuscate than the ternary.

    As for List::Util::max(); if I need to find the max() of a bunch (more than two) things, I use it, but -- just as my wife doesn't break out her food processor to slice a tomato for a sandwich -- for two items, the ternary construct is simple, efficient (and to me; clear). Perfect for the task at hand.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
    I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!
Re: Ternary vs. Sort vs. Max
by shmem (Chancellor) on Aug 10, 2015 at 10:31 UTC

    Just for the sake of TIMTOWTDI:

    $max = ($x,$y)[$x<$y]; $min = ($x,$y)[$x>$y];

    which is a golfed version of your 2nd variant: (sort-of) a one-step sort which eliminates building a code block frame and the call of sort. Ternary is cheaper, since it doesn't involve bulding a list.

    I've been working at a place where restrictive coding standards prohibited ternary and forced me to write

    if ($x < $y ) { $max = $y; } else { $max = $x; }

    - which is as cheap as ternary (I guess) but looks convoluted to me - among other hilarities. Good riddance.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      if ($x < $y ) { $max = $y; } else { $max = $x; }

      When faced with the need to write a similar construct (e.g., the condition is too long to make an easily scannable ternary or the like), I find it easier to Just Pick One and then write one conditional, like

      $max = $x; if($x < $y) { $max = $y; }

      Aside from shorter, I find it actually more descriptive, especially if the other side is an else rather than elseif; "x except when y" as a description reads just like the code.

Re: Ternary vs. Sort vs. Max
by Athanasius (Chancellor) on Aug 10, 2015 at 14:08 UTC

    Hello QM,

    Another — possibly heretical? — option is to make max an inline function using a module such as macro:

    #! perl use strict; use warnings; use macro max => sub { $_[0] > $_[1] ? $_[0] : $_[1]; }; my $x = $ARGV[0]; my $y = $ARGV[1]; my $m = max($x, $y); print "max is $m\n";


    0:05 >perl 17 12 max is 17 0:05 >perl -MO=Deparse Compiling by macro::compiler/0.06 ... sub Digest::base::new; sub Digest::base::clone; sub Digest::base::add; sub Digest::base::digest; use macro ('max', sub { use warnings; use strict; $_[0] > $_[1] ? $_[0] : $_[1]; } ); use warnings; use strict; my $x = $ARGV[0]; my $y = $ARGV[1]; my $m = $x > $y ? $x : $y; print "max is $m\n"; syntax OK 0:05 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Hi Athanasius,

      The macro is indeed interesting, as I've not delved in there before.

      However, that may suffer from techical debt. If I define a max macro that only handles 2 values, I (or my replacement) may call it later and give it 3 values, and only get the max of the first 2. Still, some careful coding (probably duplicating List::Util's max) could ensue.

      Edited to add:

      Also, it seems the macro syntax uses significant whitespace, which bugs me.

      Edited to add (2):

      The macro doc page has this:

      use macro add => sub{ $_[0] + $_[1] }; say => sub{ print @_, "\n"}; say(add(1, 3)); # it's replaced into 'print do{ (1) + (3) }, "\n";'
      which I'm assuming uses significant whitespace to figure out that say is a macro. (Or there's a typo semicolon on the first line.)

      Quantum Mechanics: The dreams stuff is made of

        It’s just a typo:

        19:13 >perl Useless use of a constant ("say") in void context at line 6. Useless use of single ref constructor in void context at line 6 +. Undefined subroutine &main::say called at line 7. 19:39 >

        Whereas with a comma instead of the semicolon:

        19:39 >perl 4 19:41 >perl -MO=Deparse Compiling by macro::compiler/0.06 ... sub Digest::base::clone; sub Digest::base::new; sub Digest::base::digest; sub Digest::base::add; use macro ('add', sub { use warnings; use strict; $_[0] + $_[1]; } , 'say', sub { use warnings; use strict; print @_, "\n"; } ); use warnings; use strict; print 4, "\n"; syntax OK 19:41 >

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Ternary vs. Sort vs. Max
by eyepopslikeamosquito (Chancellor) on Aug 11, 2015 at 03:26 UTC

    For completeness, the preferred "artistic" solution:

    my $n = [ $y => $x ] -> [ $x >= $y ];
    BTW, this coding style question is discussed in the "Cleverness" section at the bottom of The Boy Scout Rule.

Re: Ternary vs. Sort vs. Max
by sundialsvc4 (Abbot) on Aug 10, 2015 at 11:57 UTC

    The basic problem in this example, though, is that none of these three examples are actually equivalent!   And the second one, sort, is also unnecessarily inefficient.

    (1)   The ternary operator is a slightly-abbreviated if..then..else statement; a well-known and convenient special case but otherwise equivalent.   In the intended use-case, you are comparing two values, and choosing one or the other, with the intent of one of these two values being “the result.”   The comparison can, however, can be anything.

    (2)   There is no reason to sort a list to find the largest value that is in it.   Only a single, sequential pass through all of the entries is ever required to find both the largest and the smallest values in any list, as you can effortlessly demonstrate with any deck of cards.

    (3)   Functions like max() have the added advantage of instantly saying what they mean ... and also of being associated by-reference with existing code that can be trusted to actually and correctly do what they say.

    When you say, “ternary vs. sort vs. max,” you are listing three entirely different things that might be called-for in three completely different cases.   These three things are not equivalent.

      The basic problem in this example, though, is that none of these three examples are actually equivalent!

      That's not the basic poblem, that's the whole point of it: list three different ways to do the same thing, argue, which is best for the case at hand.

      If the three ways were equivalent, the whole case would be about syntactic sugar only, hence pointless.

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      The basic problem in this example, though, is that none of these three examples are actually equivalent!

      They accomplish the same thing in different ways... what definition of "equivalent" are you using here?

        They are equivalent for finding the max of only two values, but a single ternary operator can't be used when there are more than two values or when the number of values is not known in advance. But for only 2 values, I prefer the ternary operator.

        Then, for more values, I would not be too reluctant at using sort for just a handful of values, but I would avoid it for a large list because of the overhead. So, in that latter case, I would rather use the List::Utils max function, or roll my own sequential iteration through the list if the type of max I am looking for is something more complicated than just the largest number in a list (or perhaps use the List::Utils handsome reduce function with a appropriate code block).

Re: Ternary vs. Sort vs. Max
by sundialsvc4 (Abbot) on Aug 10, 2015 at 23:16 UTC

    If “that’s the whole point of it,” as you say, then I can’t speak to that.   (And, mind you, I do not intend in any way to judge that.)   All that I can say is that I believe one should always look for the simplest, the most obvious, and of course the reasonably least-expensive way to do something.   “If what you are doing should require no thought, pretty-please don’t make me think about it.”

    For instance, if you want to find the largest value in a list ... say, the largest card in your poker hand ... then you do not need to sort the list to find that out.   Your eyes can make a single furtive glance over your hand, and now you know.   Therefore, I would not ask the computer to perform any extra work for me, if it would not pay off otherwise.

    As for the other two, ternary operators work really well in the place where (I think) they were intended:   when you want to make a simple, either/or choice in an arithmetic expression.   But, I always want to see my “glance rule” clearly upheld.   I want to always see, “at a glance,” exactly what I expect to see.

    I like things like max() simply because they are nice and expressive.   They clearly say what is “the designer’s intent.”   In most languages they will do just the right thing, efficiently.

    As an aside, I encountered one programming language ... HP/2000 Access BASIC ... which had a MAX/MIN operator.   It was so very expressive ... such a nice feature.

      Replied to the wrong post again. If I were a cop I'd be doing a field sobriety test on you at this point.

      Only one language with min/max, huh? Ever use SQL? I understand it's a bizarre, fringe language used by nearly no one but maybe you've heard of it.

        Are you really serious, “Mom?”

        Pardon me, ladies and gentlemen, while I “ROTFMAO™” ... and conclude, most graciously, that seriousness in this matter simply cannot be possible.

        O-p-e-r-a-t-o-r-:   a unary or binary element within an arithmetic expression, viz:

        445 IF (A MAX B) > 5 THEN 550

        It very elegantly captures the most-common use case for a ternary operator, without requiring a function-call having two or more arguments (which that language did not support).

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1137981]
Approved by GrandFather
[Corion]: "Unmatched ) in regex; marked by <-- HERE in m/(&#9583;&# 9633;)&#9583;&# 65077; &#9531;&#9473;&# 9531;) <-- HERE / at -e line 1." :)
[Corion]: Meh - my "flip the table" string doesn't render here ;)
[choroba]: It renders correctly in pm-cb-g
[erix]: heh

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (8)
As of 2018-07-17 16:08 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (372 votes). Check out past polls.