Parse error: syntax error, unexpected token ":", expecting "," or ";" in /var/www/html/php8/ch5/L-6-pag-168.php on line 4
<?php
$a = 36; $b = 24;
echo $a <=> $b ? "They are equal" : "$a is greater than $b" : "$b is greater than $a";
?>
Parse error: syntax error, unexpected token ":", expecting "," or ";" in /var/www/html/php8/ch5/L-6-pag-168.php on line 4
<?php
$a = 36; $b = 24;
echo $a <=> $b ? "They are equal" : "$a is greater than $b" : "$b is greater than $a";
?>
Too many colons. It's test ? true : false
, not test ? true : false : dennis
.
The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to true, and expr3 if expr1 evaluates to false.
https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary
Also note that the <=>
operator returns an integer value (of -1, 0, or 1), not a Boolean; so the results will not be what I think you're expecting, anyway. (For example, if they're equal, it returns 0
, which the ?
operator will consider to be false
).
I suppose you could do something really ugly with nested ? :
operators like this, though I think you'd be better served by some if/else
blocks or even a switch/case
structure as being more readable:
echo ($a <=> $b) == 0 ? "They are equal" : (($a <=> $b) == 1 ? "$a is greater than $b" : "$a is less than $b");
NogDog A match
might be even more readable, but...
Looking at the manual and the language specification, there is no guarantee that its return values will be limited to {-1, 0, 1}.
I don't know any cases where they aren't, but it's always described as evaluating to an integer that is "less than, equal to, or greater than" zero. The RFC proposing it says it should use {-1, 0, 1}.
Going deeper, it's implemented using the pre-existing comparison infrastructure (turns out PHP already implemented its order comparisons through one function and then picked out which feature of the result to return). That infrastructure returns {-1, 0, 1} for primitive types, but for built-in objects with ordering semantics it defers to those objects' own implementations and just returns what they return. I haven't found any that implement ordering that return anything different, but I didn't check every existing or future extension. Also, as I said, PHP's comparison operators use the same comparison infrastructure and do so without assuming it produces only {-1, 0, 1}, as do functions like usort
that take comparators.
All of which means for safety (or until the language can be more explicit and restrict the operator's behaviour: a move I would endorse) the result should be tested with <0, =0, or >0. Which is silly because, as already noted, that just puts it through exactly the same comparison infrastructure that it just went through. (Not totally silly, as now it's a comparison of integers instead of a comparison of arbitrary values.)
Interesting...hadn't seen match
before. Okay, here's my new code that I hope I never, ever actually use...
function lt_eq_gt($a, $b): string {
return match(max(-1, min(1, $a <=> $b))) {
-1 => 'less than',
0 => 'equal to',
1 => 'greater than'
};
}
foreach([[1, 2], ['xyz', 'abc'], [999.351, -0.0123], [5, 5.0]] as $test) {
echo $test[0]." is ".lt_eq_gt($test[0], $test[1])." ".$test[1]."\n";
}
/*
1 is less than 2
xyz is greater than abc
999.351 is greater than -0.0123
5 is equal to 5
*/
foreach([[1, 2], ['xyz', 'abc'], [999.351, -0.0123], [5, 5.0]] as $test) { echo $test[0]." is ".lt_eq_gt($test[0], $test[1])." ".$test[1]."\n"; }
Here's another thing that might be new to you, then:
foreach([[1, 2], ['xyz', 'abc'], [999.351, -0.0123], [5, 5.0]] as [$left, $right]) {
echo "$left is ".lt_eq_gt($left, $right)." $right\n";
}
Think I'd seen that, but then forgotten it.