Q (programming language from Kx Systems)
- 7 min read
- 2 chapters
Related on Lably
Through Database, Data type and Unique key
Overview
The fundamental building blocks of q are atoms, lists, and functions. Atoms are scalars and include the data types numeric, character, date, and time. Lists are ordered collections of atoms (or other lists) upon which the higher level data structures dictionaries and tables are internally constructed. A dictionary is a map of a list of keys to a list of values. A table is a transposed dictionary of symbol keys and equal length lists (columns) as values. A keyed table, analogous to a table with a primary key placed on it, is a dictionary where the keys and values are arranged as two tables.
The following code demonstrates the relationships of the data structures. Expressions to evaluate appear prefixed with the q) prompt, with the output of the evaluation shown beneath:
<span id="mwLg"></span><span class="gp" id="mwLw">q)</span><span class="ss" id="mwMA">`john</span><span class="w" id="mwMQ"> </span><span class="c1" id="mwMg">/ an atom of type symbol</span> <span class="ss" id="mwMw">`john</span> <span class="gp" id="mwNA">q)</span><span class="il" id="mwNQ">50</span><span class="w" id="mwNg"> </span><span class="c1" id="mwNw">/ an atom of type integer</span> <span class="il" id="mwOA">50</span> <span class="gp" id="mwOQ">q)</span><span class="ss" id="mwOg">`john`jack</span><span class="w" id="mwOw"> </span><span class="c1" id="mwPA">/ a list of symbols</span> <span class="ss" id="mwPQ">`john`jack</span> <span class="gp" id="mwPg">q)</span><span class="il" id="mwPw">50</span><span class="w" id="mwQA"> </span><span class="il" id="mwQQ">60</span><span class="w" id="mwQg"> </span><span class="c1" id="mwQw">/ a list of integers</span> <span class="il" id="mwRA">50</span><span class="w" id="mwRQ"> </span><span class="il" id="mwRg">60</span> <span class="gp" id="mwRw">q)</span><span class="ss" id="mwSA">`john`jack</span><span class="o" id="mwSQ">!</span><span class="il" id="mwSg">50</span><span class="w" id="mwSw"> </span><span class="il" id="mwTA">60</span><span class="w" id="mwTQ"> </span><span class="c1" id="mwTg">/ a list of symbols and a list of integers combined to form a dictionary</span> <span class="n" id="mwTw">john</span><span class="o" id="mwUA">|</span><span class="w" id="mwUQ"> </span><span class="il" id="mwUg">50</span> <span class="n" id="mwUw">jack</span><span class="o" id="mwVA">|</span><span class="w" id="mwVQ"> </span><span class="il" id="mwVg">60</span> <span class="gp" id="mwVw">q)</span><span class="ss" id="mwWA">`name`age</span><span class="o" id="mwWQ">!</span><span class="p" id="mwWg">(</span><span class="ss" id="mwWw">`john`jack</span><span class="p" id="mwXA">;</span><span class="il" id="mwXQ">50</span><span class="w" id="mwXg"> </span><span class="il" id="mwXw">60</span><span class="p" id="mwYA">)</span><span class="w" id="mwYQ"> </span><span class="c1" id="mwYg">/ an arrangement termed a column dictionary</span> <span class="n" id="mwYw">name</span><span class="o" id="mwZA">|</span><span class="w" id="mwZQ"> </span><span class="n" id="mwZg">john</span><span class="w" id="mwZw"> </span><span class="n" id="mwaA">jack</span> <span class="n" id="mwaQ">age</span><span class="w" id="mwag"> </span><span class="o" id="mwaw">|</span><span class="w" id="mwbA"> </span><span class="il" id="mwbQ">50</span><span class="w" id="mwbg"> </span><span class="il" id="mwbw">60</span> <span class="gp" id="mwcA">q)</span><span class="nb" id="mwcQ">flip</span><span class="w" id="mwcg"> </span><span class="ss" id="mwcw">`name`age</span><span class="o" id="mwdA">!</span><span class="p" id="mwdQ">(</span><span class="ss" id="mwdg">`john`jack</span><span class="p" id="mwdw">;</span><span class="il" id="mweA">50</span><span class="w" id="mweQ"> </span><span class="il" id="mweg">60</span><span class="p" id="mwew">)</span><span class="w" id="mwfA"> </span><span class="c1" id="mwfQ">/ when transposed via the function "flip", the column dictionary becomes a table</span> <span class="n" id="mwfg">name</span><span class="w" id="mwfw"> </span><span class="n" id="mwgA">age</span> <span class="o" id="mwgQ">--------</span> <span class="n" id="mwgg">john</span><span class="w" id="mwgw"> </span><span class="il" id="mwhA">50</span> <span class="n" id="mwhQ">jack</span><span class="w" id="mwhg"> </span><span class="il" id="mwhw">60</span> <span class="gp" id="mwiA">q)</span><span class="p" id="mwiQ">(</span><span class="nb" id="mwig">flip</span><span class="w" id="mwiw"> </span><span class="p" id="mwjA">(</span><span class="ow" id="mwjQ">enlist</span><span class="w" id="mwjg"> </span><span class="ss" id="mwjw">`name</span><span class="p" id="mwkA">)</span><span class="o" id="mwkQ">!</span><span class="ow" id="mwkg">enlist</span><span class="w" id="mwkw"> </span><span class="ss" id="mwlA">`john`jack</span><span class="p" id="mwlQ">)</span><span class="o" id="mwlg">!</span><span class="nb" id="mwlw">flip</span><span class="w" id="mwmA"> </span><span class="p" id="mwmQ">(</span><span class="ow" id="mwmg">enlist</span><span class="w" id="mwmw"> </span><span class="ss" id="mwnA">`age</span><span class="p" id="mwnQ">)</span><span class="o" id="mwng">!</span><span class="ow" id="mwnw">enlist</span><span class="w" id="mwoA"> </span><span class="il" id="mwoQ">50</span><span class="w" id="mwog"> </span><span class="il" id="mwow">60</span><span class="w" id="mwpA"> </span><span class="c1" id="mwpQ">/ two equal length tables combined as a dictionary become a keyed table</span> <span class="n" id="mwpg">name</span><span class="o" id="mwpw">|</span><span class="w" id="mwqA"> </span><span class="n" id="mwqQ">age</span> <span class="o" id="mwqg">----|</span><span class="w" id="mwqw"> </span><span class="o" id="mwrA">---</span> <span class="n" id="mwrQ">john</span><span class="o" id="mwrg">|</span><span class="w" id="mwrw"> </span><span class="il" id="mwsA">50</span> <span class="n" id="mwsQ">jack</span><span class="o" id="mwsg">|</span><span class="w" id="mwsw"> </span><span class="il" id="mwtA">60</span>
These entities are manipulated via functions, which include the built-in functions that come with Q (which are defined as K macros) and user-defined functions. Functions are a data type, and can be placed in lists, dictionaries and tables, or passed to other functions as parameters.
Sign in to keep reading
One more chapter is free with a Lably account.
Examples
Like K, Q is interpreted and the result of the evaluation of an expression is immediately displayed, unless terminated with a semi-colon. The Hello world program is thus trivial:
<span id="mwvA"></span><span class="gp" id="mwvQ">q)</span><span class="s2" id="mwvg">"Hello world!"</span> <span class="s2" id="mwvw">"Hello world!"</span>
The following expression sorts a list of strings stored in the variable x descending by their lengths:
<span id="mwww"></span><span class="n" id="mwxA">x</span><span class="o" id="mwxQ">@</span><span class="nb" id="mwxg">idesc</span><span class="w" id="mwxw"> </span><span class="nb" id="mwyA">count</span><span class="w" id="mwyQ"> </span><span class="nb" id="mwyg">each</span><span class="w" id="mwyw"> </span><span class="n" id="mwzA">x</span>
The expression is evaluated from right to left as follows:
- "count each x" returns the length of each word in the list x.
- "idesc" returns the indices that would sort a list of values in descending order.
- @ use the integer values on the right to index into the original list of strings.
The factorial function can be implemented directly in Q as
<span id="mw1Q"></span><span class="p" id="mw1g">{</span><span class="ow" id="mw1w">prd</span><span class="w" id="mw2A"> </span><span class="il" id="mw2Q">1</span><span class="o" id="mw2g">+</span><span class="nb" id="mw2w">til</span><span class="w" id="mw3A"> </span><span class="n" id="mw3Q">x</span><span class="p" id="mw3g">}</span>or recursively as
<span id="mw4g"></span><span class="p" id="mw4w">{</span><span class="o" id="mw5A">$</span><span class="p" id="mw5Q">[</span><span class="n" id="mw5g">x</span><span class="o" id="mw5w">=</span><span class="il" id="mw6A">0</span><span class="p" id="mw6Q">;</span><span class="il" id="mw6g">1</span><span class="p" id="mw6w">;</span><span class="n" id="mw7A">x</span><span class="o" id="mw7Q">*.</span><span class="n" id="mw7g">z.s</span><span class="p" id="mw7w">[</span><span class="n" id="mw8A">x</span><span class="o" id="mw8Q">-</span><span class="il" id="mw8g">1</span><span class="p" id="mw8w">]]}</span>Note that in both cases the function implicitly takes a single argument called x - in general it is possible to use up to three implicit arguments, named x, y and z, or to give arguments local variable bindings explicitly.
In the direct implementation, the expression "til x" enumerates the integers from 0 to x-1, "1+" adds 1 to every element of the list and "prd" returns the product of the list.
In the recursive implementation, the syntax "$[condition; expr1; expr2]" is a ternary conditional - if the condition is true then expr1 is returned; otherwise expr2 is returned. The expression ".z.s" is loosely equivalent to 'this' in Java or 'self' in Python - it is a reference to the containing object, and enables functions in q to call themselves.
When x is an integer greater than 2, the following function will return 1 if it is a prime, otherwise 0:
<span id="mw-g"></span><span class="p" id="mw-w">{</span><span class="ow" id="mw_A">min</span><span class="w" id="mw_Q"> </span><span class="n" id="mw_g">x</span><span class="w" id="mw_w"> </span><span class="nb" id="mwAQA">mod</span><span class="w" id="mwAQE"> </span><span class="il" id="mwAQI">2</span><span class="o" id="mwAQM">_</span><span class="nb" id="mwAQQ">til</span><span class="w" id="mwAQU"> </span><span class="n" id="mwAQY">x</span><span class="p" id="mwAQc">}</span>The function is evaluated from right to left:
- "til x" enumerate the non-negative integers less than x.
- "2_" drops the first two elements of the enumeration (0 and 1).
- "x mod" performs modulo division between the original integer and each value in the truncated list.
- "min" find the minimum value of the list of modulo result.
The q programming language contains its own table query syntax called qSQL, which resembles traditional SQL but has important differences, mainly due to the fact that the underlying tables are oriented by column, rather than by row.
<span id="mwARM"></span><span class="gp" id="mwARQ">q)</span><span class="nb" id="mwARU">show</span><span class="w" id="mwARY"> </span><span class="nv" id="mwARc">t</span><span class="o" id="mwARg">:</span><span class="p" id="mwARk">([]</span><span class="w" id="mwARo"> </span><span class="nv" id="mwARs">name</span><span class="o" id="mwARw">:</span><span class="ss" id="mwAR0">`john`jack`jill`jane</span><span class="p" id="mwAR4">;</span><span class="w" id="mwAR8"> </span><span class="nv" id="mwASA">age</span><span class="o" id="mwASE">:</span><span class="w" id="mwASI"> </span><span class="il" id="mwASM">50</span><span class="w" id="mwASQ"> </span><span class="il" id="mwASU">60</span><span class="w" id="mwASY"> </span><span class="il" id="mwASc">50</span><span class="w" id="mwASg"> </span><span class="il" id="mwASk">20</span><span class="p" id="mwASo">)</span><span class="w" id="mwASs"> </span><span class="c1" id="mwASw">/ define a simple table and assign to "t"</span> <span class="n" id="mwAS0">name</span><span class="w" id="mwAS4"> </span><span class="n" id="mwAS8">age</span> <span class="o" id="mwATA">--------</span> <span class="n" id="mwATE">john</span><span class="w" id="mwATI"> </span><span class="il" id="mwATM">50</span> <span class="n" id="mwATQ">jack</span><span class="w" id="mwATU"> </span><span class="il" id="mwATY">60</span> <span class="n" id="mwATc">jill</span><span class="w" id="mwATg"> </span><span class="il" id="mwATk">50</span> <span class="n" id="mwATo">jane</span><span class="w" id="mwATs"> </span><span class="il" id="mwATw">20</span>
<span id="mwAT8"></span><span class="w" id="mwAUA"> </span><span class="n" id="mwAUE">q</span><span class="err" id="mwAUI">)</span><span class="ow" id="mwAUM">select</span><span class="w" id="mwAUQ"> </span><span class="ow" id="mwAUU">from</span><span class="w" id="mwAUY"> </span><span class="n" id="mwAUc">t</span><span class="w" id="mwAUg"> </span><span class="nb" id="mwAUk">where</span><span class="w" id="mwAUo"> </span><span class="n" id="mwAUs">name</span><span class="w" id="mwAUw"> </span><span class="ow" id="mwAU0">like</span><span class="w" id="mwAU4"> </span><span class="s2" id="mwAU8">"ja*"</span><span class="o" id="mwAVA">,</span><span class="n" id="mwAVE">age</span><span class="o" id="mwAVI">></span><span class="il" id="mwAVM">50</span> <span class="w" id="mwAVQ"> </span><span class="n" id="mwAVU">name</span><span class="w" id="mwAVY"> </span><span class="n" id="mwAVc">age</span> <span class="w" id="mwAVg"> </span><span class="o" id="mwAVk">--------</span> <span class="w" id="mwAVo"> </span><span class="n" id="mwAVs">jack</span><span class="w" id="mwAVw"> </span><span class="il" id="mwAV0">60</span> <span class="w" id="mwAV4"> </span> <span class="w" id="mwAV8"> </span><span class="n" id="mwAWA">q</span><span class="err" id="mwAWE">)</span><span class="ow" id="mwAWI">select</span><span class="w" id="mwAWM"> </span><span class="nv" id="mwAWQ">rows</span><span class="o" id="mwAWU">:</span><span class="nb" id="mwAWY">count</span><span class="w" id="mwAWc"> </span><span class="n" id="mwAWg">i</span><span class="w" id="mwAWk"> </span><span class="ow" id="mwAWo">by</span><span class="w" id="mwAWs"> </span><span class="n" id="mwAWw">age</span><span class="w" id="mwAW0"> </span><span class="ow" id="mwAW4">from</span><span class="w" id="mwAW8"> </span><span class="n" id="mwAXA">t</span> <span class="w" id="mwAXE"> </span><span class="n" id="mwAXI">age</span><span class="o" id="mwAXM">|</span><span class="w" id="mwAXQ"> </span><span class="n" id="mwAXU">rows</span> <span class="w" id="mwAXY"> </span><span class="o" id="mwAXc">---|</span><span class="w" id="mwAXg"> </span><span class="o" id="mwAXk">----</span> <span class="w" id="mwAXo"> </span><span class="il" id="mwAXs">20</span><span class="w" id="mwAXw"> </span><span class="o" id="mwAX0">|</span><span class="w" id="mwAX4"> </span><span class="il" id="mwAX8">1</span> <span class="w" id="mwAYA"> </span><span class="il" id="mwAYE">50</span><span class="w" id="mwAYI"> </span><span class="o" id="mwAYM">|</span><span class="w" id="mwAYQ"> </span><span class="il" id="mwAYU">2</span> <span class="w" id="mwAYY"> </span><span class="il" id="mwAYc">60</span><span class="w" id="mwAYg"> </span><span class="o" id="mwAYk">|</span><span class="w" id="mwAYo"> </span><span class="il" id="mwAYs">1</span>

