Interprocess Communication (IPC) · Message Handlers (.z Namespace) · Practice Question
What Do .z.pg and .z.ps Do By Default?
Question
If a q process never redefines .z.pg or .z.ps, how does it actually process an incoming request? What happens if a table is sent directly as a message, rather than wrapped in a query?
Solution
By default, both handlers simply apply value to whatever was received:
.z.pg:{value x}
.z.ps:{value x}Sending a bare table directly as a message — rather than, say, a function call that produces a table — raises a type error, because value can't evaluate a table. A list like (insert;`t;data) works, since value evaluates it as a function call. (A bare dictionary doesn't raise an error, but value just returns its values, which is rarely what was intended.)
Explanation
A request arrives as either a string of q code or a list shaped like (function;arg1;arg2;...). value evaluates both: it parses and runs a string, and executes a function-call-shaped list.
A table has no meaningful "value" to evaluate, so sending one bare raises a type error — which is why data needs wrapping in something like insert or upsert rather than sent on its own.
Since both handlers just call value, overriding either is how a process adds logging, validation, or access control to every incoming request.