3-1: Specifiers
A specifier is a composable query of relations. The concepts and syntax come directly from AppleScript.
See also: Quick Tutorial.
Relations#
Relations 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 relations#
Element 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 forms#
Each 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:
firstselects the item ordered first in its container; typically equivalent to<type> index 1.middleselects 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 alengthproperty, equivalent to<type> index (floor (length / 2)).lastselects the item ordered last in its container; for a sequence with alengthproperty, equivalent to<type> index (length).someselects 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:
beforeselects the item ordered immediately before the reference element.afterselects 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 specifiers#
Syntactically 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 relations#
A 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.
Evaluation#
Evaluating a specifier follows its query chain to arrive at a value (or storage location for set).
Implicit evaluation#
Specifiers 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
tellexpression; e.g.,tell window 1. - Key expressions in a record; e.g.,
{name: "abc"}. - The destination of a
setexpression; 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 1will not). - Filter test expressions; e.g.,
window where name is "Untitled"(the final specifier will be evaluated, butnamewill 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.