Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Please explain why firstWhere with a malformed orElse expression results in a weird/unexpected result?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 [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)?

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading