Functions · Defining Functions · Practice Question
Local vs Global Variable Assignment
Question
What does the following code print, and why?
counter: 0
increment:{
c: counter + 1;
c
}
increment[]
increment[]
increment[]
counterSolution
increment[] / 1
increment[] / 1
increment[] / 1
counter / 0Explanation
The single colon : inside a function creates a local variable. The line c: counter + 1 reads the global counter (which is 0), adds 1, and assigns the result to the local c. The global is never changed, so every call returns 1 and counter is still 0 afterwards.
To actually modify the global, use :: (double colon):
counter: 0
increment:{
counter +:: 1; / add 1 to the global counter
}
increment[]
increment[]
increment[]
counter / 3counter +:: 1 is shorthand for counter :: counter + 1 — read it as "add 1 to the global counter in place".
A Common Trap: Reusing the Global's Name
You might expect this to read the global and store the result in a local of the same name:
increment:{
counter: counter + 1;
counter
}It does not work. q decides which names are local when the function is defined: any name assigned with : anywhere in the body is local for the whole function. So the counter on the right-hand side refers to the local counter, which has no value yet, and q signals a 'counter error instead of reading the global.
Summary of assignment forms inside a function:
| Syntax | Effect |
|---|---|
a: expr | Local variable — visible only inside this call |
a :: expr | Global assignment — modifies the variable in the current namespace (unless a is a local or a parameter of the function) |
`a set expr | Global assignment by name |
In production code, functions that write to globals should be used sparingly and clearly documented, as they create hidden state that makes functions harder to test and reason about.
Note: don't name a variable count (or any other q keyword, such as sum, last or value) — keywords cannot be reassigned, and count: 0 fails with 'assign.