Consider this piece of code:
[1, 2, 3].firstWhere(
(n) => n > 3,
orElse: () => throw StateError('No match'),
);
This fails, as expected, with an error:
Bad state: No matchError: Bad state: No match
But if I change the orElse
and the test
condition:
[1, 2, 3].firstWhere(
(n) => n > 1,
orElse: throw StateError('No match'),
);
}
So:
- Yes, I have made a mistake:
orElse
should be a function. - But I don't get any syntax errors. And the result is the same error (and not
2
). - Dart warns (not a compilation error, which is why I missed it at first) that the
test
condition is dead code.
I realized the mistake and changed the orElse
to a function, but I am puzzled about the behavior.
Can you help me understand why changing the orElse
from a function:
orElse: () => throw StateError('No match')
... to an expression:
orElse: throw StateError('No match')
... results in the test
condition becoming dead code (but no compilation errors are thrown)?
CodePudding user response:
You have an expression:
list.firstWhere(condition, orElse: throw StateError('No match'));
There is no syntax error because it is legal syntax; throw StateError('No match')
is a valid Dart expression. That is what allows:
void alwaysThrow() => throw Exception();
to be valid.
Now, orElse
expects a Function
, and throw StateError('No match')
doesn't return a Function
, so you might expect a TypeError
at compilation time. However, throw StateError('No match')
doesn't return anything. Dart is an applicative-order language; that is, arguments to a function are evaluated before the function (in this case, firstWhere
) is invoked. throw StateError(...)
is evaluated immediately, and therefore the entire list.firstWhere(...)
expression is known to unconditionally throw an exception. Therefore condition
is irrelevant and is dead code.