Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Simple Q. for You

by Dan-Y (Initiate)
on Mar 16, 2018 at 00:08 UTC ( #1211005=perlquestion: print w/replies, xml ) Need Help??

Dan-Y has asked for the wisdom of the Perl Monks concerning the following question:

return 1 if ( $d->{foo} && $d->{foo} =~ /X/i ) What does this line mean? I can vaguely understand it, but want to make sure. Keep in mind I'm a new Perl programmer, just signed in, so forgive me if it looks obvious to you. Thank you in advance!

Replies are listed 'Best First'.
Re: Simple Q. for You
by trippledubs (Deacon) on Mar 16, 2018 at 01:55 UTC

    There's a lot going on. It kind of does what it reads like it should do in English, return 1 if (this and that). If either this or that is not true, keep going and do not return 1. That's pretty much what you need to know to use it effectively and correctly. The first condition is probably there just to avoid a nasty warning you'll get if foo is undefined.

    But hey, let's complicate things. You have a postfix conditional followed by a boolean context evaluation with two conditions. If the first condition is true, evaluate the second. If they both evaluate to true, the whole evaluation is true and then you can return 1.

    The first condition checks if  $d->{foo} is true or false. You're dereferencing foo out of scalar variable $d first, if that is either the number 0, 'the strings 0 or "", the empty list, or undef, it's false.

    If the first condition is false, the && returns false for the evaluation and does not evaluate the second condition.

    The second condition is a regular expression match to decide if $d->{foo} contains the letter x in either uppercase or lowercase.

      As a further supplement to trippledubs post, here's a small script you can play around with:
      use strict; use warnings; my %h = (foo => 'oxen'); my $d = \%h; print test_it(), "\n"; sub test_it { return 1 if ( $d->{foo} && $d->{foo} =~ /X/i ); return 0; }
      As trippledubs touched on, if the second condition is met then the fist condition will also inevitably be met. Hence, the script will function perfectly well if the first condition is omitted - except that it would then also print a warning if $h{foo} is not defined.

Re: Simple Q. for You
by Your Mother (Archbishop) on Mar 16, 2018 at 03:04 UTC

    And if you do (and you really should) play around with it, see how concise and idiomatic Perl can be. This does the same (provided it's the final statement in the sub and you might need to turn off uninitialized warnings depending on how it's called). Using syphilis's example as a base–

    sub test_it { $d->{foo} =~ /X/i; }
Re: Simple Q. for You
by haukex (Bishop) on Mar 16, 2018 at 08:46 UTC
    return 1 if ( $d->{foo} && $d->{foo} =~ /X/i )

    Most of the following has already been covered by trippledubs, but let me lay it out in order:

    1. Something if Something is a statement modifier. That line of code is the same as

      if ( $d->{foo} && $d->{foo} =~ /X/i ) { return 1 }

      so let's look at it in that order. (Statement modifiers can make Perl read a lot more like English.)

    2. The first part of the if condition is $d->{foo}. ->{...} dereferences a hash reference (see perlreftut), in other words, $d is a reference to a hash, and we're asking Perl to look up the key foo in that hash.

    3. Since in the first part of the condition we're not applying any other operators other than &&, this means we are checking for whether $d->{foo} holds a true or a false value. Why would we want to do this? Most likely, because if $d->{foo} was undef, Perl would issue a warning later on when we use the =~ operator (more on that below). This also applies if the hash did not even contain a key foo - in this case Perl would also return undef for that key. (Note: You can check for undef explicitly with the defined function, and check for the existence of a hash key with exists. The fact that this code does not use these means that if $d->{foo} were to hold the value "0", then that would still be evaluated as "false". But since this code is looking for "X", that should not be a problem in this case.)

    4. The && operator "short-circuits", meaning that if the left side is false, the right side does not even get executed and tested, because if the left is false, we already know that the whole && will be false. If the left side is true, then the operator will test the right side.

    5. In the right side of the condition, $d->{foo} =~ /X/i, the =~ operator basically applies the regular expression /X/i to the string value of $d->{foo}.

    6. The regular expression (see perlretut) /X/i basically means "find X case-insensitively" - the /i is a "modifier" on the regular expression /X/ that turns on case-insensitive matching.

    7. The return statement will return the value 1 from the subroutine (or similar block) it is inside of, aborting its execution at that point (see also perlsub).

    So taking all of that together, that line of code reads as "return 1 if the hash referenced by $d contains a key foo with a true value that also contains the string X (case-insensitively)".

    Update 2019-08-17: Updated the link to "Truth and Falsehood".

Re: Simple Q. for You
by Dan-Y (Initiate) on Mar 19, 2018 at 05:33 UTC
    I love this forum. You guys are great. Learned a lot from you all. Thank you! (I hope I wrote this response in the proper location)
Re: Simple Q. for You
by Anonymous Monk on Mar 16, 2018 at 14:02 UTC
    Also, the && bit is an example of short-circuit logical expression evaluation, which is a fairly standard feature of most languages. Since "false AND anything" is always False, the right-hand side of the expression won't be evaluated at all if the left-hand side is determined to be false. (It, so to speak, instead "takes the short circuit.") The programmer is using this to avoid referencing a property of something that is in a hash if that thing isn't in the hash, thus avoiding a runtime error.

      Except of course that referencing a missing hash element is not a run time error, sundialsvc4. If the most basic features and behavior of Perl are mysterious to you, just let others do the answering. You're doing no favors to anyone, especially yourself.

      P.S. Exactly the same sort of short-circuit behavior occurs with regard to logical-OR, "||". If the left-hand side is determined to be true, the right-hand side is skipped since "True OR anything" is always True. You most-often see this in Perl as something like open(FD) or die("can't open"). If the file is opened successfully, the code won't die, and vice-versa.

        And I'm sorry to carry this on further since I know a lot of monks are willing to just drop it and are getting mad at me because I shan't but this aggression will not stand, man.

        haukex wrote a perfect—Perfect.—reply to the OP. It covered everything with linked citations and sample code. It's the ideal. Friendly. Comprehensive. Broke down the basics with references for further reading. Explained clearly in plain English. It was also just there to bolster two already terrific answers from trippledubs and syphilis. Everyone involved, including me, cited the previous posts to build each other up and show respect.

        Five and one half hours later you post not just one but two half-baked rehashes of it. Awful. Useless. Pointless. Helpless. Insulting. Shameful.

        Update: added missing verb. Maleducatto. Idiota. Che scemo.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1211005]
Approved by huck
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2021-03-04 19:53 GMT
Find Nodes?
    Voting Booth?
    My favorite kind of desktop background is:

    Results (107 votes). Check out past polls.