What does the Bob say? (clojure version)












1












$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 return true/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.












share|improve this question









$endgroup$

















    1












    $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 return true/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.












    share|improve this question









    $endgroup$















      1












      1








      1





      $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 return true/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.












      share|improve this question









      $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 return true/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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 2 hours ago









      little-dudelittle-dude

      21315




      21315






















          1 Answer
          1






          active

          oldest

          votes


















          0












          $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 to has-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.






          share|improve this answer











          $endgroup$













            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            0












            $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 to has-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.






            share|improve this answer











            $endgroup$


















              0












              $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 to has-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.






              share|improve this answer











              $endgroup$
















                0












                0








                0





                $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 to has-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.






                share|improve this answer











                $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 to has-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.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 32 mins ago

























                answered 46 mins ago









                CarcigenicateCarcigenicate

                3,52911631




                3,52911631






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                    is 'sed' thread safe

                    How to make a Squid Proxy server?