Selecting patterns
Patterns can appear in the declaration of a variable, a process referred to as destructuring. SYNG supports selecting patterns that match a specific shape or inline value, such as a default.
Before we explain how to select them, let's revisit a few patterns:
let [x,y] = coords;
let {count: userCount} = users;
function log(messages = []) {}
The first is an Array Pattern where the first and second elements of the array coords
are assigned to the local variables x
and y
accordingly. The second is an Object Pattern that binds the value of the property users.count
to the local variable userCount
. The last is an Assigment Pattern appearing in a function declaration where an empty array is assigned to the messages
variable when it is passed a value of undefined
at the time the function is called.
(obj)
, (arr)
, (prop)
and (el)
can all be utilized to select patterns of the respective kind.
Selecting Object patterns
(obj)
and (prop)
select object patterns. You can be as specific about the shape as necessary. The following example matches the second pattern shown above in increasing degrees of specificity:
(var (obj))
(var (obj (prop count)))
(var (obj (prop count (prop userCount))))
(var (obj (prop count (prop userCount (num 5)))))
If you're only looking for a default value, use the placeholder atom _
to ignore the property key:
(var (obj (prop _ (num 3)))) ; const {count=3} = users;
Searching for sub-patterns
Note
This section contains an unstable feature and may change in the future.
If you're looking for only a part of a pattern, like a default value, but you don't know where it might appear, e.g. nested within a sub object, you can confine the selection to the declaration and search for the value inside that:
(:at (var) (num 3))
Which would match against the declarations:
let {a:{b:{c=3}}} = x
// ^
let [a=3] = x
// ^
Note that we didn't confine to the binding of the declaration, but rather to all of it, so an initializer matching our selector would also match:
let a = 3;
// ^ yes, this isn't what we wanted, either
It's not yet possible to confine to either initializer or binding of the declaration. In practice, however, what you'll be selecting for the pattern is highly unlikely to conflict with what's in an initializer, so there shouldn't be many false positives, if at all.
Additionally, the query would actually give you just the value you made the search with, 3
, which is not terribly useful if you wanted to see the declaration in which it appeared. Refinement is a tool we can use to get at that declaration, but we haven't covered it yet. Nor did we cover confinement, so let's keep going.