One of the issues with the syntax of
check, as proposed, is that chaining method calls with error returns will look really, really bad. For example,
check (check (check v.m1()).m2()).m3(). The common way around this in many languages, as mentioned in the draft, is the use of
? as a postfix operator instead of prefix keyword, but this has other problems, including resulting in similar illegibility if there are nested function calls, such as in
f1(f2(f3()?)?)?. It also would make it unique amongst the various Go control flow modifiying language structures as all of the other ones are keywords.
check is given a compound function expression, such as nested function calls or chained methods, it applies to all calls in the expression, not just the one it was specifically attached to. The previous two examples then become
check v.m1().m2().m3() and
check f1(f2(f3())), respectively. All other aspects of
check remain the same, meaning that you could still use something like
v, err := f1(check f2()) and whatnot.
One potential awkwardness with this solution is the case of multiple returns being intended for use directly, such as in
func f1(int, error) func f2() (int, error) check f1(f2())
It may be possible, however, for the application of
check to be conditional on the usage of the types of each call, so it simply wouldn't affect the inner call to
f2() in this case, the same as it not affecting a call to a function with no
error return value. It would also be possible to get around this by manually calling
f2() on a previous line, assigning the returns to values, and then passing those to
f1(). If it's not possible, it could simply be a compile-time error if such an ambiguity arises.