1.4 Annotations and the Dot Operator
Besides classes defined with class, a few predefined annotations work with the :~ and :: annotation operators, including Int (meaning exact integer), Number, String, Keyword, and Any (meaning any value).
The :~ and :: operators also work in expression positions. In that case, the assertion or check is about the expression on the left-hand side of :~ or ::. For ::, the left-hand expression must produce a value that satisfies the right-hand annotation, otherwise a run-time exception is thrown. The is_a operator takes an annotation like ::, but it produces a boolean result indicating whether the result of the left-hand expression satisfies the annotation.
0
> (1 :: Posn)
::: value does not satisfy annotation
value: 1
annotation: Posn
> origin is_a Posn
#true
> 1 is_a Posn
#false
When class defines a new class, an annotation can be associated with each field. When the annotation is written with ::, then the annotation is checked when an instance is created.
> Posn(1, 2)
Posn(1, 2)
> Posn(1, "2")
Posn: value does not satisfy annotation
value: "2"
annotation: Int
Naturally, class annotations can be used as field annotations, and then the . operator can be chained for efficient access:
Using . to reach an imported or namespaced binding, as in f2c.fahrenheit_to_celsius, is different than the infix expression operator, ..
More generally, . access is efficient when the left-hand side of . is an expression that can act as a dot provider. A class name also acts as a namespace to provide access to field-accessor functions, as in Posn.x (which doesn’t get a specific x, but produces a function that can be called on a Posn instance to extract its x field). An identifier that is bound using :~ or :: (where a class name follows the :~ or ::) is a dot provider, and it provides access to fields of a class instance. For example, a use of p.x in the lexical context of a p that is bound via p :: Posn is an efficient access to the x field. In general, an annotation that is associated to a binding or expression with :~ or :: might make the binding or expression a dot provider. See Static Information and Binding for more information on dot providers and other static information.
The use_static definition form redefines #%dynamism so that the . operator works only in efficient mode with a dot provider, among others. If the left-hand side of the . is not a dot provider, then . under use_static reports a compile-time error. The use_dynamic form binds #%dynamism to the default #%dynamism, which allows dynamic field lookup if the left-hand side is not a dot provider.