tenticon
tenticon

Reputation: 2913

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?

Upvotes: 1

Views: 336

Answers (1)

Thomas Smyth
Thomas Smyth

Reputation: 5644

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.

Upvotes: 1

Related Questions