0

Sorry if this is a newbie question again.

I am trying to replicate the functionality of interfaces as seen in c++, rust etc. in kdb as is shown in a simple demonstration below:

q).iface.a.fun:{x*y+z}
q).iface.b.fun:{x*x+y+z}
q)ifaces:`a`b; // for demonstration purposes
q)tab:([]time:`datetime$();kind:`ifaces$();x:`long$();y:`long$();z:`long$());
q)n:10;
q)tab,:flip(n#.z.z;n?ifaces;n?10;n?10;n?10)

Now you would assume that the kind would be able to reference the `a`b fun methods of the iface interface as follows:

q)?[`tab;();0b;`max`ifaceval!((max;`x);(`.iface;`kind;`fun;`x;`y;`z))] 
evaluation error:

fun

  [0]  ?[`tab;();0b;`max`ifaceval!((max;`x);(`.iface;`kind;`fun;`x;`y;`z))]
       ^

Obviously the functional nature of the select inhibits referencing the fun method on account of the symbol type field declarations. You can avert this error by using enlist as follows:

q)?[`tab;();0b;`max`ifaceval!((max;`x);(`.iface;`kind;enlist`fun;`x;`y;`z))] 
max ifaceval                                                                    ..
-----------------------------------------------------------------------------..
9   77 154 95 65 0 128 153 126 60 49 77 154 95 65 0 128 153 126 60 49 77 154 ..

However this duplicates the result of fun for each row. How might one effectively go about this without getting the above malformed responses? Thanks again.

Cathal O'Neill
  • 2,522
  • 1
  • 6
  • 17

1 Answers1

1

Selecting ifaceval first will ensure each row is returned. max x is a scalar, which forces all the ifaceval entries into one row. The scalar will be expanded across all rows if a vector column precedes it.

q)?[`tab;();0b;`ifaceval`max!((`.iface;`kind;enlist`fun;`x;`y;`z);(max;`x))]
ifaceval                          max
-------------------------------------
160 11 126 28 32 60 76 10 112 168 8
96  10 77  24 16 35 60 6  63  104 8
96  10 77  24 16 35 60 6  63  104 8
96  10 77  24 16 35 60 6  63  104 8
96  10 77  24 16 35 60 6  63  104 8
160 11 126 28 32 60 76 10 112 168 8
96  10 77  24 16 35 60 6  63  104 8
160 11 126 28 32 60 76 10 112 168 8
160 11 126 28 32 60 76 10 112 168 8
160 11 126 28 32 60 76 10 112 168 8

I'm not sure if this is exactly what you're looking for though. If you want to calculate ifaceval for each row in the table, this should work.

q)?[tab;();0b;`ifaceval`max!(((';(`.iface;::;enlist`fun));`kind;`x;`y;`z);(max;`x))]
ifaceval max
------------
160      8
10       8
77       8
24       8
16       8
60       8
60       8
10       8
112      8
168      8

One point to make is that it's probably best to avoid using kdb keywords for column names. Although it works in functional queries, it does not for qSQL ones.

q)select max:max x from tab
'assign
  [0]  select max:max x from tab
                 ^
Cathal O'Neill
  • 2,522
  • 1
  • 6
  • 17