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"))))
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
Clojure CheetSheet
ClojureScript CheetSheet
clojure.org
clojurescript.org
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.
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.
Related
How do you print a formatted string with quotation marks, and without the backward slashes?
For example, when I enter
(format "say ~a" "hello there!")
I want to get
" say "hello there!" "
I want the quotation marks wrapped around "hello there" as the way I typed in. However, if I format it as a string, it turns out like this:
"say \"hello there!\""
Is there a way to keep the quotation marks without having the backward slash?
evaluating strings, and print/println print the quote " as\".
Maybe you're looking for display/displayln:
(displayln (format "say \"~a\"" "hello there!"))
; => say "hello there!"
use ~s instead of ~a
> (format "say ~s" "hello there!")`
"say \"hello there!\""
I have a part of text and I need to get value with regexp
Text sample
> " class="hidden" data-productname="Heltidsulykke udvidet
> 5%"></div></div>
I write regexp that match word Heltidsulykke.
/data-productname\=\"(.*\p{L}+)sulykke+\s+\p{L}+\p{L}+\s.*\"\>/
It is a first step. key that I need to get can bee Heltidsulykke or Fritidsulykke or Børneulykke and ind in case
Heltidsulykke (-> Value should be "One")
Fritidsulykke (-> value should be "Two")
Børneulykke (-> value should be "Three")
So, the result shoud be "One", "Two" or "Three".
Here is the error summary:
CLIPS> (load "C:/Users/labor/Desktop/Witek/projekt.CLP")
Defining defrule: R1 +j+j
Defining defrule: R2 +j+j
Defining defrule: R3 =j+j+j
Defining defrule: imie-if =j=j+j+j
[CSTRCPSR1] Expected the beginning of a construct.
And here is the code for my CLIPS program. Basically I want it to react different if the name and last name are different from Abraham Lincoln.
(defrule R1
(initial-fact)
=>
(printout t "Enter your name:" crlf)
(bind ?name (read))
(assert (name ?name)))
(defrule R2
(name ?name)
=>
(printout t "Enter your last name" crlf)
(bind ?lastnm (read))
(assert (lastnm ?lastnm)))
(defrule R3
(and(name ?name)(lastnm ?lastnm))
=>
(printout t "How old are you " ?name "?" crlf)
(bind ?age (read))
(assert (age ?age)))
(defrule name-if
(name ?name)(lastnm ?lastnm)(age ?age)
=>
(if(and(eq ?name Abraham)(eq ?lastnm Lincoln))
then (printout t "Hello " ?name " " ?lastnm ", you are " ?age " years old bro" crlf))
else (printout t "Hello " ?name " " ?lastnm ", you are " ?age " years old" crlf)))
I copied the if statement logic from some webpage and I am not quite sure what, in this case, 'eq' stands for... i'd appreciate if you could additionally explain the role of it.
Regards,
W
You have an extra right parenthesis at the end of the then clause that is causing the issue. The Mac OS and Window CLIPS IDEs have a balance command that you can use to see if the parentheses are properly balanced within a construct. Just click inside a construct and apply the balance command several times until the entire construct is selected. If you place the cursor by the then keyword and balance, you'll see that the if statement is closed by the parenthesis at the end of the then clause and the else clause is left dangling.
The corrected rule is:
(defrule name-if
(name ?name)
(lastnm ?lastnm)
(age ?age)
=>
(if (and (eq ?name Abraham)
(eq ?lastnm Lincoln))
then
(printout t "Hello" ?name " " ?lastnm ", you are " ?age " years old bro" crlf)
else
(printout t "Hello " ?name " " ?lastnm ", you are " ?age " years old" crlf)))
The eq predicate is short for equals. Unlike the = predicate that expects numeric arguments, eq compares values of any type.
How do I convert a list of strings into a string in DrRacket? For example, if I have
'("44" "444") convert it into "44 444"?
I tried string-join, but it takes a delimiter and if I put one it replaces the space with the delimiter and if I use "" for the delimiter it simply gets rid of it.
In fact string-join is the right procedure for using in this case, simply use " " (a single space) as delimiter:
(string-join '("44" "444") " ")
=> "44 444"
Just to clarify: in a list the spaces between elements are not considered part of the list, they're there to separate the elements. For example, all these lists are equal and evaluate to the same value:
'("44""444")
'("44" "444")
'("44" "444")
If for some reason you want to consider the spaces as part of the list then you have to explicitly add them as elements in the list:
(define lst '("a" " " "b" " " "c" " " "d"))
(string-join lst "")
=> "a b c d"
I was reading Volkmann's Clojure tutorial, in that tutorial it says the function print-str prints the content to a string that is returned. So does this mean that:
(print-str a b c ... ) == (str a " " b " " c " " ... )
I tried with my REPL and it behaved like I assumed above, but I just want to know if it really is, or I am missing something here...
The function print-str will return a string similar to what REPL would report if asked to evaluate the argument, e.g. for human consumption. The function str invokes the .toString of the object. In the case of a string argument, the result is the same as you point out.
This is not in general true for other objects
((juxt print-str str) 1N)
;=> ["1N" "1"]
((juxt print-str str) (java.util.Date.))
;=> ["#inst \"2013-07-19T01:47:00.784-00:00\"" "Thu Jul 18 20:47:00 CDT 2013"]