5.4 Annotations
[1, 2, 3]
If annot is a converter annotation, the conversion is applied before matching the converted value against bind. This dependency implies that the conversion in annot cannot be delayed, and must be performed as part of the matching process (before committing to the match).
[1, 2, 3]
"oops"
annotation | |
| |
annotation | |
| |
annotation | |
| |
annotation | |
The None annotation matches no values, or in other words, is equivalent to Any.of(). It is useful for asserting that something never returns, such as a function that always throws.
See Annotations from Predicates for information about the time that expr is evaluated.
#true
#true
#false
> "hello" :: Any.to_boolean
#true
> #false :: Any.to_boolean
#false
#false
#false
annotation | |
| |
annotation | |
| |
annotation | |
| |
annotation | |
| |
annotation | |
| |
annotation | |
| |
annotation | |
In the case of a method, this can be used as an arg_id to refer to the actual target object. When an arg_id refers to a repetition, then static information for actual arguments mapped to the repetition are combined with statinfo_meta.or. When an arg_id refers to a splice or keyword splice, then corresponding arguments are similarly combined with statinfo_meta.or to get the element or value static information within the splice variable as a list or map.
An Any.like annotation propagates static information directly from an argument.
[v, v]
5
3
An Any.like_element annotation propagates static information corresponding to sequence or indexable values within an argument.
fun pick(choices :: List) :: Any.like_element(choices):
choices[math.random(choices.length())]
> pick(["a", "b"]).length()
1
The Any.like_key or Any.like_value annotation constructors are normally used for maps. They are similar to Any.like_element, but for a sequence that produces two values, where Any.like_key corresponds to the first value and Any.like_value the second.
Any.like_value(m))):
Pair(k, v)
1
[3, 2, 1]
The Any.like_first or Any.like_rest are similar to Any.like_element, but for the components of pairs.
fun pick_part(pr :: Pair) :: Any.like_first(pr) || Any.like_rest(pr):
if math.random(2) == 0
6
An Any.like_field(class_name.field_id(arg_id)) annotation propagates static information corresponding to the field named by field_id in the class named by class_name, where arg_id is an object that is an instance of class_name.
// if both are Int or both are Flonum, result is the same
method dist() :: (Any.like_field(Posn.x(this))
|| Any.like_field(Posn.y(this))):
x + y
6.0
6.0
expression | |
| |
repetition | |
| |
expression | |
| |
repetition | |
| |
|
If annot is a converter annotation, only the matching component of the annotation is used, and the converting part is not used. See also Annotations as Converters.
#true
#false
binding operator | |
| |
| |
binding operator | |
|
> def (x :: Int) described_as An Integer = "oops"
def: value does not satisfy annotation
value: "oops"
annotation: An Integer
def: value does not satisfy annotation
value: [9, 11]
annotation: matching([_, 10])
annotation | |
See Annotations from Predicates for information about the time that pred_expr is evaluated.
> 15 :: (satisfying(is_multiple_of(3))
&& satisfying(is_multiple_of(5)))
15
> [1, 2, 3] :: satisfying(is_list_with_one)
[1, 2, 3]
> Array(1, 2, 3) :: satisfying(is_list_with_one)
::: value does not satisfy annotation
value: Array(1, 2, 3)
annotation: satisfying(is_list_with_one)
annotation | ||||||||||||
| ||||||||||||
| ||||||||||||
|
When annot is provided, then its static information is propagated to the new converter annotation. If annot is supplied with ::, then the result of the body sequence is checked against annot.
See also Annotations as Converters.
def: value does not satisfy annotation
value: "eleven"
annotation: converting(fun (x :: Int): x + 1)
#false
"string"
::: value does not satisfy annotation
value: #true
annotation: maybe(String)
As a binding, bind!! matches non-#false values that match bind. Similar to the !! expression form, when static information for the input to bind!! is maybe(annot), then bind more specifically starts with the static information of annot.
> len("apple")
5
> len(#false)
0
> len(1)
len: argument does not satisfy annotation
argument: 1
annotation: maybe(String)
expression | |
| |
repetition | |
| |
|
> len("apple")
5
> len(#false)
!!.: claimed not false, but actual value is false
expression | |
| |
expression | |
| |
repetition | |
| |
repetition | |
| |
|
When expr has static information from maybe(annot), then the argument to . has static information of annot. If the result of the . form in the non-#false case has static information like annot, then the overall ?. expression has static information like maybe(annot).
> len("apple")
5
> len(#false)
0