Well, I’m quite late with this week’s challenges. Again, I was only going for the silver medal of doing any three languages, but I didn’t have a lot of time to spare for the challenges last week, and I also spent more time than I should have tweaking my haskell solution in particular.

This week’s exercise is fizzbuzz, but slightly different.

# JavaScript

First up, here’s my javascript solution.

```
export const convert = (num) => {
let s = [[3, "Pling"], [5,"Plang"], [7,"Plong"]]
.map(([x,y]) => num % x === 0 ? y : "")
.join("");
return s === "" ? num.toString() : s;
};
```

The basic idea is to take a list of pairs (a divisor and a string) and map that pair to the string if $n$ is divisible by the divisor, or map to the empty string otherwise. We then join those strings together. The final wrinkle is to check if the string we have left over is is still empty, and if it is, return the number as a string, rather than the resultant string.

It’s kind of terse, but none of the components are that mysterious.
We’ve got the ternary operator `p ? x : y`

which evaluates to `x`

if `p`

is true and `y`

otherwise.
So `z = p ? x : y`

is just a more compact way of doing:

```
let z;
if (p) {
z = x;
} else {
z = y;
}
```

We’ve got `map`

which takes an array and puts each element through the provided function:
`a.map(f)`

is just a more compact way of doing:

```
let z = []
for (let x of a) {
z.push(f(x));
}
```

Finally, we’ve got an anonymous function which is just a quick way of defining a function that isn’t worth writing out using `function`

.
So instead of writing `([x,y]) => num % x === 0 ? y : ""`

as the argument to `map`

, we could have defined the function first:

```
function f([x,y]) {
return num % x === 0 ? y : "";
}
```

`num`

, here, is the input to `convert`

and if we’re defining this function inside `convert`

we can effectively treat `num`

as a constant.

It took a little while (and a little complaining on social media) to get the argument to this function right. But that’s a topic for another day.

# Clojure

Next up we have Clojure.

```
(ns raindrops)
(defn p [d inString]
(fn [[accString n]]
(if (= 0 (mod n d))
[(str accString inString) n]
[accString n]
)
)
)
(def plong (p 7 "Plong"))
(def plang (p 5 "Plang"))
(def pling (p 3 "Pling"))
(defn convert [n] ;; <- arglist goes here
(def plingString (first (plong (plang (pling ["" n])))))
(if (= 0 (count plingString)) (str n) plingString)
)
```

So the first thing I’m doing here is creating a function that creates functions.
It takes two arguments, a divisor `d`

and a string `inString`

,
and it outputs a function that takes a list of a string and a number `[accString n]`

.
The output function’s number argument `n`

is the input to `convert`

and the string is the accumulation of all the “Pling"s etc that have been found so far `accString`

.
The function checks if the number `n`

is divisible `d`

, and if it is, appends `inString`

to `accString`

and returns the list of that string,
plus the `n`

that was the input.
So the input and output types for this function are the same.
I then create functions `pling`

, `plang`

, and `plong`

which check for the relevant divisibility property.
Each of these outputs something that can be consume as the input to the others, so I can then just compose them.
Each function passes the input to `convert`

through to its output so that when they’re composed, each function knows
what number they’re converting.
So `(plong (plang (pling ["" 21])))`

becomes:

```
(plong (plang ["Pling" 21]))
(plong ["Pling" 21])
["PlingPlong" 21]
```

Then all we need to do is take the first element of this pair, and check if it’s `""`

.
If not, no problem, output the string.
If it is, then output the number as a string instead.
There’s probably a better way to check for an empty string,
but I was short of time.

# Haskell

Both of these solutions rely on using `""`

as an indicator that none of 3, 5 or 7 divide the input number.
This is fine, but you can imagine that maybe you want to add a rule that says “If the number is divisible by 11 and nothing else, output the empty string”.
Now you could easily add `[11, ""]`

to the list in the javascript solution, but `convert(11)`

would output `11`

,
rather than `""`

because it’s checking for the empty string.
You could get around this, but it’s probably going to be a little awkward.
The same is true for the clojure approach.
For my haskell solution, I decided to try to handle this possibility a little more gracefully
using `Maybe`

.

```
module Raindrops (convert) where
import Data.Maybe
convert :: Int -> String
convert n = if null plingList then show n else concat plingList
where plingList :: [String]
plingList = catMaybes $ map ($ n) plingFunctions
plingFunctions :: [Int -> Maybe String]
plingFunctions = map singleConvert [(3,"Pling"), (5,"Plang"), (7,"Plong")]
singleConvert :: (Int, String) -> Int -> Maybe String
singleConvert (d,s) n
| mod n d == 0 = Just s
| otherwise = Nothing
```

Haskell has this useful type `Maybe String`

where the value is either
a string wrapped in `Just`

or the value is `Nothing`

.
So `singleConvert`

takes a pair of `(d,s)`

and another value `n`

and outputs `Nothing`

if `n`

is not evenly divisible by `d`

,
and `Just s`

if it is.
This will be useful later.
Bear with me.

So we have defined this function `singleConvert`

that takes `(d,s)`

and `n`

as its two parameters.
But we’re actually going to be using this for creating functions that
take an `Int`

as input and output a `Maybe String`

.
So we are going to partially apply `singleConvert`

to get those functions.
This is a neat, if initially mind-bending, feature of haskell.
If you have a function `f :: Int -> Int -> Int`

we read that as `f`

takes two arguments (both `Int`

s) and outputs an `Int`

.
But we could instead read this as `f`

takes one argument, an `Int`

and outputs
a function from `Int`

s to `Int`

s.
Both of these things are true!
(If anything, the latter is more true).
So that’s what we do.
We `map`

`singleConvert`

over a list of pairs `(d,s)`

to produce a list of functions called `plingFunctions`

.
The type of the functions in this list is `Int -> Maybe String`

.
Now we use another related kind of mind-bending haskell-ism:
`map ($ n) plingFunctions`

applies each function in `plingFunctions`

to input `n`

.
`f $ n`

in haskell means apply function `f`

to argument `n`

,
and is basically the same as `f n`

.
But, using `$`

means we can use `$ n`

as a *function*,
the function that applies `n`

to its input (which has to be a function that takes `n`

’s type as its input’).

An intermediate step in the javascript approach was a list that looked like, say,
`["Pling", "", "Plong"]`

.
This is the output of the `map`

step.
We then join those together, relying on the fact that `""`

is the identity for string concatenation, meaning that `s + "" == s`

.
So any `""`

entries are effectively ignored.
We get to a similar intermediate step in this haskell solution here, where we get something
that looks like: `[Just "Pling", Nothing, Just "Plong"]`

.
That’s what we get from mapping the “apply `n`

to it” function over our list of functions `plingFunctions`

.
Then we need to get only the `Just`

elements, extract them from their `Just`

contexts and concatenate them together.
That’s precisely what `catMaybes`

does; we go from a list of `Maybe String`

s to
a list of the contents of all the `Just`

elements.
Our above example becomes `["Pling", "Plong"]`

.
And we’re nearly done.
If the list is empty – `null plingList`

– then just output the number – `show n`

turns an integer to a string –
otherwise smoosh the members of the list together – that’s what `concat`

does – and return that.
The neat thing about this is that if we added `(11, "")`

to the inputs,
it would work as expected.
Because this haskell solution can distinguish between `Nothing`

and `Just ""`

.