Try? vs ? (and is there a comprehensive Swift operator precedence table?)

This questions is really two things. First, is there a comprehensive Swift operator precedence and associativity table somewhere? In particular, here's a common pattern I run up against (in my case, because I use Marshal for object <-> dictionary conversions).

self.prettyStatus = (try? inObj.value(for: "order.prettyStatus")) ?? "Canceled"

try? is used here because sometimes that key is null or doesn't exist. In this case, it seems the nil-coalescing operator binds with higher precedence than try?, and so I have to put parentheses around the try expression above. This feels counterintuitive to me, and while I don't think this change could be made to the language now without breaking a lot of code, I am curious as to why the associativity works out this way. Was it deliberate, or just a consequence of how things worked out?

In a similar case, I am able to write this without the explicit parentheses (try is used because it’s an error if that key is missing):

self.subtotal = try inObj.value(for: "order.subtotalCents") / Decimal(100)

In both cases, the type of the property on the left is enough for Swift to specialize the generic inObj.value() call to return the right type. It seems ?? binds more tightly than try?, which binds more tightly than /. And the way the type inference works through all this is just magic (but I'm grateful it works as well as it does).

Can anyone shed some light on what's happening here, so that I may better understand it? TIA!

try is one of several operators with magical behavior not expressible in terms of Swift’s ordinary precedence rules:

Reading the source code quoted in that post will give you some idea of how try interacts with other operators in terms of the “hoisting” behavior.

3 Likes

See Apple Developer Documentation

Terms of Service

Privacy Policy

Cookie Policy