Throws and where clauses on procedure definitions

I see that whilst:

proc validate (n) where n.type == int || n.type == uint throws {
  if n < 0 { throw new IllegalArgumentError(); }
}

results in the error:

src/Factorial_Chapel.chpl:21: syntax error: near 'throws'

writing:

proc validate (n) throws where n.type == int || n.type == uint {
  if n < 0 { throw new IllegalArgumentError(); }
}

the code comiles and works as anticipated. Is this as expected?

I was going to say that we can check the language specification to see if it is expected or not - but the https://chapel-lang.org/docs/master/language/spec/procedures.html#procedure-definitions section does not include throws in the syntax. So, whatever this discussion leads to, it should include updating that section.

Personally, I’m not sure if it’d be better to allow both orderings or not. I think we do allow either ordering for lifetime clauses and where clauses. I think I have a slight preference to allow either ordering. (throws where looks weird but so does a throws hanging around seemingly at the end of a where clause; it seems that the fact these keywords are separators of a sort is important in either case).

I’m coming to this late, but: I’m not a big fan of allowing syntactic elements to be reordered arbitrarily and would prefer to come up with a “most logical” ordering to things and enforcing it for consistency across function declarations. That said, I’d also be very much in favor of having the compiler generate more helpful error messages like:

'throws' clauses must precede 'where' clauses in function signatures

when the programmer gets it wrong.

For me, the ordering:

  • return type
  • throws clause
  • where clause

has a certain sense to it because the return type says most specifically / typically what the function returns / what the “type” of the function expression will be; the throws clause is like an exceptional variation to the return type; and the where clause can be used to distinguish between multiple function definitions that otherwise have a similar signature. So these flow from a “most inherent to the function’s definition” to “least” order for me.

Arbitrary reordering is bad. Consistency is good. Clear error messages are useful.That said, I am a programmer who never uses throw* in my own code and ban it from projects I control.