ZqImpliedOperatorsCanTrickYou

July 08, 2024
from LearningZq

examples use zq version 1.16.0 and jq version 1.7

A subset of zq operators are Implied Operators, which means “Zed allows certain operator names to be optionally omitted when they can be inferred from context.” The operators are evaluated in this order:

EvaluationOperatorImpliedExplicit
search expressionsearchfoosearch foo
boolean expressionwherea >= 1where a >= 1
field assignmentputa:=x+1,b:=y-1put a:=x+1,b:=y-1
aggregationsummarizecount()summarize count()
expressionyield{a:x+1,b:y-1}yield {a:x+1,b:y-1}


Note: The -C flag can be passed to zq to output the parsed query with explicit operators.

In many contexts this is really helpful (see ZqSearchIsFirstClass), but as I've been learning zq, it's been confusing at times.

I was experimenting with the example data found in this Brim Data article and put together this query:
❯ zq 'over docs
| has(author_name)
| grep(/tuta/, author_name)
| yield author_key' openlibrary.json
["OL369643A"]


Browsing the docs for some functions, I decided to try out lower function, and as is my wont given my jq experience, piped our previous output to lower. But this didn't work, and I got no output:
❯ zq 'over docs
| has(author_name)
| grep(/tuta/, author_name)
| yield author_key | over this | lower' openlibrary.json


I realized I made an error in how to call the function (see ZqFunctionsNeedParens and ZqPipeCharacter), and fixed it accordingly:
❯ zq 'over docs
| has(author_name)
| grep(/tuta/, author_name)
| yield author_key | over this | lower(this)' openlibrary.json
"ol369643a"


I'm aware that I wrote both the has and grep functions correctly, but I think because lower doesn't require an additional argument, I just fell into a jq habit.

But I am still curious. Why didn't I get an error or something letting me know I wasn't using lower properly? If I make a mistake by passing a non-string into it, I'll get an error:
❯ zq 'lower(1)'
error({message:"lower: string arg required",on:1})

So, why no error here?
❯ zq 'yield "HEY" | lower'



Our friend the -C flag has the answer:
❯ zq -C 'yield "HEY" | lower'
yield "HEY"
| search lower

Ahh. The real reason this returns nothing, not even an error, is search is now the implied operator for the term ‘lower’! It's not parsed as a built-in function because it's also a valid search expression, and because ZqSearchIsFirstClass, which is a good thing in search contexts, that's given the priority.

While this example is a bit contrived, hopefully it highlights a frequent experience for me while learning zq. Remember, if you make a change, and get no output, an Implied Operator is probably in play.



Prev: ZqSearchIsFirstClass | Up: LearningZq | Next: ZqPipeCharacter