tags:

views:

234

answers:

2

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?

+4  A: 

I see you've already realised the problem, however please note you don't need a do:

(doseq [x '(1 2 3 4)] (println x) (println "x"))

doseq is (as the name suggests) a do already :)

Timothy Pratley
+8  A: 

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.

janko