Search code examples
kdbk

Enum does not hold its keys, only a ref to keys instead


According to documentation at https://code.kx.com/q/ref/enumerate/

Enumerate

Syntax: x$y, $[x;y]

Where

  • x and y are lists

I suppose a correct way to create enum would be through giving lists to the $:

q)e:`a`b`c$`b`a`c`c`a`b
'length
  [0]  e:`a`b`c$`b`a`c`c`a`b
               ^

but obvious it is not. After reading more examples I tried:

q)mykeys:`a`b`c
q)show e:`mykeys$`b`a`c`c`a`b
`mykeys$`b`a`c`c`a`b

And it works. But then I've seen that my enum e contains its values and only a reference to its keys mykeys:

q)(key;value)@\:e
`mykeys
`b`a`c`c`a`b
q)`:e.raw set e
`:e.raw

So saving e to a file saves no keys! In a fresh session:

q)e: get `:e.raw
q)e
`mykeys!1 0 2 2 0 1
q)mykeys
'mykeys
  [0]  mykeys
       ^
q)mykeys:`a`b`c
q)e
`mykeys$`b`a`c`c`a`b

I know one could save keys with a neat enum extend functionality:

q)`:mykeys?`b`a`c`c`a`b;
q)get `:mykeys
`b`a`c

But why do enums act like this? - it seems like they hardly splitted apart into keys and values. May be in a big picture with tables, indexes, table splaying it makes more sense.

And how enumeration could exists just after loading from a file? Is it a semi-normal state when its keys domain does not exist yet?:

q)e: get `:e.raw
q)e
`mykeys!1 0 2 2 0 1

Solution

  • This behaviour is by design because, like you presumed, there is a bigger and more generalised picture.

    Enums are primarily used for:

    1. the sym file, in which the syms (keys) are always stored permanently in the database with the help of enum-extend ?
    2. foreign-keys, as per https://code.kx.com/q4m3/8_Tables/#852-example-of-simple-foreign-key

    In the latter case, it would not make sense to also store the keys with the enumeration because the keys are contents of a table. It is presumed that if you will persist the enum then you will also persist the table which contains the keys.

    A similar concept is column-linking - https://code.kx.com/q/kb/linking-columns/

    Finally, the reason

    `a`b`c$`b`a`c`c`a`b
    

    didn't work is because the list you're enumerating against must be passed by name, not passed by value. So it has to be

    `mykeys$`b`a`c`c`a`b