I am working through the Armstrong Numbers exercise on Exercism's Clojure track. An armstrong number is a number equal to the sum of its digits raised to the power of the number of digits. 153 is an Armstrong number, because: 153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153. 154 is not an Armstrong number, because: 154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190.
The test file for this exercise will call the armstrong? function, pass in a number, and expects true if the number is an Armstrong number. I have already solved the problem with this code:
(ns armstrong-numbers)
(defn pow [a b]
(reduce * 1 (repeat b a)))
(defn armstrong? [num]
(->> num
(iterate #(quot % 10))
(take-while pos?)
(map #(mod % 10))
((fn [sq]
(map #(pow % (count sq))
sq)))
(apply +)
(= num)))
but now I am trying to refactor the code. This is what I would like the code to look like:
(ns armstrong-numbers
(:require [swiss.arrows :refer :all]))
(defn pow [a b]
(reduce * 1 (repeat b a)))
(defn armstrong? [num]
(-<>> num
(iterate #(quot % 10))
(take-while pos?)
(map #(mod % 10))
(map #(pow % (count <>))
<>)
(apply +)
(= num)))
A link to the package required above: https://github.com/rplevy/swiss-arrows.
In the first code section, I create an implicit function within the thread-last macro because the sequence returned from the map form is needed in two different places in the second map form. That implicit function works just fine, but I just wanted to make the code sleeker. But when I test the second code block, I get the following error: java.lang.RuntimeException: Unable to resolve symbol: <> in this context.
I get this error whether I use #(), partial , or fn inside the second map form. I have figured out that because all of the preceding are macros (or a special form in fns case), they cannot resolve <> because it's only meaningful to the -<>> macro, which is called at a later point in macroexpansion. But why do #(), partial, and fn attempt to resolve that character at all? As far as I can see, they have no reason to know what the symbol is, or what it's purpose is. All they need to do is return that symbol rearranged into the proper s-expressions. So why does clojure attempt to resolve this (<>) symbol?