Search code examples
kdb

Amend cross sections for single element


I'm playing around with an example on https://code.kx.com/q/ref/amend/#cross-sections

$ q
KDB+ 3.6 2019.04.02 Copyright (C) 1993-2019 Kx Systems
q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
q)i:(2 0; 0 1 0)
q)y:(100 200 300; 400 500 600)
q)r:.[d; i; ,; y]

It all works fine except if I'll try to reference a single element d[1;1]:

q)i:(1 0; 0 1 0)
q)r:.[d; i; ,; y]
'type
  [0]  r:.[d; i; ,; y]

But if I use join , for lists and for just single element it works as supposed:

q)10,200
10 200
q)10,((),200)
10 200

So why the amend operation breaks on this simple join?

Upd:

One more example:

q)@[(1; 2; 3);1;,;10]
'type
  [0]  @[(1; 2; 3);1;,;10]
       ^

but it's ok if one use lists:

q)@[(1; (),2; 3);1;,;10]
1
2 10
3

Solution

  • The answer lies in examining the data you are extracting to join, here the operator -3! is your friend to help reveal the actual structure through multiple layers of enlistment

    q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
    q)i1:(2 0; 0 1 0)
    q)i2:(1 0; 0 1 0)
    q)y:(100 200 300; 400 500 600)
    q)-3!r1:.[d; i1]
    "((13 14;15 16 17 18;13 14);(1 2 3;4 5 6 7;1 2 3))"
    q)q){type each x} each .[d; i1]
    7 7 7
    7 7 7
    q)-3!r2:.[d; i2]
    "((8 9;10;8 9);(1 2 3;4 5 6 7;1 2 3))"
    q){type each x} each .[d; i2]
    7 -7 7
    7 7  7
    

    No here we can see that in the first case, each element of r1 is a list of lists, but for r2 the first element is 2 lists of longs with an atomic long 10.

    From the cross section documentation

    The shape of y is 2 3, the same shape as the cross-section selected by d . i

    i.e., Shape should be the counts and types matching, the type of each item of y is a 7h, that should match the type of each selection from d.

    Essentially when you are using the amendment operators , and @ it will be expecting conformity as it is using an amend in place. a:1;a,:1 2 3 will also fail.

    We can confirm this with your other examples

    q)type @[(1; (),2; 3);1]
    7h
    

    Changing that example to adjust the first element

    q)@[(1; (),2; 3);0;,;10]
    'type
    

    The reason that just using the , operator as 10,((),200) didn't cause any errors, is because you are using it outside the amend overloads, within the amend overload , is expecting to be working with matching shape. When used directly it can promote and adjust shape.