Cannot update vector by looping element by element - loops

I am trying to set each element of a vector equal to 3 by looping. I get:
java.lang.ClassCastException: clojure.lang.PersistentVector can
not be cast to java.lang.Number
This is the code.
(def w [1 2 3])
(defn update [index value]
(assoc w index value))
(loop [i -1]
(if (< (count w) i)
w
(recur (update (+ i 1) 3))))

Your update function doesn't work the way you expect.
(assoc w index value)
Produces a new vector based on w, except that the element at index is now value. It doesn't change w.
user> (def w [1 2 3])
user> (assoc w 0 9)
[9 2 3]
user> w
[1 2 3]
Also, you're not using loop/recur correctly. You begin the loop with i bound to -1, intending to use it as an index into w, but recur calls the loop not with the next value of i, but rather with an altered copy of w as returned by update.
Try something more like:
(def w [1 2 3])
(loop [i 0, v w]
(if (< (count w) i)
v
(recur (inc i) (assoc v i 3))))
But, since you're not actually using the index to compute the new value of the element, you can use map instead of loop. Since just setting each element to a constant value without considering its old value, you can use clojure's built-in function constantly.
(vec (map (constantly 3) w))
Map returns a sequence, I've wrapped it in a call to vec to transform it back into a vector.

You are mixing integer and vector type by passing (update ...) to recur function. The loop statement should be look like (loop [i -1 w w] ..) and then you could collect your new vector into the local "w". If you want to use recure statement this code can help you (I guess there are a lot of other options to change values of a vector):
(let [value 4
w [1 2 3]]
(loop [i 0
w w]
(if (< i (count w))
(recur (inc i) (assoc w i value))
w)))

