Scan and Over – iterating through lists

One of the first things I was told by my ex boss was to never use for/while loops unless it’s a matter of life and death. And he was dead serious. I had just taken two c++ classes in college so wasn’t sure how I would be able to replace for/while loops. They are easy to use and make your life easier. BUT that’s not the case in q. There are better alternatives there. Thing to remember with q is that it loves lists. If there is any operation where you can use lists, then do that!

In this post, I am going to cover two adverbs, scan and over, that you can use instead of for/while loops.

Scan – \

The scan adverb is denoted by \. You can also use the keyword scan. Scan takes a dyadic function (that’s a function that takes two arguments) and applies each item on the right side and applies it to the item on the left side. With scan, you get to see the result after each iteration.

For example,

q)1+\1 2 3
2 4 7

First, it takes 1+1 and returns 2. Then, it takes that value (2) and adds it to next value on the list (2) to return 4. Finally, it takes 4 and adds it to 3 to return 7.

In this simple example, + is the dyadic function being applied to left operand (1) and right operand (1 2 3). You can use a custom function instead of + for more practical purposes. For example:

q)4{5*x-y}\1 2 3
15 65 310

In this example, my custom function is {5*x-y}. This function takes the x value (4), subtracts y (1 2 3) from it and then multiplies it by 5. It does this for each value in the list (1 2 3). So, 4-1 is 3 and then 3*5=15.

Over – /

Over and scan are very similar. The difference is that instead of giving you result after each iteration, over just returns you the last value.

Let’s look at the same examples as above and compare the two:

q)1+\1 2 3
2 4 7
q)1+/1 2 3
7
q)4{5*x-y}\1 2 3
15 65 310
q)4{5*x-y}/1 2 3
310

As you can see, over simply returns the last value.

Different syntax

All the stuff I said above, you can find on kx website and q for mortals book. However, during a training session by David Demner (very smart guy), I was introduced to another way of using scan and over. I had forgotten about it but my colleague William Wicker reminded me of it (thanks Bill!).

Chiropractic for children is painless except when there cialis in kanada is an injury. When taking this drug for pain order cheap cialis relief or insomnia it has to be kept in mind that this drug has helped them to get rid of erectile dysfunction which may include: Erectile dysfunction or ED is a persistent difficulty achieving and maintaining an erection for sex. Anti order levitra online inflammatory, anti ulcer, anti anxiety and anti stress some among the highlighting advantages of using shiljait. Certain yoga poses are intended to improve blood viagra samples no prescription volume near male regenerative area.

The new syntax gives you an option to provide a seed and number of iterations to do as well as provide a function instead if number of iterations is not concrete. For example, let’s say I want to run the function {5*y} 5x times with the first value being 1:

q){5*x}\[5;1]
1 5 25 125 625 3125

So, what is it doing? It takes first value as 1. Then it takes that and multiples by 5 which returns 5. Then it takes 5 and multiples by 5 to give 25 and it does that 5x times…so overall you get list with 6 values.

If you use over instead, you will just get the last value, 3125.

q){5*x}/[5;1]
3125

This behavior is only valid for monadic functions. If you tried doing this with our previous dyadic function {5x*y}, you will get a different result.

q){5*x-y}\[5;1]
20

For a dyadic function, it takes 5 as the x value and 1 as the y value. 5-1 is 4 and then 5*4 is 20. You can have lists as well.

q){5*x-y}\[5 6;1]
20 25
q){5*x-y}\[5 6;1 2]
20 25
90 115
q){5*x-y}\[5 6;1 2 3]
20 25
90 115
435 560
q){5*x-y}\[5 6 7;1 2 3]
20 25 30
90 115 140
435 560 685
q){5*x-y}/[5 6 7;1 2 3]
435 560 685

Let’s go back to our monadic function {5*x} and instead of running the function for a specific number of iterations, we will run it as long as a condition is true.

q)f:{5*x}
q)f\[{f[x]>400};1]
1 5 25 125

Here, I first defined our function as f and then in the iteration part, defined another function which checks for condition f[x]>400. Changing that condition will change the result as well:

q)f\[{f[x]>800};1]
1 5 25 125 625

That’s it for now. Whenever you feel the urge to use a do/while loop, just remember that there might be a better alternative out there.

Credits: Thanks to David Demner for clearing out some doubts for me.

Leave a comment

Your email address will not be published. Required fields are marked *