Search code examples
kdb+q-lang

q - internal state in while loop


In q, I am trying to call a function f on an incrementing argument id while some condition is not met.

The function f creates a table of random length (between 1 and 5) with a column identifier which is dependent on the input id:

f:{[id] len:(1?1 2 3 4 5)0; ([] identifier:id+til len; c2:len?`a`b`c)}

Starting with id=0, f should be called while (count f[id])>1, i.e. so long until a table of length 1 is produced. The id should be incremented each step.

With the "repeat" adverb I can do the while condition and the starting value:

{(count x)>1} f/0

but how can I keep incrementing the id?


Solution

  • Not entirely sure if this will fix your issue but I was able to get it to work by incrementing id inside the function and returning it with each iteration:

    q)g:{[id] len:(1?1 2 3 4 5)0; id[0]:([] identifier:id[1]+til len; c2:len?`a`b`c);@[id;1;1+]}
    

    In this case id is a 2 element list where the first element is the table you are returning (initially ()) and the second item is the id. By amending the exit condition I was able to make it stop whenever the output table had a count of 1:

    q)g/[{not 1=count x 0};(();0)]
    +`identifier`c2!(,9;,`b)
    10
    

    If you just need the table you can run first on the output of the above expression:

    q)first g/[{not 1=count x 0};(();0)]
    identifier c2
    -------------
    3          a
    

    The issue with the function f is that when using over and scan the output if each iteration becomes the input for the next. In your case your function is working on a numeric value put on the second pass it would get passed a table.