http://qs1969.pair.com?node_id=1086115

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

Hello, I am breaking my head, why this works:
if(@files && ! scalar keys %tree){$isChanged = 1;} else{foreach my $file (@files){$isChanged = 1 && last if( grep { $ +files_cached{'stats'}{$file}{$_} != $params->{'files'}{'stats'}{$file +}{$_} } ('mtime', 'ctime', 'size') );}}
, but this gives a syntax error:
(@files && ! scalar keys %tree)? ($isChanged = 1): (foreach my $file (@files){$isChanged = 1 && last if( grep { $file +s_cached{'stats'}{$file}{$_} != $params->{'files'}{'stats'}{$file}{$_ +} } ('mtime', 'ctime', 'size') )});
...?...
I checked and rechecked, but didn't find any paretacy or semicolon missing or extra.
Thanx in advance.
Here is an uncondenced version of the if code:
if(@files && ! scalar keys %tree){ $isChanged = 1; }else{ foreach my $file (@files){ $isChanged = 1 && last if( grep { $files_cached{'stats'}{$file +}{$_} != $params->{'files'}{'stats'}{$file}{$_} } ('mtime', 'ctime', +'size') ); } }

New question:
I tried to convert an expression to using map:

(@files && ! scalar keys %tree)? ($isChanged = 1): (map { my $file = $_; if( grep { $files_cached{'stats'}{$file}{$_} + != $params->{'files'}{'stats'}{$file}{$_} } ('mtime', 'ctime', 'size +') ){$isChanged = 1; last;} } @files);
Now I'm curious, I cannot break out of map execution in the middle, using last or some other means. It will process an entire list to the end? It appears that the last statement in the above code will break out of the loop, containing the map command, not from the map itself, so, I've had to remove last from the code above:
(@files && ! scalar keys %tree)? ($isChanged = 1): (map { my $file = $_; $isChanged = 1 if( grep { $files_cached{'sta +ts'}{$file}{$_} != $params->{'files'}{'stats'}{$file}{$_} } ('mtime', + 'ctime', 'size') ) } @files);
Am I correct, if so, is there actually a way to breakout of map?

Replies are listed 'Best First'.
Re: conditional statement works one way, but not the other
by moritz (Cardinal) on May 15, 2014 at 08:58 UTC

    Please think of the poor programmer who comes after you and has to maintain the code. Don't try to cramp everything into one statement, it makes it much harder to read.

    A good rule of thumb for readability is that an assignment should (nearly) always be s separate statement, and not part of some expression.

      To everybody, who says, my code is hard to read, obfuscated:
      At first, I did a normal code with line breaks and indentations.

      It's my programming style to condense code blocks, only if they have one statement inside of it. To me, it actually makes easier to understan the program from the big perspective, when the program has a lot of code. When I see one line, that performs some simple action, it's easier for me to understand the program from the whole code perspective, then to folow one simple action line-by-line and not being sure if the program is at the next logical step, or still at the current action. It actually allows me to get rid of or simplify the comment description at certain points of code. I've noticed, when comments don't distract the code, in certain cases, it's easier to understand it's structure.

      I tried to run an uncondensed code, but it has the same problem.
      thanx for criticizm.

        If you feel the need to write condensed code to not obscure the structure of your code, you might be better served by giving parts of your program well-chosen names (in the form of subroutines or methods).

        That way it's easier to understand the bigger picture, and you don't need to condense code, because each subroutine will be much smaller.

Re: conditional statement works one way, but not the other
by choroba (Cardinal) on May 15, 2014 at 08:41 UTC
    You can't use for/foreach in an expression. You can replace it with map easily, though.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanx for the tip, I didn't know or didn't remember that I couldn't use for/foreach in an expression.
      I will consider mapping it.
Re: conditional statement works one way, but not the other
by kcott (Archbishop) on May 15, 2014 at 09:09 UTC

    G'day igoryonya,

    "but this gives a syntax error"

    When you get errors, please post them.

    "I checked and rechecked, didn't find any parentacy or semicolon missing or extra."

    I'm fairly certain that whatever error you got said nothing about parentheses or semicolons. The error was probably more like these:

    $ perl -Mstrict -Mwarnings -le '1 == 0 ? 1 : (for (1) { 1 })' syntax error at -e line 1, near "(for " Execution of -e aborted due to compilation errors.
    $ perl -Mstrict -Mwarnings -le '1 == 0 ? 1 : (while (1) { 1 })' syntax error at -e line 1, near "(while" Execution of -e aborted due to compilation errors.

    I suspect you may be confusing conditional statements (e.g. using if) with the Conditional Operator which takes operands, not Compound Statements.

    Writing code the way you have is highly error-prone. It's very difficult to read and a maintenance nightmare. Please read the "Perl Style Guide" — you may also find perltidy useful.

    -- Ken

Re: conditional statement works one way, but not the other
by Bloodnok (Vicar) on May 15, 2014 at 10:39 UTC
    I can't help but agree with moritz - unless you're deliberately going for an obfuscation award, make it maintainable - in that way, the folks that have to pick the code up after you're done will thank and not berate, you.

    A user level that continues to overstate my experience :-))

      "Berate" if you're lucky!

Re: conditional statement works one way, but not the other
by LanX (Saint) on May 15, 2014 at 14:20 UTC
    > Hello, I breaking my head, why this works ... but this gives a syntax error:

    Maybe SkyNet finally developed a sense of taste? o_O

    SCNR :)

    Sorry... I'm not even trying to decipher this, as long as its not at least intended...

    Cheers Rolf

    ( addicted to the Perl Programming Language)