What does the Bob say? (clojure version)
$begingroup$
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.
beginner clojure
$endgroup$
add a comment |
$begingroup$
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.
beginner clojure
$endgroup$
add a comment |
$begingroup$
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.
beginner clojure
$endgroup$
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.
beginner clojure
beginner clojure
asked 2 hours ago
little-dudelittle-dude
21315
21315
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
First, working top-down, your triggers at the top should be in sets (#{}
), not vectors (you'll see why a little farther down):
(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"})
has-phrase
has a couple things that can be improved:
Clojure ends predicates with a
?
by convention. I'd rename it tohas-phrase?
.some
already returns a truthy/falsey value.(if pred? true false)
is unnecessary.
Just reduce it to:
(defn has-phrase?
"Return whether or not the given phrase is found in the collection"
[phrase coll]
(some #(= phrase %) coll))
BUT, now that you're using sets instead of vectors, this whole function is unnecessary:
(whatever-triggers "1, 2, 3")
=> "1, 2, 3" ; Truthy
(whatever-triggers "Not in the set")
=> nil
Sets themselves can be used as functions. If the item is in the set, they return the item back (a truthy result), else they return nil
(falsey). This will also be much faster, since now you don't need to have some
iterate potentially the entire vector (although obviously speed isn't a factor here). This changes reponse-for
to:
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(whatever-triggers phrase) whatever
(chill-out-triggers phrase ) chill-out
(sure-triggers phrase) sure
(= (clojure.string/trim phrase) "") fine))
This could be changed using some some
trickery. some
returns the first truthy value returned by its predicate. If you pass it pairs of [trigger-set response]
, you can iterate over the the pairs to find the first one that satisfies it, then return the response:
(defn response-for2 [phrase]
(some (fn [[trigger-set response]]
(when (trigger-set phrase)
response))
[[sure-triggers sure]
[chill-out-triggers chill-out]
[whatever-triggers whatever]
[#{"" " "} fine]]))
Now, in this particular example, I wouldn't recommend doing this. It's not as clear as what you already had. I have used (some #(when ...))
before though, and it works great in some cases. I just thought I'd show you it here in case you run into a similar problem where this can be applied.
I'm sure something could be done using a map mapping triggers to responses, but I just did another Clojure review, and my brain's tapped out.
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214734%2fwhat-does-the-bob-say-clojure-version%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
First, working top-down, your triggers at the top should be in sets (#{}
), not vectors (you'll see why a little farther down):
(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"})
has-phrase
has a couple things that can be improved:
Clojure ends predicates with a
?
by convention. I'd rename it tohas-phrase?
.some
already returns a truthy/falsey value.(if pred? true false)
is unnecessary.
Just reduce it to:
(defn has-phrase?
"Return whether or not the given phrase is found in the collection"
[phrase coll]
(some #(= phrase %) coll))
BUT, now that you're using sets instead of vectors, this whole function is unnecessary:
(whatever-triggers "1, 2, 3")
=> "1, 2, 3" ; Truthy
(whatever-triggers "Not in the set")
=> nil
Sets themselves can be used as functions. If the item is in the set, they return the item back (a truthy result), else they return nil
(falsey). This will also be much faster, since now you don't need to have some
iterate potentially the entire vector (although obviously speed isn't a factor here). This changes reponse-for
to:
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(whatever-triggers phrase) whatever
(chill-out-triggers phrase ) chill-out
(sure-triggers phrase) sure
(= (clojure.string/trim phrase) "") fine))
This could be changed using some some
trickery. some
returns the first truthy value returned by its predicate. If you pass it pairs of [trigger-set response]
, you can iterate over the the pairs to find the first one that satisfies it, then return the response:
(defn response-for2 [phrase]
(some (fn [[trigger-set response]]
(when (trigger-set phrase)
response))
[[sure-triggers sure]
[chill-out-triggers chill-out]
[whatever-triggers whatever]
[#{"" " "} fine]]))
Now, in this particular example, I wouldn't recommend doing this. It's not as clear as what you already had. I have used (some #(when ...))
before though, and it works great in some cases. I just thought I'd show you it here in case you run into a similar problem where this can be applied.
I'm sure something could be done using a map mapping triggers to responses, but I just did another Clojure review, and my brain's tapped out.
$endgroup$
add a comment |
$begingroup$
First, working top-down, your triggers at the top should be in sets (#{}
), not vectors (you'll see why a little farther down):
(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"})
has-phrase
has a couple things that can be improved:
Clojure ends predicates with a
?
by convention. I'd rename it tohas-phrase?
.some
already returns a truthy/falsey value.(if pred? true false)
is unnecessary.
Just reduce it to:
(defn has-phrase?
"Return whether or not the given phrase is found in the collection"
[phrase coll]
(some #(= phrase %) coll))
BUT, now that you're using sets instead of vectors, this whole function is unnecessary:
(whatever-triggers "1, 2, 3")
=> "1, 2, 3" ; Truthy
(whatever-triggers "Not in the set")
=> nil
Sets themselves can be used as functions. If the item is in the set, they return the item back (a truthy result), else they return nil
(falsey). This will also be much faster, since now you don't need to have some
iterate potentially the entire vector (although obviously speed isn't a factor here). This changes reponse-for
to:
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(whatever-triggers phrase) whatever
(chill-out-triggers phrase ) chill-out
(sure-triggers phrase) sure
(= (clojure.string/trim phrase) "") fine))
This could be changed using some some
trickery. some
returns the first truthy value returned by its predicate. If you pass it pairs of [trigger-set response]
, you can iterate over the the pairs to find the first one that satisfies it, then return the response:
(defn response-for2 [phrase]
(some (fn [[trigger-set response]]
(when (trigger-set phrase)
response))
[[sure-triggers sure]
[chill-out-triggers chill-out]
[whatever-triggers whatever]
[#{"" " "} fine]]))
Now, in this particular example, I wouldn't recommend doing this. It's not as clear as what you already had. I have used (some #(when ...))
before though, and it works great in some cases. I just thought I'd show you it here in case you run into a similar problem where this can be applied.
I'm sure something could be done using a map mapping triggers to responses, but I just did another Clojure review, and my brain's tapped out.
$endgroup$
add a comment |
$begingroup$
First, working top-down, your triggers at the top should be in sets (#{}
), not vectors (you'll see why a little farther down):
(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"})
has-phrase
has a couple things that can be improved:
Clojure ends predicates with a
?
by convention. I'd rename it tohas-phrase?
.some
already returns a truthy/falsey value.(if pred? true false)
is unnecessary.
Just reduce it to:
(defn has-phrase?
"Return whether or not the given phrase is found in the collection"
[phrase coll]
(some #(= phrase %) coll))
BUT, now that you're using sets instead of vectors, this whole function is unnecessary:
(whatever-triggers "1, 2, 3")
=> "1, 2, 3" ; Truthy
(whatever-triggers "Not in the set")
=> nil
Sets themselves can be used as functions. If the item is in the set, they return the item back (a truthy result), else they return nil
(falsey). This will also be much faster, since now you don't need to have some
iterate potentially the entire vector (although obviously speed isn't a factor here). This changes reponse-for
to:
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(whatever-triggers phrase) whatever
(chill-out-triggers phrase ) chill-out
(sure-triggers phrase) sure
(= (clojure.string/trim phrase) "") fine))
This could be changed using some some
trickery. some
returns the first truthy value returned by its predicate. If you pass it pairs of [trigger-set response]
, you can iterate over the the pairs to find the first one that satisfies it, then return the response:
(defn response-for2 [phrase]
(some (fn [[trigger-set response]]
(when (trigger-set phrase)
response))
[[sure-triggers sure]
[chill-out-triggers chill-out]
[whatever-triggers whatever]
[#{"" " "} fine]]))
Now, in this particular example, I wouldn't recommend doing this. It's not as clear as what you already had. I have used (some #(when ...))
before though, and it works great in some cases. I just thought I'd show you it here in case you run into a similar problem where this can be applied.
I'm sure something could be done using a map mapping triggers to responses, but I just did another Clojure review, and my brain's tapped out.
$endgroup$
First, working top-down, your triggers at the top should be in sets (#{}
), not vectors (you'll see why a little farther down):
(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"})
has-phrase
has a couple things that can be improved:
Clojure ends predicates with a
?
by convention. I'd rename it tohas-phrase?
.some
already returns a truthy/falsey value.(if pred? true false)
is unnecessary.
Just reduce it to:
(defn has-phrase?
"Return whether or not the given phrase is found in the collection"
[phrase coll]
(some #(= phrase %) coll))
BUT, now that you're using sets instead of vectors, this whole function is unnecessary:
(whatever-triggers "1, 2, 3")
=> "1, 2, 3" ; Truthy
(whatever-triggers "Not in the set")
=> nil
Sets themselves can be used as functions. If the item is in the set, they return the item back (a truthy result), else they return nil
(falsey). This will also be much faster, since now you don't need to have some
iterate potentially the entire vector (although obviously speed isn't a factor here). This changes reponse-for
to:
(defn response-for
"return `true` if the given phrase is found in the collection, `false` otherwise"
[phrase]
(cond
(whatever-triggers phrase) whatever
(chill-out-triggers phrase ) chill-out
(sure-triggers phrase) sure
(= (clojure.string/trim phrase) "") fine))
This could be changed using some some
trickery. some
returns the first truthy value returned by its predicate. If you pass it pairs of [trigger-set response]
, you can iterate over the the pairs to find the first one that satisfies it, then return the response:
(defn response-for2 [phrase]
(some (fn [[trigger-set response]]
(when (trigger-set phrase)
response))
[[sure-triggers sure]
[chill-out-triggers chill-out]
[whatever-triggers whatever]
[#{"" " "} fine]]))
Now, in this particular example, I wouldn't recommend doing this. It's not as clear as what you already had. I have used (some #(when ...))
before though, and it works great in some cases. I just thought I'd show you it here in case you run into a similar problem where this can be applied.
I'm sure something could be done using a map mapping triggers to responses, but I just did another Clojure review, and my brain's tapped out.
edited 32 mins ago
answered 46 mins ago
CarcigenicateCarcigenicate
3,52911631
3,52911631
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214734%2fwhat-does-the-bob-say-clojure-version%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown