The Rank Of Verbs Generated By Modifiers
You can get confused when you start writing code that contains modifiers.
ALGORITHM: square the operand (3 4), sum the resulting numbers, then take the square root of the result.
%: +/ *: 3 4 5
length =: verb define %: +/ *: y ) length 3 4 5
it seems to work well.
Soon you learn about tacit verb definition. Suppose you now want to write your verb: length tacitly. First you try
length =: %: +/ *: length 3 4 10.7321 17.7321 11 18
That's no good!
You later learn that you have mistakenly written a fork.
Finally you learn about u@v which executes v followed by u. That sounds like what you want. So next you try
length =: %: @ (+/) @ *: length 3 4 3 4
That's no good either!
But someone suggests a tiny change: use (@:) instead of (@)
length =: %: @: (+/) @: *: length 3 4 5
Now it seems to work well.
What's the difference between (@:) and (@)? And why does it matter?
The difference lies in the ranks of the two different tacit verbs you wrote.
%: @ (+/) @ *: b.0 NB. (ranks of) the wrong verb 0 0 0 %: @: (+/) @: *: b.0 NB. (ranks of) the right verb _ _ _
- The wrong verb has rank zero, which means that your verb gets applied to each number individually.
- The right verb has rank infinity (_), meaning that your verb gets applied to the entire array, in one go.
If you had checked the rank of Atop (@) before you used it, the page would have told you that the rank of u@v is the same as the monadic rank of v. Since the rank of Square (*:) is 0, you'd have realized that the only possible rank for %: @ (+/) @ *: was 0.
The difference is shown in the first two columns of the following diagram: