misterperl has asked for the wisdom of the Perl Monks concerning the following question:
I don't see a lot of documentation on inline coding like these
1 statement if condition;
2 statement for array;
3 {
statement1; statement2; .. statementN;
} for array;
4 ( statement for array ) if condition;
5 statement if condition else other_statement;
6 statement while condition;
* * *
The last 3 would be particularly useful. I've tried them with various parens but they always seems to syntax error. Same with most others except a single if for or while.
Camel and Panther and Jackyl have very little to say about these constucts, but they are very useful and can yield extreme code-compression and readability.
Is there a tutorial or large set of examples, or guidelines and rules, somewhere on inline coding?
Just the other day I reduced someone's code by 1/2 then Mr suicidejunkie reduced it like 80% with this approach. Very elegant, very efficient, and easy to read (like English)..
Haters please do not reply. I'm just asking....
Re: guidelines for inline coding
by choroba (Cardinal) on Sep 25, 2014 at 15:33 UTC
|
As you can find in perlsyn, post-position modifiers are only possible with "simple statements". Block or a statement with a modifier are not simple statements.
To turn a block into a simple statement, wrap it in a do:
do { statement1; statement2 } for @array;
But I'm not sure it still buys you anything.
Also, note that do { ... } while (condition) checks the condition after the first iteration of the loop.
| [reply] [d/l] [select] |
Re: guidelines for inline coding
by Laurent_R (Canon) on Sep 25, 2014 at 17:25 UTC
|
If you are looking for something like this, you can see that it works:
$ perl -e 'my $i = 0; print $i++, " " while $i < 10;'
0 1 2 3 4 5 6 7 8 9
~
$ perl -e 'my @array = 1..10; print 2*$_, " " for @array;'
2 4 6 8 10 12 14 16 18 20
~
you can also do things like this:
for (@array) {
print $ERRORS "Error: value $_ is negative\n" and next if $_ < 0;
push @valid_vals, $_;
}
But you cannot do this:
5 statement if condition else other_statement;
You can't use an other clause when if is used as a statement modifier (i.e. after the statement).
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Hi Your Mother,
I agree that all my three examples are somewhat simplistic, I just wanted to convey the idea of the syntax that the OP was apparently looking for. In the third case, it is true that if print fails, the next statement will not be executed and the next line of code will be executed, which is presumably not what you want. But, OTOH, if the print statement fails, we have much deeper trouble than this possible Heisenbug, so that the random bug is really not the major concern.
Having said that, I fully agree that the do_some_statement() and do_some_other_statement() if something_is_true is nice for writing concise code, but can be dangerous if you are not cautious enough.
I once made the mistake of writing some code basically looking like that:
$nb_errors++ and next if some_condition(); # wrong, don't do it
That worked perfectly for most of the cases, except the first time when an error occurs through the loop, because $nb_errors was false (either 0 or undef) the first time through the loop. Changing it to:
++$nb_errors and next if some_condition();
is sufficient to correct the issue. But it shows that such a construct can be dangerous and must be carefully considered.
| [reply] [d/l] [select] |
|
| [reply] |
|
|
|
Re: guidelines for inline coding
by SuicideJunkie (Vicar) on Sep 25, 2014 at 18:04 UTC
|
I think it mostly comes down to what looks simple to humans.
Something like
do{do{print $_.',' if $_/2 == int($_/2)} for ($_..$_+4); print ' :: '} for (1..50)
works, but would be far better as a multiline block.
do {print "K=$_, V=$hr->{$_}\n" if sensibleToDo($_)} for keys %$hr; is still quite a large mouthful.
The do{} can be dropped if you use an and/or in place of the if. EG:isSensible($_) or send_alert("Help: $_ : $!\n") for (@files). The niceness depends a lot on what you're actually doing and how well your functions and variables are named. The more the actual statements read like an English sentence, the less there is to complain about.
In general, if you feel a desire to nest post-conditionals, you should consider the option of making the whole line a subroutine instead.
| [reply] [d/l] [select] |
Re: guidelines for inline coding
by BrowserUk (Patriarch) on Sep 25, 2014 at 21:04 UTC
|
print,
sum += $_ for @array;
That is, if you find yourself wanting to trace the loop, don't go through the pain of reformatting the loop as block scoped in order to print the iteration, just add the print with a comma as a line preceding the modified loop.
Then comment the added line out or just blow it away when your done debugging.
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".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
Thanks monks for all of the insight and advice, it's all most appreciated. I guess bottom-line is as advised, the inline statements are only for simple cases.
In general I want my code to look more like an sentance than code, like Englishizing:
if ( $cat ) {
$dog='onALert';
}
to
$dog='onALert' if $cat;
its so much cleaner, easier to read. It would be even nicer if "is" could substitute for =", (sort of like SQL "is NULL") then:
$dog is 'onALert' if $cat;
$dog is 'sleeping' unless $cat;
Nice!
Thanks guys for the insight- I'm just syntax-surfing techniques to pretify my code...
| [reply] [d/l] [select] |
Re: guidelines for inline coding
by Anonymous Monk on Sep 25, 2014 at 17:29 UTC
|
Note it's also possible to combine statements with and, or, &&, ||, and even xor. So e.g. something() and otherthing() if $condition; (assuming you know something() will be true). B::Deparse can be helpful in figuring out how your stuff is being parsed:
$ perl -MO=Deparse,-p -e 'something() xor otherthing() if $condition;'
($condition and (something() xor otherthing()));
Whether or not that's more readable or not is a matter of taste, and a matter of whether the coders maintaining it know their precedence tables :-)
| [reply] [d/l] [select] |
|
|