4

In kdb+/q, how to pipe data through a sequential list of functions so that output of previous step is the input to next step?

For example:

q)t:([]sym:`a`c`b;val:1 3 2)
q)`sym xkey `sym xasc t                / how to achieve the same result as this?

I presume some variation of over or / could work:

   ?? over (xasc;xkey)

Bonus: how to achieve the same in a way where t is piped in from the right-hand side (in the spirit of left-of-right reading of the q syntax)?

(xasc;xkey) ?? t
Daniel Krizian
  • 4,586
  • 4
  • 38
  • 75

2 Answers2

7

how to pipe data through a sequential list of functions so that output of previous step is the input to next step?

You can use the little known composition operator. For example:

q)f:('[;])over(2+;3*;neg)
q)f 1 # 2+3*neg 1
-1

If you want to use the left of right syntax, you will have to define your own verb:

q).q.bonus:{(('[;])over x)y}
q)(2+;3*;neg)bonus 1
-1
Will Da Silva
  • 6,386
  • 2
  • 27
  • 52
Alexander Belopolsky
  • 2,228
  • 10
  • 26
  • mindblowing, thanks for uncovering that composition operator! Very useful. Btw, to process the list from the beginning (usual notion of the beginning of the list is the leftmost, i.e. `neg` in this case) : `('[;])over reverse (neg;3*;2+)` - firstly `neg`ate, then multiply by 3, then add 2, equals -1 – Daniel Krizian Aug 04 '17 at 06:37
2

Use a lambda on the left as well as the over adverb (form of recursion) Also the dot (.) form of apply is used to apply the function to the table and the column:

  {.[y;(z;x)]}/[t;(xasc;xkey);`sym]
  sym| val
  ---| --- 
  a  | 1
  b  | 2
  c  | 3
jomahony
  • 1,662
  • 6
  • 9
  • Excellent! I tried to wrap my head around `.[;(;)]` and then I realised it's equivalent to (shorter) ``{y .(z;x)}/[t;(xasc;xkey);`sym]`` or even shorter ``{y[z;x]}/[t;(xasc;xkey);`sym]`` – Daniel Krizian Aug 04 '17 at 06:53