Selecting Object literals
(obj)
selects Object literals and, optionally, their properties -- similar to what (arr)
does for Array literals. It has the following signature:
(obj [props?])
In its bare form, (obj)
will match any Object, like {}
or {a}
:
(obj)
To select an object based on its properties, the (prop)
selector can be used, which is also analogous to (el)
for Array elements. It has the following signature:
(prop [key?] [val?])
The following query selects an object that has a property named by the identifier x
:
(obj (prop x))
Property names are not restricted to identifiers: they can be strings -- { "a": 1 }
, or numbers -- { 3: 1 }
, or computed -- { [a]: 1 }
. To be specific about the type of a key, we can use one of the corresponding selectors we've encountered before:
(obj (prop (str a))) ; { "a": 1 }
(obj (prop (comp (num)))) ; { [3]: 1 }
Property values can be selected in a similar fashion by providing a selector as the second argument to (prop)
:
(obj (prop x (str))) ; { x: "foo" }
When the property name is irrelevant, disregard it using the placeholder atom:
(obj (prop _ (str))) ; { x: "foo" }
; { [x]: "foo" }
Selecting objects based on multiple properties
As we've seen with Arrays in the introduction to the logical operators, we can use (:and)
to combine multiple (prop)
selectors and cover more than one property of an object. Say we want to select an object that has the properties named "headers" and "url":
(obj (:and (prop headers)
(prop url)))
Alternating with (:or)
and excluding with (:not)
behave similarly. Alternates are especially useful for property selection since property names (keys) may be more than identifiers; a problem we did not have with Arrays. For example, to match the "headers" and "url" properties regardless of whether they are defined as an identifier or a string:
(obj (:and (prop (:or (id headers) (str "headers")))
(prop (:or (id url) (str "url")))))
Such patterns are often necessary and could get unwieldy rather quickly; consider that a name may also be a computed property of a string literal:
(obj (:and (prop (:or (id headers) (str "headers") (comp (str "headers"))))
(prop (:or (id url) (str "url") (comp (str "url"))))))
SYNG provides dedicated constructs for dealing with these patterns. We discuss this in more detail later in the chapter on supertype selection.