Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patterns in variable bindings. #218

Merged
merged 16 commits into from
Oct 16, 2024
Merged

Patterns in variable bindings. #218

merged 16 commits into from
Oct 16, 2024

Conversation

01mf02
Copy link
Owner

@01mf02 01mf02 commented Oct 15, 2024

This PR adds support for patterns in variable bindings, e.g. . as {a: [$x, {("b", "c"): $y, $z}]} | $x, $y, $z.
This also works in foreach and reduce.

Compared to jq, this also allows indexing with integers, e.g. {(0): $x, (1): $y}, which is equivalent to [$x, $y]. This can be useful if you wish to destructure arrays, but not necessarily the starting items.

However, jaq does not support the (undocumented) syntax {$x: ...}; for example, the filter {x: [1]} as {$x: [$y]} | $x, $y this yields [1] and 1 in jq.

@01mf02 01mf02 merged commit c3e7e46 into main Oct 16, 2024
1 check passed
@01mf02 01mf02 deleted the patterns branch October 16, 2024 08:07
@wader
Copy link
Contributor

wader commented Oct 16, 2024

Impressive work! and i had no idea jq supported combining key/value pattern like{$x: [$y]}. Index based patter for arrays seems nice addition, wonder how much work it would be to get into jq. I've also wished sometimes for some kind of rest-syntax like [$x, ...$xs] and {$k, ...$obj_with_all_other_keys}

@01mf02
Copy link
Owner Author

01mf02 commented Oct 16, 2024

Regarding {$x: pattern}, I have not implemented this because of a few reasons:

  • {$x: pattern} is not the same as {($x): pattern}. I can't think of any other place in jq where ($x) cannot be substituted by $x, so this is some really surprising behaviour. If you only know the {(f): pattern} syntax and are confronted with {$x: pattern}, you may be up for a pretty big surprise.
  • {$x: pattern} discriminates keys that are not "identifier-like"; that is, this only works for fields like "x", but not for "here-be-dragons". (The same could be said of course about .x and {$x}, but these can be transformed quite simply into equivalent constructs that work with non-identifier-like keys, such as .["x"] and {"x": $x}. There is no easy transformation for {$x: pattern}, however. This can be really cumbersome if you have used {$x: pattern}, perhaps somewhere inside another pattern, then your input format changes from {"x": ...} to {"here-be-dragons: ...}. Have fun rewriting your pattern, especially if you use it inside of reduce or foreach.)

For these reasons, I would also strongly recommend against using this syntax.

@01mf02
Copy link
Owner Author

01mf02 commented Oct 17, 2024

There is also yet another reason why I believe that {$x: pattern} is not a good idea: It provides useful functionality for objects, but there is no equivalent functionality for arrays, which would be equally useful. In particular, we might want to destructure [{a: $x}] and also bind a variable to the first element of the input array, namely to the object that {a: $x} is supposed to match. In jq's destructuring today, this is not possible.

We could come up with some syntax such as

[$o as {a: $x}]

to solve this problem. In particular, wherever we can write a pattern, we should be able to write $x as PATTERN, in order to say that $x should bind to the whole value that is matched by PATTERN.

That would subsume the {$x: PATTERN} syntax, namely by writing:

{x: $x as PATTERN}

Speaking as somebody who just implemented destructuring in jaq a few days ago, I think that such a syntax should be quite feasible to implement. And speaking as somebody who is trying to rewrite the jq manual, I think that such a syntax should be also relatively easy to describe, teach, and understand.

@01mf02
Copy link
Owner Author

01mf02 commented Oct 17, 2024

I've also wished sometimes for some kind of rest-syntax like [$x, ...$xs] and {$k, ...$obj_with_all_other_keys}

While I also think that such syntax could be nice, I think that especially the second idea, namely the $obj_with_all_other_keys, could be a real pain to implement. The problem is that there is no elementary operation in jq that subtracts keys from objects, which would be useful in this case.
The first idea would be mostly subsumed by {(0): $x, (-1): $xs} that I implemented in jaq.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants