The following expression in clojure works great:
(doseq [x '(1 2 3 4)] (println x))
This one gives me a nullpointer:
(doseq [x '(1 2 3 4)] ((println x)(println "x")))
It produces the following output:
user=> (doseq [x '(1 2 3 4)] ((println x)(println "x")))
1
x
java.lang.NullPointerException (NO_SOURCE_FILE:0)
user=> (.printStackTrace *e)
java.lang.NullPointerException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:4639)
at clojure.core$eval__5182.invoke(core.clj:1966)
at clojure.main$repl__7283$read_eval_print__7295.invoke(main.clj:180)
at clojure.main$repl__7283.doInvoke(main.clj:197)
at clojure.lang.RestFn.invoke(RestFn.java:426)
at clojure.main$repl_opt__7329.invoke(main.clj:251)
at clojure.main$legacy_repl__7354.invoke(main.clj:292)
at clojure.lang.Var.invoke(Var.java:359)
at clojure.main.legacy_repl(main.java:27)
at clojure.lang.Repl.main(Repl.java:20)
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 jline.ConsoleRunner.main(ConsoleRunner.java:69)
Caused by: java.lang.NullPointerException
at user$eval__266.invoke(NO_SOURCE_FILE:26)
at clojure.lang.Compiler.eval(Compiler.java:4623)
... 14 more
nil
Just adding an extra set of parentheses around the body of a doseq gives me that nullpointer. What am I doing wrong?
Well, you already figured out the solution, so just a few hints to explain the behavior:
In Clojure (just like in Lisp, Scheme, etc) everything is an expression and an expression is either an atom or a list. With regard to lists, the Clojure manual says
Non-empty Lists are considered calls to either special forms, macros, or functions. A call has the form (operator operands*).
In your example, the body ((println x) (println x))
is a list and the operator is itself an expression which Clojure has to evaluate to obtain the actual operator. That is, you're saying "evaluate the first expression and take its return value as a function to invoke upon the second expression". However, println
returns, as you noticed, only nil
. This leads to the NullPointerException
if nil
is interpreted as an operator.
Your code works with (do (println x) (println x))
because do
is a special form which evaluates each expression in turn and returns the value of the last expression. Here do
is the operator and the expressions with println
ar the operands.
To understand the usefulness of this behavior, note that functions are first-class objects in Clojure, e.g., you could return a function as a result from another function. For instance, take the following code:
(doseq [x '(1 2 3 4)] ((if (x > 2)
(fn [x] (println (+ x 2)))
(fn [x] (println (* x 3)))) x))
Here, I am dynamically figuring out the operator to invoke upon the element in the sequence. First, the if
-expression is evaluated. If x
is larger than two, the if
evalutes to the function that prints x + 2
, else it evaluates to the function that prints x * 3
. This function is than applied to the x
of the sequence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With