Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Situation where warning "Found = in conditional, should be" seems obsolete

by rsFalse (Chaplain)
on Feb 06, 2021 at 09:43 UTC ( [id://11127970]=perlquestion: print w/replies, xml ) Need Help??

rsFalse has asked for the wisdom of the Perl Monks concerning the following question:

Hello,
I got a warning message "Found = in conditional, should be" after executing that code:
perl -wle 'my $has_even; @_ = -1 .. 9; for( @_ ){ print $_; $_ % 2 or +$has_even = 1 and last } print "\$has_even:[$has_even]"; '
OUTPUT:
Found = in conditional, should be == at -e line 1. -1 0 $has_even:[1]
Here '=' is intentional, so a warning is obsolete.
I think it is useful warning message to catch mistype. But in perlop operators 'and' and 'or' are not named being conditional. It is explained in other words (e.g. for 'and'): "the right expression is evaluated only if the left expression is true". In perlop document there is a section named "Conditional Operator", which is about ternary conditional operator. But it seems that it is not the only one conditional operator. So for clarity this section could be renamed to "ternary conditional operator". And also it could be added "a conditional operator" within description of 'and' and 'or'. Also a conditioness attribute could be shown in a widened attribute table (idea proposed in earlier node: For discussion: operator attributes - associativity, chainity and ability to short-circuit).

Back to a warning message. In my code instead of "$has_even = 1" it could be '$has_even = "TRUE"'. In that case a warning would seem even more obsolete because "TRUE" is not number-like.

Replies are listed 'Best First'.
Re: Situation where warning "Found = in conditional, should be" seems obsolete
by choroba (Cardinal) on Feb 06, 2021 at 09:59 UTC
    Are you sure you want to execute last only when $has_even = 1 is true? Using "and" would be confusing if you decide later to refactor the code and suddenly end up with
    $_ % 2 and $has_odd = 0 and last;
    or maybe the second "and" would be turned to "or", but it would be confusing anyway.

    More idiomatic way of writing this would be

    $_ % 2 or $has_even = 1, last;
    if you insisted on using no if/unless. I'd probably use
    $has_even = 1, last unless $_ % 2;
    but YMMV.

    Update: s/if/unless/. Thanks Athanasius.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Situation where warning "Found = in conditional, should be" seems obsolete
by Athanasius (Archbishop) on Feb 06, 2021 at 13:26 UTC

    Hello rsFalse,

    I suspect the warning is generated by an heuristic derived from the nature of the and operator, which interprets its operands as boolean values. Perl therefore expects the expression on the left hand side of the and to contain a boolean operator, such as ==, rather than the assignment operator. It is noteworthy that when the and is replaced by a comma, as in choroba’s preferred syntax, the warning disappears.

    You are probably correct in thinking that assignment of a non-numeric value should generate a warning of the form Found = in conditional, should be eq at.... However, perldiag contains no such warning: I guess Found = in conditional, should be == is considered sufficiently indicative of the (potential) problem.

    Hope that helps,

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

Re: Situation where warning "Found = in conditional, should be" seems obsolete
by LanX (Saint) on Feb 06, 2021 at 16:48 UTC
    Background: Short circuit and and or are semantically like if and unless in Perl, IIRC it's even the same op code.

    Personally I tend to avoid this C syntax outside one liners, where readability and maintenance are no issues.

    Now this warning is intended for conditionals.

    So if you don't like to straighten the syntax, you are free to disable this warning.

    update

    Especially chaining both operators without parens makes me second guessing precedence

    $_ % 2 or $has_even = 1 and last

    I don't wanna puzzle over such code.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      perlop is clear that and has higher precedence than or and this can be checked with B::Deparse and -p option

      $_ % 2 or ( $has_even = 1 and last )

      Like others already implied does $has_even = 1 and last not make much sense, since the assignment at LHS is always true.

      Furthermore is this a quite pathological case, because the part with the code-branch with higher precedence is never executed.

      compare

      DB<215> p 0 or 1 and 0 0 DB<216> p (0 or 1) and 0 1 DB<217>

      update
      DB<233> p 0 or 1 and die "never" 0 DB<234> p 0 or (1 and die "never") 0 DB<235> p (0 or 1) and die "never" 1never at (eval 265)[c:/Perl_524/lib/perl5db.pl:737] line 2. DB<236>

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

Re: Situation where warning "Found = in conditional, should be" seems obsolete (documentation)
by LanX (Saint) on Feb 06, 2021 at 17:35 UTC
    > But in perlop operators and and or are not named being conditional.

    https://perldoc.perl.org/perlop#Logical-And

    Binary "and" returns the logical conjunction of the two surrounding expressions. It's equivalent to && except for the very low precedence. This means that it short-circuits: the right expression is evaluated only if the left expression is true.

    https://perldoc.perl.org/perlop#C-style-Logical-And

    Binary "&&" performs a short-circuit logical AND operation. That is, if the left operand is false, the right operand is not even evaluated. Scalar or list context propagates down to the right operand if it is evaluated.

    what do you mean by "named being conditional" and how could the description be clearer?

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      > what do you mean by "named being conditional" and how could the description be clearer?

      This problem is borrowed from C, which was one of the templates for designing Perl

      "Conditional operator" seems to be the original term for the "ternary operator"

      I have an almost original copy of Kernighan/Ritchie in my bookshelf - though in German - and it's introduced as "Conditional Validation" ("Bedingte Bewertung")

      I agree with you that the name is unfortunate and I've never heard using it in Perl's context. "Ternary Operator" is the "normal" term.

      I'd suggest:

      changing the title to "Ternary Operator" and appending an example exemplifying the analogy to if-then-else

      https://perldoc.perl.org/perlop#Conditional-Operator

      * Ternary Operator

      Ternary "?:" is like the conditional operator in C.

      It works much like an if-then-else. ... yadda yadda ..

      $max = ($a > $b) ? $a : $b

      has the same effect like

      $max = do { if ($a > $b) {$a} else {$b} }

      I'd also add similar code examples to and , && , or and ||

      • "It works much like an if-then"
      • "It works much like an unless-then"

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        I agree with you.
        You gave a good answer instead of me :)
        >>what do you mean by "named being conditional"
        I mean that when I press CTRL+F and ask for "condit..." in perlop it didn't land into 'and', 'or' sections.
        By the way a warning warns about '=' been found inside "conditional", so an operator 'and' worked with "conditional". Sorry if I'm not pretty good at understanding english.

        And how about replacing infamous variable names '$a' and '$b' with foo/bar or so.

        UPD.: I changed my mind and now I disagree with '?:' naming 'Ternary operator' and suggest explicitly name it 'Ternary conditional operator'. Because I think that the name 'ternary' is too abstract and meaningless (it only says about how much operands it operates on). OK, it is the only ternary operator by now, but why not future Perl include other ternary operators?!
      Then maybe there should be the only one description?!

      I mean that it is enough to describe one operator, and only get a link to it with explanation that difference is only precedence. This would become SPOT - single point of thuth.

      I suggest to rename these two groups of operators.
      1. They are EQUIVALENT except for their precedence, that means that they are both C-style or both not-C-style. Am I right?
      2. The name of operators should differ in the way they differ from each other, so I suggest for example: 'Low-precedence-Logical-And' and 'High-precedence-Logical-And'.
      3. As 'and' ('or') operates on so called "conditional" (on its left side) and also it returns the last evaluated expression (or so), I suggest further to rename it from 'Logical-And' to something else, if someone can find more suitable name. E.g. I would suggest 'Conditional-And' (therefore 'High/Low-precedence-Conditional-And'), how does it sound?

      Also I suggest to make a link from documentation of operator 'and' to the documentation of statement 'if then' or vice versa. Why? For having SPOT. All the same behavior in one place, except for explanation of differences(?) (as I know they are not fully equivalent, because we can not use the return value of 'if' directly (e.g. we needs to envelope it with do{ })).

      How do you think?

      Upd.: Oh... I just realized that I made a suggestion (in 3rd point) the same as it is used in Java as you wrote earlier :( (Re^4: Situation where warning "Found = in conditional, should be" seems obsolete (documentation - C terminology)).
        Also I want to suggest another thing in documentation, which is a bit related:
        Now in documentation there is a section 'Logical or and Exclusive Or' - https://perldoc.perl.org/perlop#Logical-or-and-Exclusive-Or. Both operators 'or' and 'xor' has the same precedence. But I think they differ from each other by significant: 1) one short-circuits, another - doesn't, 2) one - returns only 1 or ''/0, another returns last expression (in case of left expression it is returned evaluated). I suggest to split it into separate sections.
        As they were both in one section, I though of their similar behavior, and once I thought 'xor' will return last expression not 1 or ''/0 (related node: 'xor' operator is not a sibling to 'or' and 'and'?).
Re: Situation where warning "Found = in conditional, should be" seems obsolete
by GrandFather (Saint) on Feb 08, 2021 at 20:04 UTC

    You need to fill up the character hopper on your keyboard so you can be more extravagant and expressive with your code. If this is code from a golf competition sure, do nasty stuff, but suck it up when things grump at you. If this is code for any other purpose take the time to write clear maintainable code.

    And don't bother with the "time it takes to type" argument. In writing, reading and replying to this thread you have already used more time than you will ever save in keystroke time writing obfuscated code instead of maintainable code. Actually, you will save more time just in being able to understand what you wrote more quickly in the future (say, ten minutes from when you wrote it) than you lose by spending more time typing.

    And in case you think that one complicated line is easier to understand than several shorter lines, especially where important stuff is at the end of the line, then you would be wrong because it isn't true despite what you might wish.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
      Hello.
      I will spend (waste?) more time for answer this thread. You may not interpret that code as obfuscated or intentionally obfuscated. Secondly obfuscation is a point of view, e.g. it depends on reading/writing style, which differs as Perl greets TMTOWTDI idiom; and it depends on demands of maintainability (which are not mentioned in this node).
      This node is not about obfuscation nor about code maintenance. It is more about warning, its significance and about operators which throws it.
        I will spend (waste?) more time for answer this thread.

        Not a waste of time. Robust discussion of style issues in the context of code maintainability, without getting inflammatory, is time well spent in a public forum such as this.

        You may not interpret that code as obfuscated or intentionally obfuscated.

        I don't understand that.

        Secondly obfuscation is a point of view, e.g. it depends on reading/writing style, which differs as Perl greets TMTOWTDI idiom; and it depends on demands of maintainability (which are not mentioned in this node).

        I agree it is somewhat a point of view. That is, there is a large murky area between two reasonably clear extremes. And context plays a large part in where it is reasonable to draw a line between what is acceptable practice and what is not. In the context of a one liner as demonstrated above maintenance is not an issue and whatever gets the job done is fine. In that case though warnings are not an issue either so where's the problem? In longer lived code the warning plays an important role - it is pointing out bad practice that, in my view, always serves to obscure the intent of the code and always makes maintenance harder. While TMTOWTDI applies on a fine scale, my interpretation of TMTOWTDI is that Perl as a language allows different programming paradigms rather than locking programmers into "one true way" style coding. That is, TMTOWTDI addresses functional versus OO versus procedural and other high level style choices and to a lesser extent choices other languages don't offer like high and low priority operators and use of statement modifiers. TMTOWTDI is largely orthogonal to code maintenance discussions.

        This node is not about obfuscation nor about code maintenance. It is more about warning, its significance and about operators which throws it.

        The significance of the warning is exactly about code maintenance and obfuscation. In places where the warning doesn't matter such as one liners and deliberately obfuscated code, ignore the warning. In any other context, fix the code. The warning is your friend.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re: Situation where warning "Found = in conditional, should be" seems obsolete
by rsFalse (Chaplain) on Feb 09, 2021 at 00:33 UTC
    For complete picture I want to share findings that this warning does appear if (1) right side of an assignment '=' operator contains a "constant" (i.e. number, string), except 'undef'; And the warning does not appear if (2) the left side of an assignment operator '=' is enclosed with parentheses or if it is an array. I think it is desired behavior. Of course if some coder have wanted to compare his array with a number (e.g. @_ == 5, i.e. if a number of elements of an array equals to 5) and he accidentally put one '=' instead of '==', warning won't appear; And example:
    perl -wle '@_ = -1 .. 3; for( @_ ){ print $_; ( ) = 0 or last }'
    OUTPUT:
    -1 0 1 2 3
    No warning.
    Note that 'last' never executed because of: an assignment operator works as "list assignment operator" (because of parentheses on the left side of the '='), and an operator 'or' asked for scalar context. In scalar context list assignment operator returns a number of elements of the right side (i.e. one element: '0').

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11127970]
Approved by davies
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-25 05:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found