# Going down the branchless FizzBuzz rabbit hole in APL

I read a bit about APL earlier this week from Xpqz's Learn APL and decided to try FizzBuzz in APL using TryAPL. How hard could it be, right?

Wrong.

Here's what the finished program looked like:

```
⍝ Explicitly set the first index, because it affects iota (⍳, as in ⍳100).
⍝ Note 1 is the default first index.
⎕IO ← 1
range ← ⍳100
output ← ↓(⍕⍤0)range
((0=3|range)/output) ← ⊂'fizz'
((0=5|range)/output) ← ⊂'buzz'
((0=15|range)/output) ← ⊂'fizzbuzz'
⎕ ← ↑output
```

Breaking this down:

- We set the first index. APL is 1-indexed by default (so the first index is 1), but you can set it to be 0-indexed, so just in case we explicitly set a 1-index.
`range`

is assigned the vector of integers from 1 to 100, inclusive.`output`

is assigned a vector of boxed string versions of each integer. Ordinarily the format operator`⍕`

would format the*vector itself*as a string, so we would get the string`'1 2 3 4 ... 100'`

(where ... is replaced with the intervening numbers, separated by spaces), i.e. a string 291 characters long. I use`⍕⍤0`

to convert the format operator to operate elementwise over its operand. Finally,`↓`

converts the result (a 100x3 character matrix) to a vector of boxed strings by boxing the rows.`((0=3|range)/output) ← ⊂'fizz'`

is a special assignment statement.`0=3|range`

is a vector of booleans (*boolean mask*). It's 1 at each element of`range`

that is divisible by 3 and 0 everywhere else.`(mask/vector) ← value`

is a special assignment form that assigns to only those parts of vector corresponding to 1s in the mask. So this says: Assign the boxed string`'fizz'`

where the number is divisible by 3. The other two statements work similarly.`⎕ ← ↑output`

produces output by assigning to`⎕`

— this is how you print in APL. The`↑`

converts`output`

from a vector of boxed strings into a character matrix so that each string is printed on its own line. (This means trailing spaces also get printed. For example, we print`1`

rather than`1`

. That's because the matrix has to be 10x8 to accomodate the`fizzbuzz`

— every row in the matrix has to have the same number of columns.)

Some pain points that came up in trying to do this in APL:

- Initially I just did
`output ← (⍕⍤0)range`

, but this gives a 10x3 matrix of characters. I tried expanding to 10x8 with`output ← ((⍕⍤0)range),(' '⍴⍨(≢range) 5)`

, and this works fine, but things get annoying when you want to mask and set entire rows to`'fizz '`

,`'buzz '`

, or`fizzbuzz`

based on the row number. I couldn't find a convenient way to do this based on a mask of`0=X|range`

. Eventually I settled on`↓(⍕⍤0)range`

which gives an array of 100 boxed 3-character strings. - Initially I wanted to do the simpler
`mask/output ← value`

pattern, but I got a length error. I solved the length error by boxing the values. That's what the`⊂`

is for. - However, for some reason when I did
`(0=3|range)/output ← ⊂'fizz'`

, this whole expression returned a long (33-element) array where every element is just the boxed string`fizz`

. Worse, afterward the`output`

was a vector containing only a single boxed string, namely the string`'fizz'`

! I tried a different approach using the`@`

operator,`{⊂'fizz'}@{0=3|range}⊢output`

, and this seemed to work, but I think it is harder to read. - I eventually figured out how to fix this.
`output`

was getting replaced with`⊂'fizz'`

because the APL interpreter was interpreting the expression as`(0=3|range)/(output←'fizz')`

. Parenthesizing the`(mask/output)`

pair fixed the problem, so I was able to get rid of the more complicated`{}`

notation.

I learned a few things about APL from this:

- Vectors of boxed strings are easier to work with in some cases than character matrices. You can turn a character matrix into a vector of boxed strings with
`↓charMatrix`

. - When assigning to a vector of boxed strings, you have to explicitly box the string(s) you assign. If you don't, you might get a length error.
- When using
`(mask/array) ← value`

, always parenthesize`mask/array`

like that, otherwise you may get confusing results when`value`

is a complex expression.

An interesting thing about this program is that it's branchless. We set a first-pass output (the boxed number strings). We then compute which outputs we want to change and then change only those indices. That means we never need an if-statement to decide which string to output.