I need to make loop method, which takes as argument some method name and how many times it will be looped.
Problem is that, i can't use any mutations (def,let and etc) as well as standart clojure functions, except if, inc, dec, println, +, -, = and etc.
Only with SEQ and Recursion !!!
My example:
;; F = some function name, for example, inc, dec, println and etc.
(defn my-loop [f n]
(if (= n 0)
f
(my-loop f (dec n))))
;; Returns 2, instead of 3, because on next iteration argument F = nil :(
(my-loop (inc 1) 2)
Obviously, when recursion is called, argument F is NIL, so how i can return same argument when recursion was called (without hardcode).
(letfn [(my-loop [f n result]
(if (< n 1) result
(recur f (dec n) (f result))))]
(my-loop inc 2 1))
Thanks for help, my solution is:
(defn my-loop [f n result]
(if (< n 1)
result
(my-loop f (dec n) (f result))))
(my-loop inc 2 1)
Related
Hello I can't wrap my head around this problem:
(defn integrate
"Finding the definite integral from 0 to stop"
([f dx]
(let [itg (memoize
(fn [itg stop n]
(if (<= n 0)
0
(+ (let [b (* n dx) a (- b dx)]
(println "[DEBUG] stop = " stop " and n =" n)
(* (- b a) (/ (+ (f a) (f b)) 2))
)
(itg itg stop (dec n))))))
itg (partial itg itg)]
(fn [x] (itg x (quot x dx))))))
(time ((integrate (fn [x] (* x x)) 0.1) 5))
(time ((integrate (fn [x] (* x x)) 0.1) 5))
I expect that the 2nd time I call this function, it should hit the memoized result, but it just recalculates the whole integral the second time and prints the DEBUG messages all over again.
Why this happens? How to fix this?
Two problems. 1) Each call to integrate creates a fresh memoized function, so a second call to integrate won't reuse any results computed by the first call. 2) One of the parameters to the memoized function is itself a function. It is not true that (= (fn []) (fn [])), so the memo might not match as often as you hope.
You can find a good write-up on this issue here: https://quanttype.net/posts/2020-09-20-local-memoized-recursive-functions.html
I want to write the function collect which can combine the sublists into a list, like:
user=> (collect '(a b c d e) 1)
((a)(b)(c)(d)(e))
user=> (collect '(a b c d e) 2)
((a b)(c d)(e))
user=> (collect '(a b c d e) 5)
(a b c d e))
this is my code:
(defn collect [lst num]
(loop [l lst res (atom ())]
(if (<= (count l) num) #res
(recur (drop num l) (swap! res conj (take num (drop num l)))))))
But when I run
user=> (collect '(a b c d e) 1)
I got the error:
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IAtom clojure.core/swap!
why I cannot get the res when I use "swap!" ? Thank you.
It's blowing up in the second pass through the loop.
swap returns the value that was put into the atom, not the atom it's self. So the first pass is updating the atom, and then passing the value it just put into the atom to the second pass through the loop. in the second pass it's trying to use the value as the atom, and getting the exception above.
To "fix" this use a do to update the atom, then pass the atom to the next pass through the loop once it contains the correct value.
user> (defn collect [lst num]
(loop [l lst res (atom ())]
(if (<= (count l) num) #res
(recur (drop num l)
(do (swap! res conj (take num (drop num l)))
res)))))
#'user/collect
user> (collect '(a b c d e) 2)
((e) (c d))
You can also in this case, just remove the atom completely and get exactly the same result (I fixed on ordering problem from your example by using a [] instead of () in the initial value of res):
user> (defn collect [lst num]
(loop [l lst res []]
(if (<= (count l) num) res
(recur (drop num l)
(conj res (take num (drop num l)))))))
#'user/collect
user> (collect '(a b c d e) 2)
[(c d) (e)]
and of course you can also use partition-all as glts mentions above.
;; this would be a correct way to do it
(defn collect [coll n]
(partition-all n coll))
;; this would be a clumsy way to do it
(defn collect
"using a loop (there is not point to do that but at least you can see the logic working as in your example)"
[coll n]
(lazy-seq
(loop [res []
coll coll]
(if (empty? coll)
res
(recur (conj res (take n coll)) (drop n coll))))))
Regarding your error, on the second loop, res is a list-like value, not an atom anymore. That would lead us to :
(defn collect [coll n]
(lazy-seq (loop [res (atom [])
coll coll]
(if (empty? coll)
#res
(recur (do (swap! res conj (take n coll))
;; return the atom instead of the value'
res)
(drop n coll))))))
Note that in order to preserve the order in the solution, I use a vector (litteral []) instead of a list (litteral '()). This is because of the behaviour of conj described here.
I want to create a generator to do, 1 2 3 4.
(defn getNums []
(loop [i 4
r []]
(when (<= i 0)
r ;<--- point A
(recur (dec i)
(conj r i)))))
(getNums) ;Eval to nil.
Nothing get return, why ?
Would the code in point A return result vector r ?
when, is a clojure macro defined as:
(when test & body)
So, in your first example, the body of when would be:
(do
r
(recur (dec i)
(conj r i)))
The when test itself is evaluated to false so the body of the when macro is not executed.
The return value of the function it therefore the return value of when itself is return, which is nil. Ex:
(when (< 2 1)) ; nil
By the way, there is a build in function range that does the same as your method:
(range 1 10)
And, in a more generic way, you could use the lazy function iterate:
(take 10 (iterate inc 1))
(defn getNums []
(loop [i 4
r []]
(if (<= i 0)
r
(recur (dec i)
(cons i r)))))
(getNums)
I'm trying to solve the Count a Sequence problem on 4Clojure, but I can't work out what's wrong with my use of recur:
fn [s] (
fn [t n] (
if (empty t)
n
(recur (rest t) (+ n 1))
) s 0
)
It gives the following exception:
java.lang.UnsupportedOperationException: Can only recur from tail position, compiling:(NO_SOURCE_PATH:0)
But to me it seems that the call to recur is in a tail position for the inner function. What am I missing?
Two problems:
Your parentheses are misplaced.
You are using empty where you want empty?.
Parentheses
The fn special form for defining a function takes the shape
(fn name? [params* ] exprs*) with the parentheses around it.
Another level of parentheses applies the function ((fn [n] (* n n))
3) => 9.
Using defn instead of fn for the moment, we get
(defn l [s]
((fn [t n] (if (empty? t) n (recur (rest t) (+ n 1))))
s 0))
Then, for example,
(l ())
; 0
and
(l [1 2 3])
; 3
#Thumbnail is right -- your code will work just fine if you fix the placement of your parentheses (most importantly, you need to add a ( before (fn [t n] ... and a corresponding ) after s 0, in order to actually return the result of calling that function (the one that takes t and n as arguments) on the values s and 0. Otherwise, you are returning the function itself.), and change empty to empty?.
If you wanted to simplify things a bit, you might consider using a loop/recur structure instead, like this:
(fn [s]
(loop [t s, n 0]
(if (empty? t)
n
(recur (rest t) (+ n 1)))))
I am having a problem running my program in Clojure. I just start learning Clojure a couple of weeks ago. So I don't know the quick and easy way to debug a Clojure program. My func2 raises an exception at (adj(a b)) as followed:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
user/func2.
I don't know what is wrong with it. Can someone point out the problem with my coding?
And in func3, I call func2 recursively, but it throws:
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lan g.AFn.throwArity (AFn.java:437)
What is wrong with func3? Thank you.
(defn adj [value1 value2]
(def result (+ (/ value1 2) (/ value2 2)))
(if (= (mod result 2) 1)
(+ result 1)
result
)
)
(defn func2 [list]
(let [[a b c d] list]
(inc d)
([(adj c a) (adj a b) (adj b c) d]))
)
(defn func3 [list]
(loop [v list r []]
(if(= (v 0) (v 1) (v 2))
(conj list r)
(func3(func2(list)))
))
)
What's the intended result of these functions? We probably need to see some sample inputs and expected results to really be able to help you.
Here's my attempt at cleaning them up. I've noted the changes I made as comments. func3 has the most serious problem in that it's an infinite recursion - there's no end condition. What should cause it to stop working and return a result?
(defn adj [value1 value2]
;; don't use def within functions, use let
(let [result (+ (/ value1 2) (/ value2 2))]
(if (= (mod result 2) 1)
(+ result 1)
result)))
(defn func2 [list]
(let [[a b c d] list]
;; The extra parens around this vector were causing it
;; to be called as a function, which I don't think is
;; what you intended:
[(adj c a) (adj a b) (adj b c) d]))
;; This needs an end condition - it's an infinite recursion
(defn func3 [list]
(loop [v list r []]
(if (= (v 0) (v 1) (v 2))
(conj list r)
;; Removed extra parens around list
(func3 (func2 list)))))
The reason I say not to use def within functions is that it always creates a global function. For local bindings you want let.
Regarding the extra parens, the difference between [1 2 3] and ([1 2 3]) is that the former returns a vector containing the numbers 1, 2, and 3, whereas the latter tries to call that vector as a function. You had excess parens around the literal vector in func2 and around list in func3, which was causing exceptions.
As a style note, the name list isn't a good choice. For one thing, it's shadowing clojure.core/list, and for another you're probably using vectors rather than lists anyway. It would be more idiomatic to use coll (for collection) or s (for sequence) as the name.
This would suggest at least one other change. In func3 you use a vector-only feature (using the vector as a function to perform lookup by index), so to be more general (accept other data structures) you can convert to a vector with vec:
(defn func3 [coll]
(loop [v (vec coll) r []]
(if (= (v 0) (v 1) (v 2))
(conj v r)
(func3 (func2 v)))))
Oh, there is no need to debug that. I suggest you have a look at LightTable.
The first two functions are easily fixed:
(defn adj [value1 value2]
;(def result (+ (/ value1 2) (/ value2 2))) def creates a global binding in current namespace !!!
(let [result (+ (/ value1 2) (/ value2 2))]
(if
(= (mod result 2) 1)
(inc result)
result)))
(defn func2 [xx]
(let [[a b c d] xx]
[ (adj c a) (adj a b) (adj b c) (inc d)]
))
The third function is not clear to me. I don't read your intent. What I understand is: "Keep applying func2 to itself until the first three elements of its result are equal." But I'm afraid this condition is never met, so I replaced it with a true in order to see just one result without blowing the stack.
(defn func3 [xx]
(loop [ v (func2 xx) ]
(if
;(= (v 0) (v 1) (v 2))
true
v
(recur (func2 v))
)))
Useful link: http://clojure.org/cheatsheet
Cheers -