In short, it's a parse tree signature 'type' construct, very similar to lambda (which would be type 64). k
recognises and evaluates expression in parse tree when object reaches call stack, de-referencing symbols-which acts like a pointer.
TL;DR - Step by step breakdown
- Basic evaluation constructs
"x[y]" ~ "x y"
q)x:count
q)y: 1 2 3
q)parse "x y"
x
y
q)x y
3
q)`x y
3
q)eval parse "x y"
3
Simple indexing, 'simplified' 2nd param -> int atom:
q)parse "y 2" //this nicely shows parse tree
`y
2
q)eval parse "y 2"
3
q)eval (`y;2)
3
q)`y 2
3
q)y 2
3
Both above examples are mixed lists (0h), with actual elements following immediately - where symbols - are references. Instead with normal mixed list construct where all lenghts and types are defined later
- Looking at serialised IPC frame helps to understand this construct
Establish what expressions are the same
q)parse["x[y]"] ~ parse "x y"
1b
q)parse["x[y]"] ~ parse "x@y"
0b
q)parse["x[y]"] ~ parse "{x y}"
0b
Compare byte frames
q)-8!parse "x[y]"
0x0100000014000000000002000000f57800f57900
q)-8!parse "x y"
0x0100000014000000000002000000f57800f57900
q)-8!`x`y
0x01000000120000000b000200000078007900
q)-8!enlist `x`y
0x01000000180000000000010000000b000200000078007900
Compare parse tree output from 1st paragraph with actual obj instead of reference
q)-8!parse "x y"
0x0100000014000000000002000000f57800f57900
q)-8!parse "x 2"
0x010000001a000000000002000000f57800f90200000000000000
Lambda structure to complete the list for reference
q)-8!{x y}
0x010000001500000064000a00050000007b7820797d
/0x7b "{" ; 0x7d "}"
- And finally the IPC frame breakdown
`x`y (symbol list)
q)symlist:`endian`isync`x`y`length`type`attr`msg!sums[0 1 1 1 1 4 1 1] _ -8!`x`y
q)symlist
endian| ,0x01 (little endian)
isync | ,0x00
x | ,0x00
y | ,0x00
length| 0x12000000
type | ,0x0b (11h - symbol list - 1st difference)
attr | ,0x00
msg | 0x0200000078007900
dig into the symlist:
q)msg:`lenght`msg!sums[0 4] _ symlist`msg
q)msg
lenght| 0x02000000
msg | 0x78007900
Here we can clearly see, how null terminated symbol follows length of vector immediately, due to explicit type: 0x0b - 11h - symbol list
q)`char$msg`msg
"x\000y\000"
parse "x[y]"
- parse tree breakdown
q)o1:`endian`isync`x`y`length`type`attr`msg!sums[0 1 1 1 1 4 1 1]_ -8!parse"x[y]"
q)o1
endian| ,0x01
isync | ,0x00
x | ,0x00
y | ,0x00
length| 0x14000000
type | ,0x00 (could expect 64 - 100h lambda)
attr | ,0x00
msg | 0x02000000f57800f57900
Difference from simple list:
q)`lenght`type1`msg1`type2`msg2!sums[0 4 1 2 1 ] _ o1`msg
lenght| 0x02000000
type1 | ,0xf5 (-11h - symbol atom) - acts as a reference
msg1 | 0x7800 null terminated "x"
type2 | ,0xf5 (-11h - symbol atom)
msg2 | 0x7900 null terminated "y" - acts as a reference