Views

A view is a calculation that is re-evaluated only if the values of the underlying dependencies have changed since its last evaluation.

Splayed tables

To use views with splayed tables make sure you invalidate the data when it changes; this can be done for example by reloading the table.

Why use a view?

Views can help avoid expensive calculations by delaying propagation of change until a result is demanded.

How is a view defined?

The syntax for the definition is

q)viewname::[expression;expression;…]expression

The following defines a view called myview which depends on vars a and b.

q)myview::a+b
q)a:1
q)b:2
q)myview
3

Defining a view does not trigger its evaluation.

A view should not have side-effects, i.e. should not update global variables. Although ; is permitted at the end of the definition, it would mean the view returns (::). As a view should have no side-effects, returning (::) would make the purpose of the view redundant.

A view definition can be spread over multiple lines in a script as long as it is indented accordingly (e.g. exactly like a function definition). e.g.

$cat v.q
t:([]a:til 10)
myview::select from t
 where a<5 / note this line is indented by one space
$q v.q
KDB+ 3.2 2014.08.26 Copyright (C) 1993-2014 Kx Systems
m64/...
q)myview
a
-
0
1
2
3
4

How to list views

Invoke the views function (or \b) to get a list of the defined views.

q)a::b+c
q)d::b+a
q)views`
`s#`a`d

How to list invalidated views

Invalidated (pending) views are awaiting recalculation.

Invoking \B will return a list of pending views.

q)a::b+c
q)\B
,`a
q)b:c:1
q)\B
,`a
q)a
2
q)\B
`symbol$()

How to see the definition of a view

The text definition of a view can be seen with view `viewname.

q)a::b+c
q)view`a
"b+c"

The following view command has the form `. `viewName. Note the space between `. and `viewname.

q)d::b+a
q)`. `d
b+a

value on that reveals the underlying representation:

  • (last result|::)
  • parse-tree
  • dependencies
  • text
q)value`. `d
::
(+;`b;`a)
`b`a
"b+a"

If previously evaluated, the last result can be seen here as the first element.

q)b:1;a:2
q)d
3
q)value`. `d
3
(+;`b;`a)
`b`a
"b+a"

A view which uses select/exec/update/delete is worth mentioning as it may not be immediately obvious what dependencies are present. e.g. in the following example, t is the only dependency, as a and b may be columns in t, or globals – this is not known until the select is evaluated and hence cannot be inferred as dependencies.

q)v::select from t where a in b
q)value`. `v
::
(?;`t;,,(in;`a;`b);0b;())
,`t
"select from t where a in b"

If a or b are globals to be dependencies, a workaround is for these is to be mentioned at the beginning of the definition, e.g.

q)v::a;b;select from t where a in b
q)value`. `v
::
(";";`a;`b;(?;`t;,,(in;`a;`b);0b;()))
`a`b`t
"a;b;select from t where a in b"

If a function is used within a view, that does not become a dependency. The following view would not be invalidated unless the f were redefined.

q)v::f[]+1
q)f:{42}
q)v
43
q)value`. `v
43
(+;(`f;::);1)
,`f
"f[]+1"

Self-referencing views

Self-referencing views are allowed since V3.2. A self-referencing view is a view that includes itself as part of the calculation. In such a case, the view uses its previous value as part of the evaluation if it exists, otherwise it signals 'loop. e.g.

q)v::$[b;1;v+1]
q)b:1;0N!v;b:0;v
q)v::$[b;1;v+1]
q)v
'loop

From V3.2 view-loop detection is no longer performed during view creation; it is checked during the view recalc.

Dot notation

Views do not support dot notation.

q)t:.z.p
q)t1::t
q)t.date
2014.09.03
q)t1.date
'nyi

Multithreading

Views must be evalulated on the main thread, otherwise the calculation will signal 'threadview. E.g. with q using 2 slave threads

$q -s 2
KDB+ 3.2 2014.08.26 Copyright (C) 1993-2014 Kx Systems
m64/...
q)a::b+c
q)b:c:1
q){a}peach 0 1
k){x':y}
'threadview
@
{a}':
0 1
q.q))\
q)a
2
q){a}peach 0 1
2 2

Parse

Views are not parsable, e.g. eval parse "a::b+c"

view, views, \b, \B, .z.b, .z.vs