develooper Front page | perl.perl5.porters | Postings from February 2020

Re: chained comparisons

Thread Previous | Thread Next
February 5, 2020 17:15
Re: chained comparisons
Message ID:
On Wed, 5 Feb 2020 at 13:13, Smylers <> wrote:

> Zefram writes:
> > Branch zefram/cmpchain at <git://> may be
> > of some interest.
> Nice — that's definitely of interest! Thank you.

Agreed a million times over.

> A few small doc suggestions. Re:
>   A sequence of relational operators, such as
>   S<C<"$a E<lt> $b E<lt>= $c">>, does not group in accordance with left
>   or right associativity, which would produce the almost-useless result
>   of using the truth-value result of one comparison as a comparand in
>   another comparison. Instead the comparisons are I<chained>: each
>   comparison is performed on the two arguments surrounding it, with each
>   interior argument taking part in two comparisons, and the comparison
>   results are implicitly ANDed.
> • I think for somebody first encountering this feature, it's more useful
>   to state what it does, before what it doesn't.
>   Specifically “You can chain operators like $a < $b <$c” is
>   conceptually quite easy to understand, even for beginners.
>   Thinking about what that would do were it not for chaining, involving
>   associativity and the truth value of one comparison being used in
>   another, isn't necessary in order to be able to use chaining, as well
>   as being harder to think about.

I think this is pretty reasonable feedback. If Zefram doesn't push a
doc-fix I will. I do think there is some use to explain the difference, but
after explaining the point. Someone used to the standard formulation might
think it is syntactic sugar for the expanded expression, but it is more
clever than that.

> • The word ‘comparand’ doesn't currently appear anywhere else in Perl's
>   docs. It's a bit jargony, and may be offputting to people unfamiliar
>   with the word. I haven't looked to see how comparand's are referred to
>   elsewhere in the docs, but if there's a reasonably concise alternative
>   which can be used, that may be better.

I'm inclined to think that "dumbing it down"[1] will actually be
counter-productive and make the docs less clear not more. As the saying
goes "everything should be as simple as possible but not simpler".

A quick google search for "operand" shows it is at least somewhat well
known in the fields of computing and linguistics, and its pretty easy to
guess its meaning if one is familiar with the mathematical term "operand".

[1] Quotes because I can't think of a better way to summarize your request,
not because you said that

> And in this bit:
>   Thus S<C<"$a E<lt> $b E<lt>= $c">> behaves very much like
>   S<C<"$a E<lt> $b && $b E<lt>= $c">>.  The ANDing short-circuits just
>   like C<"&&"> does, stopping the sequence of comparisons as soon as one
>   yields false. Each argument expression is evaluated at most once, even
>   if it takes part in two comparisons.
> • “very much like” suggests it isn't identical, but doesn't precisely
>   state the difference(s). The common expression only being evaluated
>   once is a difference, but it would be clearer to specifically label it
>   as such, and also state if that's the only difference or there's
>   something else than hasn't occurred to me.

It does say the difference. The arguments are evaluated once, not twice.

Consider if $x is replaced with an expression like do { $n++; $x}

So with this feature we can write:

if (1 < $x < 10) {}

without it we would have to write:

if (1 < $x && $x < 10) {}

if we substitute in the do{} expression we would have

if (1< do{ $n++; $x} < 10) {}
if (1<do{$n++; $x} && do{$n++; $x} < 10) {}

the side effect would be that $n would be incremented by 1 with the new
logic, and with the old logic it would be incremented by 2. Consider if $x
is implemented as tied scalar, it would call FETCH once, not twice, etc.

  It may also be worth giving an example of where avoiding double
>   evaluation makes a difference, to illustrate that chaining isn't just
>   a minor syntactic convenience but can have other benefits.

Consider if $x is replaced by do{ sleep(1); $x} to represent an expensive
function. The new logic would sleep for 1 second, the old would sleep for 2.

Basically it means you can write

if (1 < expensive_function < 10) {}

and have it perform the same as

my $tmp= expensive_function();
if (1<$tmp && $tmp < 10) { }

Does this cover your concerns? I begged Zefram for this feature so I feel
obliged to help with shepherding it into Perl, including any doc fixes.

> Thank you again for implementing this.


perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About