Question on the Null Item (::)

The “null item” is a bit of a syntactic anomaly, no?

It appears to act like an atom, but has a positive type of 101h which indicates that it’s non-atomic.

q)type ::

returns

@:

What does this mean?

q)c : (1; 2; ::)

q)c[::]

1

2

::

Tells us that it is not a 1-item list.

Does it really have any purpose other than perhaps a generic placeholder that keeps what would be simple lists from being simple? 

q)type (::)
101h

q)type (::; ::; ::)

0h

So although it has a type of 101h it cannot be used to construct a simple list even if the list contains only null items.

type is ‘q’ syntactic sugar for ‘k’ monadic function @.
q) type ::     is the same as    _q) type    _which gives the definition for the function type as is defined in q.k:  type:@:


You can get the type of :: (which is 101h - an unary primitive) using:


q)(@)(::)

101h

There are several uses for ::

  1. :: is the identity function (returns its own argument)

  2. Used inside a function assigns to a global variable:

q){local:123}[]

123

q)local

'local

q){global::123}[]

q)global

123

  1. Can be used to define an alias/view:

q)a:1 2 3

q)b:4

q)c::a+b

q)d:a+b

  

q)c

5 6 7

q)d

5 6 7

q)b:5

q)c

6 7 8

q)d

5 6 7

  1. As a null can keep a list general

I may be missing some other uses…

Thanks Tiago.  Yes it is heavily over-loaded. lol … I was wondering if it’s use as a null item had any more interesting uses other than keeping a list general or eliding an index, but it does seem to be the case.  I appreciate the detailed reply as usual!

So when denoted as a literal constant for “the null item” it has to be inside parentheses?

type ::

and

count ::

seem to return vestiges from k and the expression:

:: ~ ::

returns an error

even though the null item is atomic (and not a singleton) as far as I can tell.  Thanks for any additional insight.

When you’re juxtaposing :: to a function is the same as calling the function with no arguments. That’s why you get the functions definitions.

I may be getting out of my depth here, but in C you can return the identity function (::) with:

K identity(){ K id=ka(101); id->g=0; return id;}

From the K object definition in k.h:

typedef unsigned char G;

typedef struct k0{signed char m,a,t;C u;I r;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{J n;G G0[1];};};}*K;

So its in fact an atom of type 101h with the unsigned char member of the union set to 0.

You can see its reference count with:

q)-16!(::)

14i

q)-16!(::)

14i

q)a:(::)

q)-16!(::)

15i

Interestingly enough you can’t see the variable a being assigned to the :: object:

q)\v

q)

Though you can assign it:

q)b:(1; 2; a)

q)b

1

2

::

q)-16!(::)

16i

And even free it:

q)a:()

q)-16!(::)

15i

  I second you that there should be an updated K/Q reference manual that lays the behaviour of the language. Otherwise we’re just inferring from its behaviour which may lead to some wrong conclusions. I guess its a deliberate move from kx to protect its intellectual property but its frustrating at times. Don’t know if there’s one available to paid customers (I’d actually like to know that).

  You may be probably interested to take a look at this old K reference manual (available only through payback machine. its outdated and relative to K v2). Some things have changed but I found it quite helpful to improve my understanding of how Q/K works: K reference manual

 Hope any of this helps :)

Obviously I meant wayback (not payback) machine :)

Much of this is alrady documented at http://code.kx.com/wiki/Reference/ColonColon

as an infix dyad, :: is
global assign if inside a function
assign if outside a function and a space before ::
create view if outside of a function and no space before ::.

e.g.

/view, note no space between target variable ‘a’ and ::

a::b+c

/assign, note space between target variable ‘a’ and ::
a ::b+c

/assign to global from within lambda

{a::b+c}

wrapping in () changes verb to noun. e.g. (+) as flip
q)(+)(1 2;3 4)
1 3
2 4

q)b:2;c:3;a(::)b+c / identity, not assign, hence error
'a

Missing arg and identity (op which returns its arg; a “no-op”) are not quite the same

q)(null;{-8!x}‘;type’)@:0N!1_value {[x;y]}[::;]
(::;::)
1                      0                    
0x010000000a0000006500 0x010000000a00000065ff
101                    101  

even though the display and type id are the same, null and serialization reveal they are not.

q)(-8!)@/:1 _ value{x+y}[::;]  / missing arg projects -8!
0x010000000a0000006500
![-8;]

q)1 2 3(::) / identity used as index, just return the lhs
1 2 3

q)(::)1 2 3 / identity monad, just return the rhs
1 2 3

q)eval(::;a;0) / dyadic, assign 0 q)eval(::;a) / monadic, identity
0

identity can be useful in functional programming.