Proposal: add elipsis matching for arrays
When we want to match each of these paths,
path1 = ["root", "private"]
path2 = ["root", "private", "foo"]
path3 = ["root", "private", "foo", "bar"]
path4 = ["root", "public"]
and only care for them to start with ["root", "private"], it would me nice if we could say
input.path == ["root", "private", ...]
and had it match all of path1, path2, and path3.
Right now, we have to explicitly state
input.path[0] == "root"
input.path[1] == "private"
to make it match those three paths.
This can be helped with, a little, by a helper definition:
path_prefix := {q | q := array.slice(input.path, 0, j + 1); input.path[j]}
This lets then use
path_prefix[["root", "private"]]
where we'd have liked to match with ["root", "private", ...], and it also allows for variables in the array:
> path_prefix := {q | q := array.slice(input.path, 0, j + 1); input.path[j]}
Rule 'path_prefix' defined in package repl. Type 'show' to see rules.
> path_prefix with input.path as ["foo", "bar", "baz"]
[
[
"foo"
],
[
"foo",
"bar"
],
[
"foo",
"bar",
"baz"
]
]
> path_prefix[[x, "bar", y]] with input.path as ["foo", "bar", "baz"]
+-------+-------+--------------------------------+
| x | y | path_prefix[[x, "bar", y]] |
| | | with input.path as ["foo", |
| | | "bar", "baz"] |
+-------+-------+--------------------------------+
| "foo" | "baz" | ["foo","bar","baz"] |
+-------+-------+--------------------------------+
>
While I like this, is there something this provides more than what is shown in the example here?
It feels like this would just as well be improved by a a more succint way of expressing array slices, like e.g. Python provides:
input.path == ["root", "private", ...]
could be:
input.path[:2] == ["root", "private"]
Having a more powerful way of expressing array slices would have quite a few more benefits, like slicing from the end of the array, providing a custom step value, etc.
Discussing this with @srenatus, it would be pretty neat if an elipsis operator would encompass objects as well, so you could do object destructuring like:
some {"name": name, "permissions": permissions, ...} in input.user.attributes
And perhaps it could be used to match parts of an object as well:
{"a: 1, "b": 2, ...} == {"a": 1, "b": 2, "c": 3}
@johanfylling had an interesting case for this, where he wanted to do pattern matching for "last in path" without knowing the length of the array, e.g. something like
walk(object, [[..., "modules"], value])
I could also see the elipsis operator being useful for referencing documents at arbitrarily deep paths for dynamic composition... for example:
data.acme[path...].allow