(ns language.vocabulary.idioms (:require [clojure.test :refer [deftest is are run-tests]]))
all of that and we still can't say anything useful...
let's build something very simple together and see how that works out:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9.
The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
using clojure's bare building blocks:
(defn euler1-loop-recur [m]
(loop [n 0 ;; our looping index
sum 0] ;; our accumulator
(let [over? (>= n m) ;; our halt condition
div-by-3? (= 0 (mod n 3))
div-by-5? (= 0 (mod n 5))]
(if over? sum
(recur (inc n) ;; our recursive tail call!
(if (or div-by-3? div-by-5?)
(+ sum n)
sum))))))
yes that is a cool recursive way to do it, but is not pleasant at all...
you could try to be less of a micro-manager
and some more familiar
constructs with something like:
(defn euler1-for-macro [m]
(apply +
;; sum everything in the collection that comes next
(for [n (range 1 m)
;; this works as a python-style generator
:when (or (= 0 (mod n 3))
(= 0 (mod n 5)))]
;; just yield a list of these n's that pass the `when` test
n)))
that still screams of foreign accent...
not that there's anything wrong with it,
but if you want to talk like the natives,
you could try something like:
(defn euler1-threading-sequences [m]
;; a pipeline!
(->> m
;; an input collection, just data
(range 1)
;; composable filter, it is just a function
(filter #(or (= 0 (mod % 3))
(= 0 (mod % 5))))
;; a reduction, which internally uses a loop-recur
(reduce +)))
we could even go deeper into a cool feature called transducers, but that is a bit beyond what you need to get by on your first trip
but how can we be sure something works? testing of course!
(deftest euler-problem-1 (is (= 23 (euler1-loop-recur 10))) (is (= 23 (euler1-for-macro 10))) (is (= 23 (euler1-threading-sequences 10))))
or you can generic assertions
(deftest euler-problem-1-but-cooler
(are [solve] (= 23 (solve 10))
euler1-loop-recur
euler1-for-macro
euler1-threading-sequences))
and you can run them programatically with:
(run-tests)
there is still more to learn, so on to an exercise!
(assuming you already have the whole setup work-book)