3-1: Specifiers
A specifier is a composable query of relations. The concepts and syntax come directly from AppleScript.
See also: Quick Tutorial.
#
RelationsRelations relate items to each other, connecting them through an item graph.
Relations are not themselves syntactic elements, but exist at runtime between items, and are described by specifiers.
There are two types of relations: element relations and property relations.
Chaining#
A specifier is a chain of relation descriptions, starting from a concrete root item.
For example, a specifier referring to the id
property of a root item is a chain of one relation description. On the other hand, a specifier referring to the length
property of the Calendar event before the event "Lunch" of the root item (a Calendar account) is a chain of three relation descriptions.
#
Element relationsElement relations are one-to-many relations keyed by type. Elements can be specified via an indexing form, and possibly one or two additional identifying items.
Element specifiers#
An element specifier describes an element relation. The syntax varies by indexing form, but always includes a type term.
#
Indexing formsEach element relation has an indexing form that specifies how it selects items.
Simple#
Simple form is a convenience syntax for either Name or Index form, depending on the type of identifying item used.
Identifying item: A string
, integer
or real
. string
makes a Simple specifier act like a Name specifier; integer
and real
make a Simple specifier act like an Index specifier. An item that is not of one of these types produces a runtime error.
Name#
Name form specifies a single element according to the value of its ae4:pnam
(name
) property.
Identifying item: A string
that a name
property must match.
Index#
Index form specifies a single element according to the value of its ae4:pidx
(index
) property.
Identifying item: A number
that an index
property must match.
ID#
ID form specifies a single element according to the value of its ae4:ID
(id
) property.
Identifying item: An item that an id
property must match.
Absolute positioning#
Absolute Positioning form specifies a single element according to its ordinal position within a container.
No identifying items, but the selection varies based on the positioning used.
The choice of first
, middle
, last
or some
affects the meaning of the specifier:
first
selects the item ordered first in its container; typically equivalent to<type> index 1
.middle
selects the item ordered at the center of its container (the median item), preferring the one ordered first when a two-way tie occurs. For a sequence with alength
property, equivalent to<type> index (floor (length / 2))
.last
selects the item ordered last in its container; for a sequence with alength
property, equivalent to<type> index (length)
.some
selects a random item from the container. No, seriously. Listen, this was Apple's idea, not mine 👀.
Relative positioning#
Relative Positioning form specifies a single element according to its ordinal position relative to another element in the same container.
No identifying items, but the selection varies based on the positioning used.
The choice of before
or after
affects the meaning of the specifier:
before
selects the item ordered immediately before the reference element.after
selects the item ordered immediately after the reference element.
Note that the reference element is not an identifying item, but is rather the immediate parent of the specifier.
To form a Relative Positioning specifier under the current default target, it
must be used, since the syntax requires explicit mention of the parent after before
/after
; i.e., window after
is not a syntactically valid specifier:
All#
All form specifies every element in a container.
No identifying items.
Range#
Range form specifies elements within a range of values in a container. The test used to determine whether an item is in the range depends on the element and container types, and possibly the type of the identifying items used.
Identifying items: One representing the lower bound, and another representing the upper bound.
Filter#
Filter form specifies elements that pass a certain custom test.
A Filter test is predicated on comparions between test specimen-rooted specifiers and other items. Logical operations can compose these tests to form new tests.
No identifying items, but a special test predicate expression is used instead.
The test expression should usually consist of binary comparison or logical operations.
#
Specimen specifiersSyntactically unrooted specifiers in the test expression are implicitly rooted in the test specimen item. Such specifiers are called specimen specifiers, and are reevaluated for each item tested.
name
in this context is a specimen specifier.
#
Property relationsA property relation relates a host item to a value item via a property term. While element relations are one-to-many, property relations are one-to-one. Property relations often describe the host item with number or string values, although they can also act as references to other complex items.
Property specifiers#
A property specifier describes a property relation, and is created by simply naming a property term.
#
EvaluationEvaluating a specifier follows its query chain to arrive at a value (or storage location for set
).
#
Implicit evaluationSpecifiers are implicitly evaluated in most expression contexts. This means that naming a specifier will, by default, result in the specifier's current value rather than a static, unevaluated specifier
item.
The following are all the contexts where specifiers are not implicitly evaluated:
- The argument of a reference expression (see below); e.g.,
ref window 1
. - The target expression of a
tell
expression; e.g.,tell window 1
. - Key expressions in a record; e.g.,
{name: "abc"}
. - The destination of a
set
expression; e.g.,set URL to "https://google.com/"
. - The parent expression of a specifier phrase; e.g.,
name of window 1
(the final specifier will be evaluated, butwindow 1
will not). - Filter test expressions; e.g.,
window where name is "Untitled"
(the final specifier will be evaluated, butname
will not).
Explicit evaluation#
A specifier can be explicitly evaluated with a get
expression. This always results in evaluation, even in contexts where implicit evaluation is disabled.
Reference expressions#
Implicit evaluation can be contextually disabled with a ref
expression. This always creates a specifier
item, which can then be sent in remote calls or evaluated later.