I'm doing the exercices from clojureacademy. Here are the instructions for this one.
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
- Returns "Whatever." if given phrase is one of the following inputs:
- "Tom-ay-to, tom-aaaah-to."
- "Let's go make out behind the gym!"
- "It's OK if you don't want to go to the DMV."
- "Ending with ? means a question."
- "1, 2, 3"
Returns "Woah, chill out!" if given phrase is one of the following inputs:
- "WATCH OUT!"
- "WHAT THE HELL WERE YOU THINKING?"
- "ZOMG THE %^@#$(^ ZOMBIES ARE COMING!!11!!1!"
- "1, 2, 3 GO!"
- "I HATE YOU"
Returns "Sure." if given phrase is one of the following inputs:
- "Does this cryogenic chamber make me look fat?"
- "4?"
- Returns "Fine. Be that way!" if given phrase is one of the following inputs:
- ""
- " "
Here is my code in src/ex1_bob/core.clj
:
(ns ex1-bob.core
(:gen-class))
; responses
; =======================
(def whatever "Whatever.")
(def chill-out "Woah, chill out!")
(def sure "Sure.")
(def fine "Fine. Be that way!")
; triggers
; =======================
(def sure-triggers
["Does this cryogenic chamber make me look fat?" "4?"])
(def whatever-triggers
["Tom-ay-to, tom-aaaah-to."
"Let's go make out behind the gym!"
"It's OK if you don't want to go to the DMV."
"Ending with ? means a question."
"1, 2, 3"])
(def chill-out-triggers
["WATCH OUT!"
"WHAT THE HELL WERE YOU THINKING?"
"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"
"1, 2, 3 GO!"
"I HATE YOU"])
(defn has-phrase
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase coll]
(if (some #(= phrase %) coll)
true
false))
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(has-phrase phrase whatever-triggers) whatever
(has-phrase phrase chill-out-triggers) chill-out
(has-phrase phrase sure-triggers) sure
(= (clojure.string/trim phrase) "") fine))
I also wrote some tests in test/ex1_bob/core_test.clj
:
(ns ex1-bob.core-test
(:require [clojure.test :refer :all]
[ex1-bob.core :refer :all]))
; This does not work because `is` is a macro, and it seems it does not like to
; be used in a `map` or with `comp`.
;
; (deftest non-working-response-for-chill-out-triggers
; (doall (map (comp is #(= % chill-out) response-for) chill-out-triggers)))
(deftest response-for-chill-out-triggers
(is (every? #(= % chill-out) (map response-for chill-out-triggers))))
(deftest response-for-whatever-triggers
(is (every? #(= % whatever) (map response-for whatever-triggers))))
(deftest response-for-sure-triggers
(is (every? #(= % sure) (map response-for sure-triggers))))
(deftest response-for-empty-string
(is (every? #(= % fine) (map response-for [""]))))
Two things make me a bit unhappy about this code:
- the
has-phrase
function seems a bit silly. Do I really have to write a function to returntrue
/false
if an element is found in a collection? I feel that there must be a function that does this already I first wrote my unit test with:
(deftest non-working-response-for-chill-out-triggers (doall (map (comp is #(= % chill-out) response-for) chill-out-triggers)))
The idea is to have one assertion for each item, which I assumed would give me a better error message in case of a failure (because I know which item failed). But it seems that
is
is a macro and somehow, the interpreter doesn't like this.