This is my very first program:
(println "hello, what is your name?")
(let [myname (read-line)]
((println (str "hello " myname))))
It kinda works:
hello, what is your name?
Joel
hello Joel
Exception in thread "main" java.lang.NullPointerException, compiling:(/home/joel/workspace/coolstuff/clojure/hello.clj:1:38)
at clojure.lang.Compiler.load(Compiler.java:7142)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$script_opt.invoke(main.clj:336)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:379)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
at user$eval3.invoke(hello.clj:3)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.load(Compiler.java:7130)
... 9 more
Why does it throw an exception?
((println (str "hello " myname)))
...is running the thing returned by println as a function.
println doesn't return anything. Hence, it returns null. Hence, running its return value as a function throws a NullPointerException.
Take out the extra parenthesis:
(println (str "hello " myname))
Related
(println "The number is: " (read-line))
(read-line) reads coming input from a new line.
How to read from the end of printed string instead of a newline?
Like in C:
printf("The number is: ")
scanf("%d", &value)
If you do the (read-line) inside the print it will be executed first (blocks and waits for the user-input, then the "question" and the user input will be printed).
Instead use do to execute multiple things one after another. To force the output of the print (not println), use flush:
(do
(print "The number is: ")
(flush)
(read-line))
; The number is: 666
; => "666"
do returns with the last result.
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.
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.
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"]
I was trying to break the time string which is in hrs:min format using regex but it fails and gives MatchError.
what is going on here? using Scala 2.10.
scala> val minsecs = """\d+:\d+""".r
minsecs: scala.util.matching.Regex = \d+:\d+
scala> val minsecs(m,s) = "03:45"
scala.MatchError: 03:45 (of class java.lang.String)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:731)
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:980)
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:570)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:601)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:565)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:745)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:790)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:702)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:566)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:573)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:576)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:867)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:889)
at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:73)
at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:64)
at sbt.Console.console0$1(Console.scala:23)
at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)
You need to use two capturing groups in order to extract values:
val minsecs = """(\d+):(\d+)""".r
val minsecs(m,s) = "03:45"
Note the added parenthesis around \d+.