You can do this with map and constantly:
(def w [1 2 3])
(map (constantly 3) w)
=> (3 3 3)
Note that this doesn't change w - it returns a new sequence of threes that is the same length as w. Therefore you could equally get the same result by using:
(repeat (count w) 3)
=> 3
If you actually want to change w, then I would suggest making w into an atom so it can be updated with a swap! function:
(def w (atom [1 2 3]))
(swap! w
(fn [old-w]
(vec (map (constantly 3) old-w))))
#w
=> [3 3 3]
Finally, if you really want to update the elements of w one at a time, you can do something like:
(dotimes [i (count #w)]
(swap! w
(fn [previous-w]
(assoc previous-w i 3))))
This seems rather unidiomatic and imperative in Clojure, but it does work.....

Related

How do I flatten params passed to recur?

I'm trying to learn about loop/recur. I wanted to pass the return vector from a function back to the loop and I've tried something like this:
(defn foo [x y]
[(dec x) y])
(loop [x 3 y 4]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
That gives:
1. Caused by java.lang.IllegalArgumentException
Mismatched argument count to recur, expected: 2 args, got: 1
Now I can change the loop parameters to this other form which works:
(defn foo [x y]
[(dec x) y])
(loop [[x y] [3 4]]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
I'd like to know if there's any way I could change the first code to leave the (loop [x 3 y 4] ...) but change the arguments passed to recur somehow. I guess I need something like the apply function, but I couldn't get that to work with recur, because recur is not a function.
There is no easy way around it. recur is a special
form and Clojures
way around the JVM not having easy access to TCO.
Therefor you can not use apply here (which would be a solution to call
a function with arguments from a list).
So you have to hold on to the result of foo and then recur with
those. Note beside: if with just one branch is just when.
(defn foo [x y]
[(dec x) y])
(loop [x 3 y 4]
(when (> x 0)
(prn x y)
(let [[x' y'] (foo x y)]
(recur x' y'))))
If your domain here really is [x y] (e.g. coordinates) my suggestion
would be to build your functions around that and don't jump between
sometimes using a vector and sometimes passing x/y.
you could also make up a simple macro for that purpose.. maybe like this (which is basically a macro rewrite of your vectorized params variant):
(defmacro loop1 [bindings & body]
(let [left-side (vec (take-nth 2 bindings))
right-side (vec (take-nth 2 (rest bindings)))]
`(loop [~left-side ~right-side]
~#body)))
(loop1 [x 3 y 4]
(if (> x 0)
(do
(prn x y)
(recur (foo x y)))))
;;=> 3 4
;; 2 4
;; 1 4
nil
so, if you have repetitive usage pattern alike that, this macro could be a nice utility.

Idiomatic way to run nested loop with passing value

I want to do something like this
int n=0
for(int i=xs; i<xe; i++){
for(int j=ys; j<ye; j++){
n++
}
}
return n;
in Clojure way. Since all values are immutable, I think the value n should be passed as a parameter of a (possibly) recursive function. What is the best way to do so?
the closest to your code would be
(defn f [xs xe ys ye]
(let [n (atom 0)]
(doseq [_ (range xs xe)
_ (range ys ye)]
(swap! n inc))
#n))
user> (f 1 10 2 20)
;;=> 162
but the mutable atom approach is unidiomatic at all.
it could look like this, a bit more clojure way:
(defn f [xs xe ys ye]
(count (for [_ (range xs xe)
_ (range ys ye)]
nil)))
#'user/f
user> (f 1 10 2 20)
;;=> 162
it really depends on what you're trying to do. Counting n's is obviously done better by (* (- xe xs) (- ye ys)) , as #jas noticed, independent from what language you use )
what about recursive solution you mentioned, it could look like this:
(defn f [xs xe ys ye]
(loop [n 0 i xs j ys]
(cond (== j ye) n
(== i xe) (recur n xs (inc j))
:else (recur (inc n) (inc i) j))))
#'user/f
user> (f 1 10 2 20)
;;=> 162
Don't over-think the problem. When you really need mutable state, you can always use an atom:
(defn calc
[xs ys]
(let [result (atom 0)]
(doseq [x xs]
(doseq [y ys]
(swap! result + (* x y))))
#result))
(let [xs [1 2 3]
ys [2 5 7 9]]
(calc xs ys))
with result
(calc xs ys) => 138
You could also use a volatile. It is like a non-thread-safe atom. Note the use of vswap!:
(defn calc
[xs ys]
(let [result (volatile! 0)]
(doseq [x xs]
(doseq [y ys]
(vswap! result + (* x y))))
#result))
Performance
In a tight loop, using a volatile makes a difference. An example:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [tupelo.profile :as prof]))
(def N 100)
(def vals (vec (range N)))
(prof/defnp summer-atom []
(let [result (atom 0)]
(doseq [i vals]
(doseq [j vals]
(doseq [k vals]
(swap! result + i j k))))
#result))
(prof/defnp summer-volatile []
(let [result (volatile! 0)]
(doseq [i vals]
(doseq [j vals]
(doseq [k vals]
(vswap! result + i j k))))
#result))
(dotest
(prof/timer-stats-reset)
(dotimes [i 10]
(spyx (summer-atom))
(spyx (summer-volatile)))
(prof/print-profile-stats))
with result:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
(summer-atom) => 148500000
(summer-volatile) => 148500000
...
---------------------------------------------------------------------------------------------------
Profile Stats:
Samples TOTAL MEAN SIGMA ID
10 2.739 0.273879 0.023240 :tst.demo.core/summer-atom
10 0.383 0.038313 0.041246 :tst.demo.core/summer-volatile
---------------------------------------------------------------------------------------------------
So it makes about a 10x difference. Probably not worthwhile unless you are doing at least a million operations like here (100^3).
For similar low-level operations on data structures, please see transient! and friends.
Especially bookmark the Clojure CheatSheet from this list
I think here you can apply reduce function over for. What you do inside loop-processing-fn is up to you - it can be recursive as well.
(let [n-init 0 ;; your `n` variable
xs 10 xe 20 ys -5 ye 5 ;; loop(s) ranges
loop-processing-fn (fn [current-state [i j :as loop-data]]
(inc current-state) ;; anything here
) ;; processing function operating on state (n) and loop data
]
(reduce loop-processing-fn n-init (for [i (range xs xe)
j (range ys ye)]
[i j])))
;; => 100
Macros come to mind. I defined a macro for-state that I use like this:
(def xs 0)
(def xe 9)
(def ys 1)
(def ye 4)
(for-state
i xs (< i xe) (inc i) n 0
(for-state
j ys (< j ye) (inc j) n n
(inc n)))
;; => 27
Macros let you add new constructs that are hard to build using just functions. So if you have several nested loops of this kind, defining a macro like for-state could be an option:
(defmacro for-state [iter-var iter-init iter? iter-next
state-var state-init state-next]
`(loop [~iter-var ~iter-init
~state-var ~state-init]
(if ~iter?
(recur ~iter-next
~state-next)
~state-var)))
You can tweak it as you please. For example, you could group the macro arguments using vectors and do destructuring of those arguments to facilitate readability.

Clojure multiply first n elements in sequence by 'x' non recursive

I am a newbie in clojure and came across a problem which says, multiply first n elements in a sequence by some number 'x' (non recursively). So for example
(multiply-n-by-x [1 2 3 4 5] 2 10) => [10 20 30 4 5]
So here i understood that i need to loop over the sequence n times and then stop, but i am unable to do that. If someone could guide me on how to do about it, it would be great.
Same as Shawn's answer but with destructuring and split-at (a bit less redundant):
(defn multiply-n-by-x [s n x]
(let [[s1 s2] (split-at (inc n) s)]
(concat (map #(* x %) s1) s2)))
I think the easy way is :
(defn multiply-n-by-x [seq n m]
(concat (map #(* m %) (take (inc n) seq)) (drop (inc n) seq) )
)
This does what you want:
(defn multiply-n-by-x [sq n x]
(for [i (range (count sq)) ;for i in range 0 to number of elements in sq
:let [element (nth sq i)]] ;bind element to the nth item in sq
(if (<= i n) ;if index below n, return the multiplied element, otherwise return the element as is
(* x element)
element)))
whatever you return inside the for macro gets put into a sequence so the end result is collection.
Lazy sequences capture delayed recursion. take, drop, split and for are lazy constructions. We can avoid them by computing the altered head of the sequence eagerly, as follows:
(defn multiply-n-by-x [coll n x]
(loop [head [], coll coll, n n]
(if (and (seq coll) (>= n 0))
(recur (conj head (* (first coll) x)) (rest coll) (dec n))
(concat head coll))))
For example,
(multiply-n-by-x [1 2 3 4 5] 2 10)
;(10 20 30 4 5)
By the way, the convention in Clojure is to give the count of a slice, not the index of the final element, which is one less.
(range 3)
;(0 1 2)

add value to first list (of lists) matching predicate

I have a list of lists and a value. My goal is a new list of lists, where the value is conjed (new first item) to the first list matching a predicate (eg > to the first item of the list). If no list matches the predicate, I want my value to "begin" a new list at the end of lists.
if my list is: ['(2 3 4) '(4 5 6 7) '(5 6 7)]
and my value: 3
and my predicate: (comp (partial < my-value) first)
then my result should be: ['(2 3 4) '(3 4 5 6 7) '(5 6 7)]
if my value was: 10
my result should be: ['(2 3 4) '(4 5 6 7) '(5 6 7) '(10)]
This problem confuses me, because my imperative mind keeps telling me how easy it should be, but I cannot find an easy (ok, be honest: any) solution. this is my attempt so far:
(defn add-to-first-list-that-matches [func value]
(loop [result []
remaining-lists list-of-lists
value-to-add value]
(if (empty? remaining-lists)
result
(let [current-list (first remaining-lists)
value-matches? (func value-to-add current-list)
new-list (if value-matches? (conj value-to-add current-list) current-list)]
(recur (conj new-list result)
(rest remaining-lists)
(if-not value-matches? value-to-add nil))))))
(it crashes)
please enlighten me with some clojure expression magic :)
btw. I want to solve this as part of the longest-increasing-subsequence problem.
This uses loop-recur.
(defn add-to-ll
[ll pred value]
(loop [[current & unprocessed] ll
processed []]
(cond
(pred current) (concat processed
[(cons value current)]
unprocessed)
(empty? unprocessed) (concat processed
[current]
[[value]])
:else (recur unprocessed
(conj processed current)))))
(def l-l1 [[2 3 4] [4 5 6 7] [5 6 7]])
(add-to-ll l-l1 (comp (partial < 10) first) 10)
=> ([2 3 4] [4 5 6 7] [5 6 7] [10])
(add-to-ll l-l1 (comp (partial < 3) first) 3)
=> ([2 3 4] (3 4 5 6 7) [5 6 7])
You could also use split-with
(defn add-to-ll
[ll pred value]
(let [[first-lists [to-change & rest-lists]] (split-with (complement pred) ll)]
(if to-change
(concat first-lists [(cons value to-change)] rest-lists)
(concat ll [[value]]))))
Performance wise the first solution should run a bit faster.
Ye olde lazy-seq:
(defn add-to-first-match
[pred x coll]
(lazy-seq
(if-let [s (seq coll)]
(let [fst (first s)]
(if (pred fst)
(cons (conj fst x) (rest s))
(cons fst (add-to-first-match pred x (rest s)))))
(cons (list x) nil))))
Note: one could further extract list into an argument and allow for example also vector as element constructor.
(defn find-index
"find index of the first item in s matching predicate `pred`"
[pred s]
(first (keep-indexed (fn [index item]
(if (pred item)
index
nil))
s)))
(defn update-first-match
"update first item in s that matches `pred` using (f item args*)"
[s pred f & args]
(apply update-in s [(or (find-index pred s)
(count s))]
f args))
(def my-lists
['(2 3 4) '(4 5 6 7) '(5 6 7)])
(defn add-to-first-list-less-than
[l n]
(update-first-match l #(< n (first %)) conj n))
;; usage:
(update-first-match my-lists #(< 5 (first %)) conj 5)
;; or
(add-to-first-list-less-than my-lists 5)
Here is my attempt to answer more succinctly using reduce:
(defn add-to-first-list-that-matches
[value lists]
(let [pred (comp (partial < value) first)
[found result] (reduce (fn [[found result] el]
(if (and (not found) (pred el))
[true (conj result (cons value el))]
[found (conj result el)]))
[false []]
lists)]
(if found
result
(conj result (list value)))))
I am using the idiom of a vector in reduce to carry multiple values (a boolean to indicate whether a match has been found, plus the modified data structure we are building up). I was also able to combine the various conditions into a single if per element, plus a final post-condition rather than nested conditions or a multi branch cond.
Here is how it works with your examples:
user> (add-to-first-list-that-matches 3 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (3 4 5 6 7) (5 6 7)]
user> (add-to-first-list-that-matches 10 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (4 5 6 7) (5 6 7) (10)]

Printing contents of array LISP

Why does this code not print out the content of the array -
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(aref state x y))))
Here I am passing a 3x3 matrix which is built like this -
`(setq i (make-array '(3,3) :initial-contents '((0 1 3) (4 2 5) (7 8 6))))`
I am calling - (loopfn i)
Edit--------
#Greg
Thanks for pointing that out...
I had the following question..
Why does this print the output ...
(defun loopfn ()
(loop for x from 0 to 3 do
(if (eq x 2)(return (list x)))))
Where as this prints a nil...
(defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (eq x 2)(return (list x y))))))
I am calling
(loopfn)
Your code does not print anything. That's also what you want - usually.
But you want functions to return something useful.
So you need to understand the difference between printing and having a REPL printing a return value.
CL-USER > 3
3
Above returns 3. The Read-Eval-Print-Loop prints the return value.
CL-USER > (print 3)
3
3
Above prints a newline and then two times the 3. Why?
The first is the side-effect of the PRINT call which prints the newline and then its argument.
The second is the REPL printing the return value.
Note also the EQ is not for numeric comparisons. Use EQL instead.
See: http://www.lispworks.com/documentation/lw50/CLHS/Body/f_eql.htm
As for your second question, (return ...) is equivalent to (return-from NIL ...) so you just return from your inner LOOP into the outer one. Use this instead:
[11]> (defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (= x 2) (return-from loopfn (list x y))))))
[12]> (loopfn)
(2 0)
Another possibility is to collect more values than just one, as in
[36]> (defun loopfn ()
(loop for x from 0 to 2 nconc
(loop for y from 0 to 2
if (= y 2)
collect (list x y))) )
LOOPFN
[37]> (loopfn)
((0 2) (1 2) (2 2))
Your call to aref is getting the specified element, but you're not doing anything with it. You could stick it on to a list which is then returned:
(defun loopfn (state)
(let ((result '()))
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(setf result (cons (aref state x y) result))))
result))
or you could just print it out:
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(format t "~a~%" (aref state x y)))))
The former is far more useful ; you want to return things which can then be further processed, and anything that gets passed to the top level will be printed out for you.
As long as you are using LOOP you can easily gather up your values with COLLECT, APPEND, etc., which is the idiomatic way to do it.
This was neatly covered in this forum topic.
The outer loop has no clause which would cause a return value.
Some code examples from that thread:
(defun print-2d-array-as-table (array)
(loop for i from 0 below (array-dimension array 0)
do (loop for j from 0 below (array-dimension array 1)
do (princ (aref array i j))
(if (= j (1- (array-dimension array 1)))
(terpri)
(princ #\Space)))))
and one loop:
(defun print-2d-array-as-table (array)
(loop for i below (array-total-size array) do
(if (zerop (mod i (array-dimension array 0)))
(terpri)
(princ #\Space))
(princ (row-major-aref array i))))
For your second question, in the loop that doesn't print, (eq x 2) is never true. You have modified the loop bounds from 0 to 3 to 0 to 2, so x never reaches 2. Since there is no explicit (return ...) executed, the function returns nil.

Resources