Re: Nested OR as a control structure
by diotalevi (Canon) on Jun 02, 2004 at 22:54 UTC
|
if ( $dothis )
{
if ( dofistcritical() )
{
dofirstremainder();
}
elsif ( dobackupcritical() )
{
dobackupremainder();
}
else
{
die "main and backup failed";
}
exit 0;
}
| [reply] [d/l] |
Re: Nested OR as a control structure
by BrowserUk (Patriarch) on Jun 02, 2004 at 23:59 UTC
|
If you really want do this (why?:), you can, and without resorting to subs or do blocks--but I wouldn't advise it. T'is fun though:)
#! perl -slw
use strict;
my @result;
sub dofirstcritical {
print 'do first critical returning ', $result[ 0 ];
$result[ 0 ]
}
sub dobackupcritical {
print 'do backup critical returning ', $result[ 1 ];
$result[ 1 ]
}
sub dobackupremainder{ print 'backup remainder done' }
sub dofirstremainder { print 'first remainder done' }
for my $result ( [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1] ) {
@result = @$result;
eval{
dofirstcritical() and ( dofirstremainder(), die 'Exiting 0' )
or (
( dobackupcritical() or die "main and backup failed" )
and
( dobackupremainder(), die 'Exiting 0' )
)
};
print $@, $/;
}
__END__
P:\test>temp
do first critical returning 0
do backup critical returning 0
main and backup failed at P:\test\temp.pl line 15.
do first critical returning 0
do backup critical returning 1
backup remainder done
Exiting 0 at P:\test\temp.pl line 15.
do first critical returning 1
first remainder done
Exiting 0 at P:\test\temp.pl line 15.
do first critical returning 1
first remainder done
Exiting 0 at P:\test\temp.pl line 15.
Note: The eval block is only there to captiure and record the dies and simulated exits.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
| [reply] [d/l] |
Re: Nested OR as a control structure
by eric256 (Parson) on Jun 02, 2004 at 22:56 UTC
|
Well i'm not sure i understand what you expect that to do. Or doesn't take a code block or a reference on the right, it takes an expression. So you can't do {} or sub {}. I think your control structure is similar to the following but i'm not realy sure. Also in the future you should consider includeing whatever errors you get because "I'm still pondering the syntax of why it fails." isn't very discriptive. The following code emulates how i read your example but is probably not what you had in mind.
use strict;
use warnings;
sub test1 {print "Hello\n"; return 0;}
sub test1remainder {print "Bye\n";return 1;}
sub test2 {print "\tHello2\n"; return 0;}
sub test2remainder {print "\tBye2\n";return 1;}
sub test3 {print "\t\tHello3\n"; return 1;}
sub test3remainder {print "\t\tBye3\n";return 1;}
unless(0) {
if (test1) { test1remainder and exit 0};
if (test2) { test2remainder and exit 0};
if (test3) { test3remainder and exit 0};
}
__DATA__
C:\test>perl or.pl
Hello
Hello2
Hello3
Bye3
| [reply] [d/l] |
Re: Nested OR as a control structure
by parv (Parson) on Jun 02, 2004 at 23:17 UTC
|
#!/usr/local/bin/perl
use strict;
use warnings;
my $p = 9;
if ( $p )
{
sub
{ printf "$p < 3 ? %s\n" , $p < 3 ? 'yes' : 'no';
return 0;
}->()
or
sub
{ printf "$p > 3 ? %s\n" , $p > 3 ? 'yes' : 'no';
return 0;
}->()
or
print "I forgot my Math: $p <!> 3!\n"
;
}
In other words, if your subs return appropriate truth values, then
your posted example should work. Mind you can bundle your subs w/
exit() in anonymous sub references similar to as shown
above.
| [reply] [d/l] [select] |
|
|
Ah this is interesting, thanks Parv. Im playing with your anonymous sub refs type thing now. Im returning undefs from failed subs. Encouraging that you also think it should work.
I wandered into writing it quite naturally, it seemed intuitively right.
Thanks to the other posters for your thoughts too. I was specifically refering to the syntactic usage of OR even if the question sounded vague. Maybe it is more subtle than it seems,
the expression (which I call a block) must behave as the return value of the sub. Damn my C legacy.
| [reply] |
Re: Nested OR as a control structure
by andyf (Pilgrim) on Jun 03, 2004 at 00:19 UTC
|
Thanks for all your replies.
That's very thorough little test harness there Browser, nice.
I think your going to beat me when you see that the nub of the question was just all about return values. This finally works
#!/usr/bin/perl
dofistcritical() or dobackupcritical() or dofailed();
sub dofistcritical {if (int rand 5)
{print "hooray it worked first time!\n"}
else {return 0}}
sub dobackupcritical {if (int rand 5)
{print "First time failed but luckily the backup worked...phew\n"}
else {return 0}}
sub dofailed {if (int rand 5)
{print "Main failed. Backup Failed. You have 3 minutes to reach a
+safe distance\n"}
else {return 0}}
I'm not exactly sure where it was failing before, but the complicated blocks to force critical and non-critical areas must have had me seeing things, from here I can work the critical/non-critical sections back in. Cheers all. | [reply] [d/l] |
Re: Nested OR as a control structure
by dave_the_m (Monsignor) on Jun 03, 2004 at 09:53 UTC
|
Others have pointed out better ways of doing this; for the
record I'll just explain how Perl was seeing your code. Perl
expects an expression to follow 'or', so
... or { ....; ... }
is interpreted as an anonymous hash constructor, and the
semicolon in the middle of it is then a syntax error.
Also, no-one seems to have mentioned 'do'; this allows
you to use a block of code as an expression, eg
.... or do { statement; statment; statement_with_final_value }
But most of the time you're still better off using if/else.
Dave. | [reply] [d/l] [select] |
|
|
Also, no-one seems to have mentioned 'do'...
Yup, that's what I was thinking.
I've become increasingly fond of the do-block syntax; here's the OP's code with the two "do"s added where needed:
unless ($dontdothis) {
dofistcritical() or do {
dobackupcritical() or do {
die "main and backup failed";
};
dobackupremainder();
exit 0;
};
dofirstremainder();
exit 0;
}
| [reply] [d/l] |
Re: Nested OR as a control structure
by bobn (Chaplain) on Jun 03, 2004 at 03:20 UTC
|
tryfirstchoice() or trysecondchoice() or trynextchoice or .... trylast
+choice();
then why not just do so?
#!/use/bin/perl -lw
tryfirstchoice() or trysecondchoice() or trylastchoice();
sub tryfirstchoice
{
print "tryfirstchoice";
return;
}
sub trysecondchoice
{
print "trysecondchoice";
return 1;
}
sub trylastchoice
{
print "trylastchoice";
return 1;
}
<code>
Running this produces:
<code>
# perl or.pl
tryfirstchoice
trysecondchoice
#
--Bob Niederman, http://bob-n.com All code given here is UNTESTED unless otherwise stated.
| [reply] [d/l] [select] |
Re: Nested OR as a control structure
by TomDLux (Vicar) on Jun 03, 2004 at 02:24 UTC
|
or is identical to the operator || except that with ||, function calls need parentheses, while with or they don't.
# this reports a problem if func() fails.
func $arg1, $arg2 or warn "error invoking func()";
# so does this
func( $arg1, $arg2 ) || warn "error invoking func()";
# Not what you might expect
# this invokes func( $arg1, ($arg2 || warn "error invoking func()" );
func $arg1, $arg2 || warn "error invoking func()";
My interpretation is that as the use of paranthese-less function calls became increasingly common, and so did the use of error detection, there was a clash, leading the the invention of or.
But you aren't dealing with expressions, you're dealing with blocks.
You can keep the code in block form, and use if() or unless().
Alternately, you could have the first main and alternate return values which distinguish which one ran. They already need to return true for success and false for failure ... just modify things so dofirstcritical() and dobackupcritical() return different true values. Then you can break the continuation out into a separate block.
# At the top of the file in the configuration section
my $first_backup = 1;
my $backup_backup = 2;
unless ($dontdothis) {
my $status = dofistcritical() or
dobackupcritical() or
die "main and backup failed";
if ( $status == $first_backup ) {
dobackupremainder();
} elsif ( $status == $backup_backup ) {
dofirstremainder();
} else {
die( Invalid status '$status' from first backup component" );
}
}
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] [d/l] [select] |
|
|
or is identical to the operator || except that with ||, function calls need parentheses, while with or they don't.
there are other differences than that. consider:
tina@lux:~> perl -wle'
@a = qw(a b c);
@b = @a or die;
@c = @a || die;
print "(@b) (@c)"'
(a b c) (3)
| [reply] [d/l] |
|
|
Aye Tom,
For a while I suspected || and OR might be synonyms, it seems that || binds more strongly, so I get that 3rd example ok. Using $status to grab the result of whichever one finally ran is nice. I can use that.
Cheers,
Andy.
| [reply] |