Looping over vectors - vector

I am new to Clojure and have found that when I loop over this vector in clojure using a list comprehension I get some nils at the end.
(def myVec [1,2,3])
user=> (for [x myVec] (println x))
(1
2
3
nil nil nil)
I get the same thing using map
user=> (map println myVec)
(1
2
3
nil nil nil)
What causes the nill to be printed in these cases?

for and map create a new lazy sequence with every element in the original vector replaced by the result of (println element), and println returns nil.
You should not be using for and map to perform side-effects (like printing) on the elements. Use doseq for that.

Those nil are the return value of println. Every time you call
(println "something")
the println function prints something on the standard output, and then returns nil. The overall effect in your code is that you see all the side effects (I/O) of all println invocations, then the REPL prints the return value coming from each and every invocation (e.g. three times nil).

nil is the value returned by println so you are seeing the printed lines followed by the mapped list of nil values.

Related

read's recursive-p argument when used inside a reader macro

I have written a Common Lisp implementation of Scheme's s-expression comments (SRFI 62):
(eval-when (:compile-toplevel
:load-toplevel
:execute)
(set-dispatch-macro-character #\# #\;
(lambda (stream char n)
(declare (ignore char))
(when n
(error "Infix parameter not allowed in s-expression comment."))
(read stream) ; Discard the s-expression.
(values))))
Based on my reading of The RECURSIVE-P argument, it appears that my implementation is incorrect. I have to use (read stream t nil t) instead (i.e. set the recursive-p argument to t). Is my understanding correct?
I have been using the apparently incorrect implementation above, and it seems to function correctly. What would happen if I continue to use (read stream) instead of (read stream t nil t)?
For an example of incorrect behavior, let's consider the first of the three reasons given in the RECURSIVE-P argument documentation. First, using your original definition:
* (+ 1 #1=2 #;(+ #1# 3))
Reader error: Missing #1# label.
Changing (read stream) into (read string t nil t) gives the correct result:
* (+ 1 #1=2 #;(+ #1# 3))
3

Recursive Loop in Clojure via Macro is throwing me errors

I've been trying to write a recursive loop in clojure that will print me out the very last number in the list. The point is not that I need to get the last number (for which I'm sure there's a built in function for that) but that I want to better understand recursion and macros in clojure. So I have this macro...
(defmacro loop-do [the-list]
`(if (= (count '~the-list) 1)
(println (first '~the-list))
(loop-do (rest '~the-list))))
But I get a stackoverflow error. What am I doing wrong?
How will people use your macro?
Somewhere, someone will call:
(loop-do list)
As a piece of code, those are only two symbols in a list. The first one is recognized as your macro, and the second one, list, is a symbol that represents a variable that will be bound at runtime. But your macro only knows that this is a symbol.
The same goes for:
(loop-do (compute-something))
The argument is a form, but you do not want to get the last element of that form, only the last element of the list obtained after evaluating the code.
So: you only know that in your macro, the-list will be bound to an expression that, at runtime, will have to be a list. You cannot use the-list as-if it was a list itself: neither (count 'list) nor (count '(compute-something)) does what you want.
You could expand into (count list) or (count (compute-something)), though, but the result would only be computed at runtime. The job of the macro is only to produce code.
Recursive macros
Macros are not recursive: they expand into recursive calls.
(and a b c)
might expand as:
(let [a0 a] (if a0 a0 (and b c)))
The macroexpansion process is a fixpoint that should terminate, but the macro does not call itself (what would that mean, would you expand the code while defining the macro?). A macro that is "recursive" as-in "expands into recursive invocations" should have a base case where it does not expand into itself (independently of what will, or will not, happen at runtime).
(loop-do x)
... will be replaced by:
(loop-do (rest 'x))
... and that will be expanded again.
That's why the comments say the size actually grows, and that's why you have a stackoverflow error: macroexpansion never finds a fixpoint.
Debugging macros
You have a stackoverflow error. How do you debug that?
Use macroexpand-1, which only performs one pass of macroexpansion:
(macroexpand-1 '(loop-do x))
=> (if (clojure.core/= (clojure.core/count (quote x)) 1)
(clojure.core/println (clojure.core/first (quote x)))
(user/loop-do (clojure.core/rest (quote x))))
You can see that the generated code still contains a call to usr/loop-do , but that the argument is (clojure.core/rest (quote x)). That's the symptom you should be looking for.

How do I map over a list of async channels in the order they exist in a list?

I'm having trouble returning the values from core.async channels in the browser in the order they were created (as opposed to the order at which they return a value). The channels themselves are returned from mapping cljs-http.client/get over a list of URLs.
If I bind the results manually in a let block then I can return the results in the order of the channels "by hand", but this obviously a problem when I don't know how many channels exist.
(let [response-channels (map #(http/get "http://date.jsontest.com" {:with-credentials? false}) (range 3))]
; Response is now three channels generated by http/get:
;(#object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel])
; If I want the results back in the guaranteed order that I made them, I can do this:
(go (let [response1 (<! (nth response-channels 0))
response2 (<! (nth response-channels 1))
response3 (<! (nth response-channels 2))]
(println "This works as expected:" response1 response2 response3))))
But if I try to map <! over the channels instead of binding to them individually then I just get a the list of channels instead of their values.
(let [response-channels (map #(http/get "http://date.jsontest.com" {:with-credentials? false}) (range 3))]
(let [responses (into [] (map (fn [c] (go (<! c))) response-channels))]
(println "This just returns the channels:" responses)
; This is still just a vec of many-to-many channels
; [#object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]]
)
)
I suspect it's a problem with the location of the go block, however I can't move it outside of the anonymous function without an error that I'm using <! outside of a go block.
This doesn't work:
(into [] (go (map <! response-channels)))
And neither does this:
(go (let [responses (into [] (map <! response-channels))]))
I also tried merging the channels via async/merge and then using async/reduce to conjoin the values but results are in the order of when the requests were fulfilled, not the order of the channels being merged.
Can anyone shed some light on retrieving values from a list of channels in the order the channels exist in the list?
In Clojure you could do (map <!! response-channels), but that's not possible in ClojureScript. What's even more important is that it's discouraged to use map—or lazy operations in general—for side effects (checkout this blog post to see why). The reason your code doesn't yield the results you're expecting is the (nested) use of fn within the go block (see this answer):
By [the Clojure go-block] stops translation at function boundaries, I mean this: the go block takes its body and translates it into a state-machine. Each call to <! >! or alts! (and a few others) are considered state machine transitions where the execution of the block can pause. At each of those points the machine is turned into a callback and attached to the channel. When this macro reaches a fn form it stops translating. So you can only make calls to <! from inside a go block, not inside a function inside a code block.
I'm not quite sure, but when you have a look at (source map) you'll see that it invokes fn directely as well as via other functions (such as lazy-seq), which is probably why (go (map <! response-channels)) doesn't work.
Anyway, how about doseq:
(go (doseq [c response-channels]
(println (<! c))))
This will respect the order within response-channels.

common lisp: read list into list

It might seem simple, but I can't get it to work. I simply need to read a file where the contents are just one big list
(a b c d)
. . . as is . . . into a list in my program. I have
(let ((ardplst nil))
...
(with-open-file (in ardpfile :direction :input :if-does-not-exist nil)
(when in
(read-sequence ardplst in))
(format t "~a" ardplst))
But it's not working. I get NIL. What am I doing wrong?
What does read-sequence do? It reads some elements from the stream, typically characters (but it depends on the element-type of the stream) and destructively insert them into the input sequence. So, you would collect characters #\(, then #\a, then #\Space, then #\b, etc. However, reading stops as soon as you reach the end of your sequence: with your empty list, that means immediately (you are supposed to pass a buffer, e.g. a vector). In you case, read-sequence returns 0.
The reason you get nil is because your last expression is format, which in the above code outputs to the standard output (because of t) and returns nil. You could have used print, which returns the printed object.
I don't understand why you are explicitely using :if-does-not-exist nil. Are you sure you want to silently skip the task if the file cannot be opened? What if the list you read is empty? You should probably let an error be signaled in case the file is not found.
I would use read while disabling read-time evaluation:
(with-open-file (in my-file)
(let* ((*read-eval* nil)
(list (read in)))
(prog1 list
(check-type list list))))
Note that the default :direction is :input. In my opinion it does not hurt to omit this argument here, though sometimes it can be more readable to write it explicitely.

Why does (keys "") return nil in Clojure, whereas (keys "abc") is an error?

I'm new to Clojure. The behaviour of keys strikes me as inconsistent:
user=> (keys "")
nil
user=> (keys "abc")
ClassCastException
Empty collections appear to be treated specially, and the test cases indicate that this is intentional. What's the thinking behind this behaviour?
The reason for this is that when a collection is converted to a sequence using seq function, in case the collection is empty seq will return nil rather than an empty sequence. There is another thread which discuss the reason for that.

Resources