There are three dimensions of the reasoning footprint for implicitness:
- Applicability. Where are you allowed to elide implied information? Is there any heads-up that this might be happening?
- Power. What influence does the elided information have? Can it radically change program behavior or its types?
- Context-dependence. How much of do you have to know about the rest of the code to know what is being implied, i.e. how elided details will be filled in? Is there always a clear place to look?
The basic thesis of this post is that implicit features should balance these three dimensions. If a feature is large in one of the dimensions, it’s best to strongly limit it in the other two.
?operator in Rust is a good example of this kind of tradeoff. It explicitly (but concisely) marks a point where you will bail out of the current context on an error, possibly doing an implicit conversion on the way. The fact that it’s marked means the feature has strongly limited applicability: you’ll never be surprised that it’s coming into play. On the other hand, it’s fairly powerful, and somewhat context-dependent, since the conversion can depend on the type where
?is used, and the type expected in the scope it’s jumping to. Altogether, this careful balance makes error handling in Rust feels as ergonomic as working with exceptions while avoiding some of their well-known downsides.
Stay up-to-date by subscribing to the Comments RSS Feed for this post.