I'm kind new in the Lisp/Functional/Clojure world and I've a JS function:
function buildString(someInteger) {
var question = "Initial text";
if (someInteger == 1) {
question += " put this string ";
} else if(someInteger == 2) {
question += " oh! another string ";
} else if(someInteger == 3) {
question += " guess what? ";
}
return question;
}
What could be a good way to rewrite this to a Clojure function? I already have some code using the "cond" Clojure macro, but I'm not sure about the immutable string "question":
(defn build-string [some-integer]
(let [question "Initial text"]
(cond
(= some-integer 1) (str question "Add string one")
(= some-integer 2) (str question "Add string two")
(= some-integer 3) (str question "Add string three"))))
-
Please add the cljs code you have already tried.cfrick– cfrick2018年08月24日 19:27:35 +00:00Commented Aug 24, 2018 at 19:27
3 Answers 3
You want the cond-> macro:
(defn build-string [some-integer]
(let [question "Initial text; "]
(cond-> question
(= some-integer 1) (str "Add string one")
(= some-integer 2) (str "Add string two")
(= some-integer 3) (str "Add string three"))))
(build-string 1) => "Initial text; Add string one"
(build-string 2) => "Initial text; Add string two"
(build-string 3) => "Initial text; Add string three"
although in this case plain old cond will work:
(defn build-string [some-integer]
(let [question "Initial text; "]
(cond
(= some-integer 1) (str question "Add string one")
(= some-integer 2) (str question "Add string two")
(= some-integer 3) (str question "Add string three"))))
@cfrick makes a good point:
(defn build-string-map [some-integer]
(let [question "Initial text; "
data {1 "Add string one"
2 "Add string two"
3 "Add string three"}
suffix (get data some-integer)
result (str question suffix)]
result))
(build-string-map 1) => "Initial text; Add string one"
(build-string-map 2) => "Initial text; Add string two"
(build-string-map 3) => "Initial text; Add string three"
Be sure to look at the
1 Comment
cond-> is useful when you want to conditionally thread clause by clause. The question was for the selection of exactly one clause.Your cond form is fine, but you can use case here:
(defn build-string [some-integer]
(str "Initial text"
(case some-integer
1 "Add string one"
2 "Add string two"
3 "Add string three")))
Your "immutable string question": in contrast to your JavaScript version, none of the operators you or I have been using modify any of their arguments. For example, Clojure's str builds a new string, but JavaScript's += modifies a variable. You need not worry: it is not a mistake to modify things in Clojure that you would need to keep an eye out for, but rather the language makes it difficult to do it in the first place. If you see a simple function using standard operators, it is very improbable for it to be doing something unsafe.
Comments
If you have just some "equal number" checks, i'd just go with a map. E.g.
(str "Initial text" ({1 "Add string one" 2 "Add string two" 3 "Add string three"} some-integer))
Or just go with condp. E.g.
(defn build-string
[some-integer]
(str "Initial text"
(condp = some-integer
1 "Add string one"
2 "Add string two"
3 "Add string three"
nil)))
(map build-string (range 4))
; => ("Initial text" "Initial textAdd string one" "Initial textAdd string two" "Initial textAdd string three")
I think the keypoint here is to eliminate duplication; not only eliminate the "length" but also eliminate the "width" of your code.