Welcome! Please see the About page for a little more info on how this works.

0 votes
in Syntax and reader by

I open a file, type in (map prn (range 2)) then save the file and execute clojure file.clj.
This produces no output.
I then execute clojure and type in (map prn (range 2)).
This produces output.

Is there some kind of "feature" of clojure that discards code within for and map if the result is not used when you run it on a file?
If that is the case, presumably it should give an error or at least a warning that there is dead code that it is discarding.

2 Answers

+2 votes
selected by
Best answer

According to the docs (https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/map), map returns a lazy sequence, which means the work is not done (in particular the prn's do not happen) until the sequence is consumed. As Eugene Pakhomov points out in another answer, the REPL consumes the sequence, but the forms in the file by themselves did not.

Because map returns a lazy sequence, one does not usually rely on map for side effects like printing. doseq is good for executing side effects. Besides the question of timing, you usually need either the data (sequence) or the side effects, so it is convenient that doseq does not amass a sequence.

It still seems like a mature programming environment would exhibit more obvious behaviour. Like force evaluate all unevaluated code before exit. Or have a warning if the code you run will not actually do anything.

Nevertheless, doseq is what I was looking for in my particular case. My original workaround was to just use loop and recur since for and map were not producing side effects. But doseq is closer to the syntax I wanted.
+1 vote

I'll give you one better - if you just type 1 or any other literal in that file, executing it by itself won't produce any result.

The P in REPL stands for "print" - it prints all the results for you. Executing a file does not print anything by itself, unless you use some printing function.