1) (def x (for [i (range 1 3)] (do (println i) i)))
2) (def x (for [i (range 1 3)] (do i)))
Both pro开发者_运维技巧duces same output, then what is the use of println?
Values evaluate to themselves, and a do block returns the result of the last expression. That is why (do 2) returns 2, in the example below. Because it returns 2, when evalled from a REPL, 2 will be printed to the screen as the result. The function println however causes a side effect, but returns nil. The side effect below is that the value 2 will be printed to standard output. Also nil is printed, because that is the return value from the function println.
user=> (do 2)
2
user=> (println 2)
2
nil
In your example the outputs are not the same, because of what I explained above. Notice the difference yourself:
user=> (def x (for [i (range 1 3)] (do (println i) i)))
#'user/x
user=> x
(1
2
1 2)
user=> (def x (for [i (range 1 3)] (do i)))
#'user/x
user=> x
(1 2)
Also take note that for is lazy:
(def x (for [i (range 1 3)] (do (println i) i)))
#'user/x
user=> x
(1
2
1 2)
user=> x
(1 2)
The second time x is requested, only (1 2) is printed. Why? Because for is lazy. It only produces its elements the first time they are requested (the first time x is requested). A next time, the elements are already produced, so the side effect within do will not happen again.
In a REPL they may produce (roughly) the same output, but they won't if run from a compiled program. The P in REPL stands for Print - it prints the value of the current expression.
Try compiling into a Jar and running it to see the difference. Also never forget that using println means your function has side-effects; you may find you need to force evaluation of the function (e.g. in a do) in order to produce output.
精彩评论