Created
January 4, 2012 02:11
-
-
Save jennifersmith/1558084 to your computer and use it in GitHub Desktop.
Weird non lazy behaviour
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; I thought map was lazy and that first only took the first thing but ... | |
(first (map (fn [x] (print "XXXX" x "XXXX") x) [1 2 3 4])) ;; XXXX 1 XXXXXXXX 2 XXXXXXXX 3 XXXXXXXX 4 XXXX1 | |
;; Unless it is a list | |
(first (map (fn [x] (print "XXXX" x "XXXX") x) '(1 2 3 4)));; XXXX 1 XXXX1 | |
;; deffing it gives no output | |
(def foo (map (fn [x] (print "XXXX" x "XXXX") x) [1 2 3 4])) | |
;; but this does | |
(first foo) ;; XXXX 1 XXXXXXXX 2 XXXXXXXX 3 XXXXXXXX 4 XXXX1 | |
;; this doesn't eval the map result | |
(first (cons "A" (map (fn [x] (print "XXXX" x "XXXX") x) [1 2 3 4]))) ;; "A" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi..well this behaviour is a bit weird..exactly I can't explain you why happen (the problems is related to how clojure is implemented) but the problem is than u are using a side effect function inside a map and that's wrong because first clojure is evaluating the side effect (print) and then evaluate your x...if you wanna try your code must use (swank.core/break) inside your code instead print because this has side effect...if you wanna use side effect functions use doseq...now playing a bit with the repl you can notice a few things:
if you write:
(first (map #(* 10 %) (iterate inc 1)))
your are evaluating the first term in a infinite sequence..
but if you write:
(first (map #((print %) * 10 %) (iterate inc 1)))
you get a overflow..that is because clojure first try print every number until infinite and then take the first number...of course..this never get the first number
now I use a little modification your script
(interleave (map (fn x x) [1 2 3 4]) (repeat "-")) or more readable
(->
(map (fn x x) [1 2 3 4])
(interleave (repeat "-")))
you will get (XXXX 1 XXXXXXXX 2 XXXXXXXX 3 XXXXXXXX 4 XXXX1 "-" 2 "-" 3 "-" 4 "-")
here print every side effect and then print the numbers
notice than XXXX 1 XXXXXXXX 2 XXXXXXXX 3 XXXXXXXX 4 XXXX isn't a term..but the repl mix these with the real sequence because they are evaluate first...weird??
you can notice it if you do in the repl...writing this in 2 steps..first write
(map (fn x x) [1 2 3 4]) and then write
(interleave *1 (repeat "-"))
you will get a perfect (1 "-" 2 "-" 3 "-" 4 "-")
if you've the book pragmatic clojure in the macro part the author gives a explanation why this happen ("....The problem is that Clojure evaluates
all the arguments before passing them to a function, so the println
is called before unless ever sees it. ...")
I hope than it can help u...bye :) ...