hy build-in with-decorator throws NameError: name 'with_decorator' is not defined - decorator

I'm trying to run the with-deocorator example from hy manual (https://docs.hylang.org/en/stable/language/api.html?highlight=with-decorator#with-decorator):
(defn inc-decorator [func]
(fn [value-1 value-2] (func (+ value-1 1) (+ value-2 1))))
(with-decorator inc-decorator (defn addition [a b] (+ a b)))
(setv foo (addition 1 1))
(print foo)
but I'm getting an exception:
line 4, in <module>
(with-decorator inc-decorator (defn addition [a b] (+ a b)))
NameError: name 'with_decorator' is not defined
with_decorator with underscore. I'm trying with the latest stable version of hy. The same thing happens with any code that has with-decorator.

I found the documentation.
(with-decorator (app.route "/") (defn index [] "Hello World !"))
that worked in earlier versions is now done like this:
(defn [(.route app "/")] index [] "Hello World !")
and
(with-decorator (inc-decorator (defn addition [a b] (+ a b)))
is now
(defn [inc-decorator] addition [a b] (+ a b))

I'm trying with the latest stable version of hy.
with-decorator was recently removed in master, whereas it still existed in 0.20.0, so I think you're mistaken. Check hy --version.

Related

How to step in SBCL like this?

I am new to Common Lisp and I am using SBCL, Slime and Emacs to learn.
While reading the book Common Lisp: A Gentle Introduction to Symbolic Computation, the author mentions the STEP tool which is helpful for debugging and able to do this:
It is not 100% clear if the italic text is coming from the author or the tool itself. Probably, just the author's comments.
However, even if I do not consider the italic, I am unable to generate descriptive info like this.
If I use just SBCL's REPL, I get:
* (step (if (oddp 5) 'yes 'no))
YES
If I use the REPL inside Emacs with Slime on, I get:
CL-USER> (step (if (oddp 5) 'yes 'no))
YES
The author says that:
Each implementation of Common Lisp provides its own version of this
tool; only the name has been standardized.
If I try the same thing in Emacs/Slime with a function, I get more info:
(defun my-abs (x)
(cond ((> x 0) x)
((< x 0) (- x))
(t 0)))
Using the definition above and the command bellow on the REPL:
CL-USER> (step (my-abs 10))
I get:
Evaluating call:
(MY-ABS 10)
With arguments:
10
[Condition of type STEP-FORM-CONDITION]
Restarts:
0: [STEP-CONTINUE] Resume normal execution
1: [STEP-OUT] Resume stepping after returning from this function
2: [STEP-NEXT] Step over call
3: [STEP-INTO] Step into call
4: [RETRY] Retry SLIME REPL evaluation request.
5: [*ABORT] Return to SLIME's top level.
--more--
Backtrace:
0: ((LAMBDA ()))
1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LET ((SB-IMPL::*STEP-OUT* :MAYBE)) (UNWIND-PROTECT (SB-IMPL::WITH-STEPPING-ENABLED #))) #S(SB-KERNEL:LEXENV :FUNS NIL :VARS NIL :BLOCKS NIL :TAGS NIL :TYPE-RESTRICTIONS ..
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (STEP (MY-ABS 10)) #<NULL-LEXENV>)
3: (EVAL (STEP (MY-ABS 10)))
--more--
Unfortunately, none of those options seem to give me what I want (which could be an error of interpretation on my side).
I would like to see something like:
SLIME seems to be a thorough tool. I might be missing something.
Is there a way to generate the same output described by the book using SLIME or SBCL?
As someone suggested above, SBCL does optimize away a lot by default, and compiles by default as well. Here's what I did to create an example:
I first made up "a bad value" for the "suggested optimization" by running
(declaim (optimize (debug 3) (space 0) (speed 0)))
Then, I defined a function with something more than an if condition, since that sort of thing is always inlined, unfortunately (though you might try (declaim (notinline ...)), I haven't. One way is to create a function that calls another one, like:
(defun foo () "hey!")
(defun bar () (foo))
Now, when I run (step (bar)), I see the debugger pane that you shared in your question above, and if I now select option #3, step into, I get the same pane but now focussed, as hopefully expected, on the call to foo.
Good luck!
Some references:
SBCL manual on "Single stepping": http://www.sbcl.org/manual/#Single-Stepping
SBCL manual on "Debugger policy control": http://www.sbcl.org/manual/#Debugger-Policy-Control
It looks like the author is using LispWorks' stepper.
With LispWorks
Here's my step session, using :s to step the current form and all its subforms.
CL-USER 5 > (step (my-abs -5))
(MY-ABS -5) -> :s
-5 -> :s
-5
(COND ((> X 0) X) ((< X 0) (- X)) (T 0)) <=> (IF (> X 0) (PROGN X) (IF (< X 0) (- X) (PROGN 0)))
(IF (> X 0) (PROGN X) (IF (< X 0) (- X) (PROGN 0))) -> :s
(> X 0) -> :s
X -> :s
-5
0 -> :s
0
NIL
(IF (< X 0) (- X) (PROGN 0)) -> :s
(< X 0) -> :s
X -> :s
-5
0 -> :s
0
T
(- X) -> :s
X -> :s
-5
5
5
5
5
5
Help is on :?:
:?
:s Step this form and all of its subforms (optional +ve integer arg)
:st Step this form without stepping its subforms
:si Step this form without stepping its arguments if it is a function call
:su Step up out of this form without stepping its subforms
:sr Return a value to use for this form
:sq Quit from the current stepper level
:bug-form <subject> &key <filename>
Print out a bug report form, optionally to a file.
:get <variable> <command identifier>
Get a previous command (found by its number or a symbol/subform within it) and put it in a variable.
:help Produce this list.
:his &optional <n1> <n2>
List the command history, optionally the last n1 or range n1 to n2.
:redo &optional <command identifier>
Redo a previous command, found by its number or a symbol/subform within it.
:use <new> <old> &optional <command identifier>
Do variant of a previous command, replacing old symbol/subform with new symbol/subform.
For compiled code it also has a visual stepper, where you can press a red button to set a breakpoints, see the intermediate variables changing etc. It looks like this:
LispWorks is a proprietary implementation and IDE that has a free but limited version. I just wrote a review that should be merged on the Cookbook.
trace and printv
Do you know trace? printv, an external library, is a trace on steroids. They resemble the output you appreciate.
(defun factorial (n)
(if (plusp n)
(* n (factorial (1- n)))
1))
(trace factorial)
(factorial 2)
0: (FACTORIAL 3)
1: (FACTORIAL 2)
2: (FACTORIAL 1)
3: (FACTORIAL 0)
3: FACTORIAL returned 1
2: FACTORIAL returned 1
1: FACTORIAL returned 2
0: FACTORIAL returned 6
6
(untrace factorial)
printv prints the code and the returned values.
(printv:printv
(+ 2 3)
*print-case*
*package*
'symbol
(let* ((x 0) (y (1+ x)) (z (1+ y)))
(values x y z)))
;;; (+ 2 3) => 5
;;; *PRINT-CASE* => :UPCASE
;;; *PACKAGE* => #<PACKAGE "ISSR-TEST">
;;; 'SYMBOL => SYMBOL
;;; (LET* ((X 0) (Y (1+ X)) (Z (1+ Y)))
(VALUES X Y Z)) =>
[ [X=0] [Y=1] [Z=2] ]
;;; => 0, 1, 2

clojure - (Another one) StackOverflow with loop/recur

I know this is a recurring question (here, here, and more), and I know that the problem is related to creating lazy sequencies, but I can't see why it fails.
The problem: I had written a (not very nice) quicksort algorithm to sort strings that uses loop/recur. But applied to 10000 elements, I get a StackOverflowError:
(defn qsort [list]
(loop [[current & todo :as all] [list] sorted []]
(cond
(nil? current) sorted
(or (nil? (seq current)) (= (count current) 1)) (recur todo (concat sorted current))
:else (let [[pivot & rest] current
pred #(> (compare pivot %) 0)
lt (filter pred rest)
gte (remove pred rest)
work (list* lt [pivot] gte todo)]
(recur work sorted)))))
I used in this way:
(defn tlfnum [] (str/join (repeatedly 10 #(rand-int 10))))
(defn tlfbook [n] (repeatedly n #(tlfnum)))
(time (count (qsort (tlfbook 10000))))
And this is part of the stack trace:
[clojure.lang.LazySeq seq "LazySeq.java" 49]
[clojure.lang.RT seq "RT.java" 521]
[clojure.core$seq__4357 invokeStatic "core.clj" 137]
[clojure.core$concat$fn__4446 invoke "core.clj" 706]
[clojure.lang.LazySeq sval "LazySeq.java" 40]
[clojure.lang.LazySeq seq "LazySeq.java" 49]
[clojure.lang.RT seq "RT.java" 521]
[clojure.core$seq__4357 invokeStatic "core.clj" 137]]}
As far as I know, loop/recur performs tail call optimization, so no stack is used (is, in fact, an iterative process written using recursive syntax).
Reading other answers, and because of the stack trace, I see there's a problem with concat and adding a doall before concat solves the stack overflow problem. But... why?
Here's part of the code for the two-arity version of concat.
(defn concat [x y]
(lazy-seq
(let [s (seq x)]
,,,))
)
Notice that it uses two other functions, lazy-seq, and seq. lazy-seq is a bit like a lambda, it wraps some code without executing it yet. The code inside the lazy-seq block has to result in some kind of sequence value. When you call any sequence operation on the lazy-seq, then it will first evaluate the code ("realize" the lazy seq), and then perform the operation on the result.
(def lz (lazy-seq
(println "Realizing!")
'(1 2 3)))
(first lz)
;; prints "realizing"
;; => 1
Now try this:
(defn lazy-conj [xs x]
(lazy-seq
(println "Realizing" x)
(conj (seq xs) x)))
Notice that it's similar to concat, it calls seq on its first argument, and returns a lazy-seq
(def up-to-hundred
(reduce lazy-conj () (range 100)))
(first up-to-hundred)
;; prints "Realizing 99"
;; prints "Realizing 98"
;; prints "Realizing 97"
;; ...
;; => 99
Even though you asked for only the first element, it still ended up realizing the whole sequence. That's because realizing the outer "layer" results in calling seq on the next "layer", which realizes another lazy-seq, which again calls seq, etc. So it's a chain reaction that realizes everything, and each step consumes a stack frame.
(def up-to-ten-thousand
(reduce lazy-conj () (range 10000)))
(first up-to-ten-thousand)
;;=> java.lang.StackOverflowError
You get the same problem when stacking concat calls. That's why for instance (reduce concat ,,,) is always a smell, instead you can use (apply concat ,,,) or (into () cat ,,,).
Other lazy operators like filter and map can exhibit the exact same problem. If you really have a lot of transformation steps over a sequence consider using transducers instead.
;; without transducers: many intermediate lazy seqs and deep call stacks
(->> my-seq
(map foo)
(filter bar)
(map baz)
,,,)
;; with transducers: seq processed in a single pass
(sequence (comp
(map foo)
(filter bar)
(map baz))
my-seq)
Arne had a good answer (and, in fact, I'd never noticed cat before!). If you want a simpler solution, you can use the glue function from the Tupelo library:
Gluing Together Like Collections
The concat function can sometimes have rather surprising results:
(concat {:a 1} {:b 2} {:c 3} )
;=> ( [:a 1] [:b 2] [:c 3] )
In this example, the user probably meant to merge the 3 maps into one. Instead, the three maps were mysteriously converted into length-2 vectors, which were then nested inside another sequence.
The conj function can also surprise the user:
(conj [1 2] [3 4] )
;=> [1 2 [3 4] ]
Here the user probably wanted to get [1 2 3 4] back, but instead got a nested vector by mistake.
Instead of having to wonder if the items to be combined will be merged, nested, or converted into another data type, we provide the glue function to always combine like collections together into a result collection of the same type:
; Glue together like collections:
(is (= (glue [ 1 2] '(3 4) [ 5 6] ) [ 1 2 3 4 5 6 ] )) ; all sequential (vectors & lists)
(is (= (glue {:a 1} {:b 2} {:c 3} ) {:a 1 :c 3 :b 2} )) ; all maps
(is (= (glue #{1 2} #{3 4} #{6 5} ) #{ 1 2 6 5 3 4 } )) ; all sets
(is (= (glue "I" " like " \a " nap!" ) "I like a nap!" )) ; all text (strings & chars)
; If you want to convert to a sorted set or map, just put an empty one first:
(is (= (glue (sorted-map) {:a 1} {:b 2} {:c 3}) {:a 1 :b 2 :c 3} ))
(is (= (glue (sorted-set) #{1 2} #{3 4} #{6 5}) #{ 1 2 3 4 5 6 } ))
An Exception will be thrown if the collections to be 'glued' are not all of the same type. The allowable input types are:
all sequential: any mix of lists & vectors (vector result)
all maps (sorted or not)
all sets (sorted or not)
all text: any mix of strings & characters (string result)
I put glue into your code instead of concat and still got a StackOverflowError. So, I also replaced the lazy filter and remove with eager versions keep-if and drop-if to get this result:
(defn qsort [list]
(loop [[current & todo :as all] [list] sorted []]
(cond
(nil? current) sorted
(or (nil? (seq current)) (= (count current) 1))
(recur todo (glue sorted current))
:else (let [[pivot & rest] current
pred #(> (compare pivot %) 0)
lt (keep-if pred rest)
gte (drop-if pred rest)
work (list* lt [pivot] gte todo)]
(recur work sorted)))))
(defn tlfnum [] (str/join (repeatedly 10 #(rand-int 10))))
(defn tlfbook [n] (repeatedly n #(tlfnum)))
(def result
(time (count (qsort (tlfbook 10000)))))
-------------------------------------
Clojure 1.8.0 Java 1.8.0_111
-------------------------------------
"Elapsed time: 1377.321118 msecs"
result => 10000

transient map not updated as expected [duplicate]

I'm a bit lost with usage of transients in clojure. Any help will be appreciated.
The sample code:
(defn test-transient [v]
(let [b (transient [])]
(for [x v] (conj! b x))
(persistent! b)))
user> (test-transient [1 2 3])
[]
I tried to make it persistent before return and the result is:
(defn test-transient2 [v]
(let [b (transient [])]
(for [x v] (conj! b x))
(persistent! b)
b))
user> (test-transient2 [1 2 3])
#<TransientVector clojure.lang.PersistentVector$TransientVector#1dfde20>
But if I use conj! separately it seems work ok:
(defn test-transient3 [v]
(let [b (transient [])]
(conj! b 0)
(conj! b 1)
(conj! b 2)
(persistent! b)))
user> (test-transient3 [1 2 3])
[0 1 2]
Does for has some constraint? If so, how can i copy values from persistent vector to transient?
Thank you.
Transients aren't supposed to be bashed in-place like that. Your last example only works due to implementation details which you shouldn't rely on.
The reason why for doesn't work is that it is lazy and the conj! calls are never executed, but that is besides the point, as you shouldn't work with transients that way anyway.
You should use conj! the same way as you would use the "regular" conj with immutable vectors - by using the return value.
What you are trying to do could be accomplished like this:
(defn test-transient [v]
(let [t (transient [])]
(persistent! (reduce conj! t v))))

Making current function of list recursive Clojure

Hi i am looking for a bit of help with some Clojure code. I have written a function that will take in a list and calculate the qty*price for a list eg. '(pid3 6 9)
What i am looking for is to expand my current function so that it recursively does the qty*price calculation until it reaches the end of the list.
My current function is written like this:
(defn pid-calc [list] (* (nth list 1) (nth list 2)))
I have tried implementing it into a recursive function but have had no luck at all, i want to be able to call something like this:
(pid-calcc '( (pid1 8 5) (pid2 5 6))
return==> 70
Thats as close as i have came to an answer and cannot seem to find one. If anyone can help me find a solution i that would be great. As so far i am yet to find anything that will compile.
​(defn pid-calc [list]
(if(empty? list)
nil
(* (nth list 1) (nth list 2)(+(pid-calc (rest list))))))
You don't need a recursive function. Just use + and map:
(defn pid-calc [list]
(letfn [(mul [[_ a b]] (* a b))]
(apply + (map mul list))))
#sloth's answer, suitably corrected, is a concise and fast enough way to solve your problem. It shows you a lot.
Your attempt at a recursive solution can be (a)mended to
(defn pid-calc [list]
(if (empty? list)
0
(let [x (first list)]
(+ (* (nth x 1) (nth x 2)) (pid-calc (next list))))))
This works on the example, but - being properly recursive - will run out of stack space on a long enough list. The limit is usually about 10K items.
We can get over this without being so concise as #sloth. You might find the following easier to understand:
(defn pid-calc [list]
(let [line-total (fn [item] (* (nth item 1) (nth item 2)))]
(apply + (map line-total list))))
reduce fits your scenario quite well:
(def your-list [[:x 1 2] [:x 1 3]])
(reduce #(+ %1 (* (nth %2 1) (nth %2 2))) 0 your-list)
(reduce #(+ %1 (let [[_ a b] %2] (* a b)) 0 your-list)

Trouble with lazy convolution fn in Clojure

I am writing some signal processing software, and I am starting off by writing out a discrete convolution function.
This works fine for the first ten thousand or so list of values, but as they get larger (say, 100k), I begin to get StackOverflow errors, of course.
Unfortunately, I am having a lot of trouble converting the imperative convolution algorithm I have to a recursive & lazy version that is actually fast enough to use (having at least a modicum of elegance would be nice as well).
I am also not 100% sure I have this function completely right, yet – please let me know if I'm missing something/doing something wrong. I think it's correct.
(defn convolve
"
Convolves xs with is.
This is a discrete convolution.
'xs :: list of numbers
'is :: list of numbers
"
[xs is]
(loop [xs xs finalacc () acc ()]
(if (empty? xs)
(concat finalacc acc)
(recur (rest xs)
(if (empty? acc)
()
(concat finalacc [(first acc)]))
(if (empty? acc)
(map #(* (first xs) %) is)
(vec-add
(map #(* (first xs) %) is)
(rest acc)))))))
I'd be much obliged for any sort of help: I'm still getting my bearings in Clojure, and making this elegant and lazy and/or recursive would be wonderful.
I'm a little surprised how difficult it is to express an algorithm which is quite easy to express in an imperative language in a Lisp. But perhaps I'm doing it wrong!
EDIT:
Just to show how easy it is to express in an imperative language, and to give people the algorithm that works nicely and is easy to read, here is the Python version. Aside from being shorter, more concise and far easier to reason about, it executes orders of magnitude faster than the Clojure code: even my imperative Clojure code using Java arrays.
from itertools import repeat
def convolve(ns, ms):
y = [i for i in repeat(0, len(ns)+len(ms)-1)]
for n in range(len(ns)):
for m in range(len(ms)):
y[n+m] = y[n+m] + ns[n]*ms[m]
return y
Here, on the other hand, is the imperative Clojure code. It also drops the last, non fully-immersed, values from the convolution. So aside from being slow and ugly, it's not 100% functional. Nor functional.
(defn imp-convolve-1
[xs is]
(let [ys (into-array Double (repeat (dec (+ (count xs) (count is))) 0.0))
xs (vec xs)
is (vec is)]
(map #(first %)
(for [i (range (count xs))]
(for [j (range (count is))]
(aset ys (+ i j)
(+ (* (nth xs i) (nth is j))
(nth ys (+ i j)))))))))
This is so disheartening. Please, someone show me I've just missed something obvious.
EDIT 3:
Here's another version I thought up yesterday, showing how I'd like to be able express it (though other solutions are quite elegant; I'm just putting another one out there!)
(defn convolve-2
[xs is]
(reduce #(vec-add %1 (pad-l %2 (inc (count %1))))
(for [x xs]
(for [i is]
(* x i)))))
It uses this utility function vec-add:
(defn vec-add
([xs] (vec-add xs []))
([xs ys]
(let [lxs (count xs)
lys (count ys)
xs (pad-r xs lys)
ys (pad-r ys lxs)]
(vec (map #(+ %1 %2) xs ys))))
([xs ys & more]
(vec (reduce vec-add (vec-add xs ys) more))))
(vec (reduce vec-add (vec-add xs ys) more))))
(defn ^{:static true} convolve ^doubles [^doubles xs ^doubles is]
(let [xlen (count xs)
ilen (count is)
ys (double-array (dec (+ xlen ilen)))]
(dotimes [p xlen]
(dotimes [q ilen]
(let [n (+ p q), x (aget xs p), i (aget is q), y (aget ys n)]
(aset ys n (+ (* x i) y)))))
ys))
Riffing on j-g-faustus's version if I was doing this in the Clojure equiv branch. Works for me. ~400ms for 1,000,000 points, ~25ms for 100,000 on a i7 Mackbook Pro.
The likely cause of the stack overflow errors is that the lazy thunks are getting too deep. (concat and map are lazy). Try wrapping those calls in doall to force evaluation of their return values.
As for a more functional solution, try something like this:
(defn circular-convolve
"Perform a circular convolution of vectors f and g"
[f g]
(letfn [(point-mul [m n]
(* (f m) (g (mod (- n m) (count g)))))
(value-at [n]
(reduce + (map #(point-mul % n) (range (count g)))))]
(map value-at (range (count g)))))
Use can use reduce to perform summation easily, and since map produces a lazy sequence, this function is also lazy.
Can't help with a high-performance functional version, but you can get a 100-fold speedup for the imperative version by foregoing laziness and adding type hints:
(defn imp-convolve-2 [xs is]
(let [^doubles xs (into-array Double/TYPE xs)
^doubles is (into-array Double/TYPE is)
ys (double-array (dec (+ (count xs) (count is)))) ]
(dotimes [i (alength xs)]
(dotimes [j (alength is)]
(aset ys (+ i j)
(+ (* (aget xs i) (aget is j))
(aget ys (+ i j))))))
ys))
With xs size 100k and is size 2, your imp-convolve-1 takes ~6,000ms on my machine when wrapped in a doall, while this one takes ~35ms.
Update
Here is a lazy functional version:
(defn convolve
([xs is] (convolve xs is []))
([xs is parts]
(cond
(and (empty? xs) (empty? parts)) nil
(empty? xs) (cons
(reduce + (map first parts))
(convolve xs is
(remove empty? (map rest parts))))
:else (cons
(+ (* (first xs) (first is))
(reduce + (map first parts)))
(lazy-seq
(convolve (rest xs) is
(cons
(map (partial * (first xs)) (rest is))
(remove empty? (map rest parts)))))))))
On sizes 100k and 2, it clocks in at ~600ms (varying 450-750ms) vs ~6,000ms for imp-convolve-1 and ~35ms for imp-convolve-2.
So it's functional, lazy and has tolerable performance. Still, it's twice as much code as the imperative version and took me 1-2 additional hours to find, so I'm not sure that I see the point.
I'm all for pure functions when they make the code shorter or simpler, or have some other benefit over an imperative version. When they don't, I have no objection to switch to imperative mode.
Which is one of the reasons I think Clojure is great, since you can use either approach as you see fit.
Update 2:
I'll amend my "what's the point of doing this functionally" by saying that I like this functional implementation (the second one, further down the page) by David Cabana.
It's brief, readable and times to ~140ms with the same input sizes as above (100,000 and 2), making it by far the best-performing functional implementation of those I tried.
Considering that it is functional (but not lazy), uses no type hints and works for all numeric types (not just doubles), that's quite impressive.
(defn convolve [xs is]
(if (> (count xs) (count is))
(convolve is xs)
(let [os (dec (+ (count xs) (count is)))
lxs (count xs)
lis (count is)]
(for [i (range os)]
(let [[start-x end-x] [(- lxs (min lxs (- os i))) (min i (dec lxs))]
[start-i end-i] [(- lis (min lis (- os i))) (min i (dec lis))]]
(reduce + (map *
(rseq (subvec xs start-x (inc end-x)))
(subvec is start-i (inc end-i)))))))))
It is possible to express a lazy, functional solution in concise terms. Alas, the performance for > 2k is impractical. I'm interested to see if there are ways to speed it up without sacrificing readability.
Edit:
After reading drcabana's informative post on the topic (http://erl.nfshost.com/2010/07/17/discrete-convolution-of-finite-vectors/), I've updated my code to accept different sized vectors. His implementation is better performing:
for xs size 3, is size 1000000, ~2s vs ~3s
Edit 2:
Taking drcabana's ideas of simply reversing xs and padding is, I arrived at:
(defn convolve [xs is]
(if (> (count xs) (count is))
(convolve is xs)
(let [is (concat (repeat (dec (count xs)) 0) is)]
(for [s (take-while not-empty (iterate rest is))]
(reduce + (map * (rseq xs) s))))))
This is probably as concise as it's going to get, but it is still slower overall, likely due to take-while. Kudos to the blog author for a well considered approach. The only advantage here is that the above is truly lazy in that if I ask (nth res 10000), it will only need the first 10k calculations to arrive at a result.
Not really an answer to any of the many questions you asked, but I have several comments on the ones you didn't ask.
You probably shouldn't use nth on vectors. Yes, it's O(1), but because nth works on other sequences in O(n), it (a) doesn't make it clear that you expect the input to be a vector, and (b) means if you make a mistake, your code will mysteriously get really slow instead of failing immediately.
for and map are both lazy, and aset is side-effects-only. This combination is a recipe for disaster: for side-effecting for-like behavior, use doseq.
for and doseq allow multiple bindings, so you don't need to pile up loads of them like you (apparently) do in Python.
(doseq [i (range (count cs))
j (range (count is))]
...)
will do what you want.
#(first %) is more concisely written as first; likewise #(+ %1 %2) is +.
Calling vec on a bunch of intermediate results that don't need to be vectors will slow you down. Specifically in vec-add it's sufficient to only call vec when you make a final return value: in (vec (reduce foo bar)) there's no reason for foo to turn its intermediate results into vectors if it never uses them for random access.

Resources