Philip Potter wrote:
2009/9/11 John W. Krahn <jwkr...@shaw.ca>:
Philip Potter wrote:
Does ?: guarantee that only one arm of its conditions will be executed?
eg:
# @_ has 3 elements
$x = $flag ? shift : push;
$ perl -e'$x = $flag ? shift : push;'
Not enough arguments for push at -e line 1, near "push;"
Execution of -e aborted due to compilation errors.
Perhaps you meant:
$x = $flag ? shift : pop;
I did indeed, thanks.
I ask because this is the behaviour I expect from C and C++, it's very
important (Steve's original ? shift : {} is broken without it), but
it's not explicitly stated in perldoc perlop. perlop *does* explain
the short-circuit behaviour of qw(|| && // or and) and their use for
control flow, but is silent on ?:'s control flow behaviour. Is this
documented in perldoc, and if so where?
Operators borrowed from C keep the same precedence
relationship with each other, even where C’s precedence is
slightly screwy. (This makes learning Perl easier for C folks.)
Conditional Operator
Ternary "?:" is the conditional operator, just as in C. It works
much like an if-then-else. If the argument before the ? is true,
the argument before the : is returned, otherwise the argument
after the : is returned.
That language doesn't guarantee that the other side won't be
evaluated, just that it won't be returned. Compare the language in the
C draft standard, n1256 6.5.15p4:
"The first operand is evaluated; there is a sequence point after its
evaluation. The second
operand is evaluated only if the first compares unequal to 0; the
third operand is evaluated
only if the first compares equal to 0; the result is the value of the
second or third operand
(whichever is evaluated), converted to the type described below."
Here, it's very explicit wrt evaluation as well as return value.
Well... Let's convert the Perl code I posted to C and see what *it* does:
$ cat ternary-test.c
#include <stdio.h>
#include <stdlib.h>
char *shift ( int *argc, char **argv ) {
int i;
char *temp = argv[ 0 ];
for ( i = 1; i < *argc; ++i ) {
argv[ i - 1 ] = argv[ i ];
}
return temp;
}
char *pop ( int *argc, char **argv ) {
return argv[ --*argc ];
}
char *my_shift ( int *argc, char **argv ) {
fprintf( stderr, "In my_shift function\n" );
return shift( argc, argv );
}
char *my_pop ( int *argc, char **argv ) {
fprintf( stderr, "In my_pop function\n" );
return pop( argc, argv );
}
int main ( int argc, char **argv ) {
/* remove program name from argv */
char *prog_name = shift( &argc, argv );
char *flag = argv[ 0 ];
char *x = flag[ 0 ] == '0' ? my_pop( &argc, argv ) : my_shift(
&argc, argv );
printf( "x = \"%s\"\n", x );
return EXIT_SUCCESS;
}
$ gcc ternary-test.c -o ternary-test
$ ./ternary-test one two three four five six
In my_shift function
x = "one"
$ ./ternary-test 0 one two three four five six
In my_pop function
x = "six"
Yep, same behavior as the Perl ternary operator.
John
--
Those people who think they know everything are a great
annoyance to those of us who do. -- Isaac Asimov
--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/