kdb+k

Table transformation, table as list of dicts


Please help me with t1 transformation through the following path:

t1:enlist `a`b!1 2;
t2:exec val from ([]val:t1);
-3!t1    // +`a`b!(,1;,2)
-3!t2    // ,`a`b!1 2
t1~t2[;] // 1b

I expect that the 2nd line (exec) returns the same object as t1, but it is not. For some reason only [;] gets t1 from t2.

So what (and why) happens on lines 2 and 5?


UPD Why the enlist is so fruitful? It makes enlist for each element, and also flips the entire object

-3!enlist `a`b!1 2           // +`a`b!(,1;,2)
-3!enlist each `a`b!1 2      //  `a`b!(,1;,2)
-3!flip enlist each `a`b!1 2 // +`a`b!(,1;,2)

Solution

  • I think what's happening here is that the special promotion of lists of (conforming) dictionaries to a table is essentially "undone" when it becomes the column of a table. It goes back to being lists of dictionaries as if they were non-conforming, though misleadingly the terminal still displays it as if it was a table. To see this, consider this example:

    /promoted to table
    q)-3!(`a`b!4 5;`a`b!1 2)
    "+`a`b!(4 1;5 2)"
    /still a table (embedded)
    q)-3!enlist(`a`b!4 5;`a`b!1 2)
    ",+`a`b!(4 1;5 2)"
    /still a table (embedded)
    q)-3!(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    "(,`val)!,+`a`b!(4 1;5 2)"
    /no longer a table, now a list of dictionaries
    q)-3!flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    "+(,`val)!,(`a`b!4 5;`a`b!1 2)"
    /extracting the column gives an "un-promoted" list of dictionaries
    q)-3!exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    "(`a`b!4 5;`a`b!1 2)"
    /even though there are two of them and they both have type 99h, it is not a table
    q)count exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    2
    q)type each exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    99 99h
    q)type exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    0h
    
    /so it is not comparable to something that has the promotion, even though the terminal makes them appear the same
    q)((`a`b!4 5;`a`b!1 2))~exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    0b
    q)(`a`b!4 5;`a`b!1 2)
    a b
    ---
    4 5
    1 2
    q)exec val from flip(1#`val)!enlist(`a`b!4 5;`a`b!1 2)
    a b
    ---
    4 5
    1 2
    

    Your case is the same thing but for a single dictionary rather than two, but I think two dictionaries makes it easier to see.