I am new to clojure and currently struggling with loop / recur. The question basically is why my 'custom' range func. does not return a lazy sequence. Is there something wrong with my implementation or you are not supposed to use recursion in this case?
(defn my-range
[nr]
(loop [l nr acc '()]
(if (< l 1)
acc
(recur (dec l) (conj acc l)))))
When I run it:
> (time (take 10 (my-range 100000))) ;; "Elapsed time: 85.443 msecs"
> (time (take 10 (range 100000))) ;; "Elapsed time: 0.095 msecs"
The very big time difference leads me to belive the list is first constructed and then 10 taken.
You do not use any lazy constructs in my-range. Since you assemble the list by starting at the end and working your way toward the beginning, the only way to access the first ten elements is to first realize all the other elements.
Lazy sequences start at the beginning and work toward the end, like this:
(defn my-range
([end]
(my-range 1 end))
([start end]
(when (<= start end)
(lazy-seq (cons start (my-range (inc' start) end))))))
The trick here is that you don't return a realized sequence. Rather, you return an object that stores this function:
#(cons start (my-range (inc' start) end))
When someone calls seq on that object, it will call the above function, cache its result, and return that result. Future calls to seq will simply return the cached result. Note, though, that the second parameter you pass to cons is also a lazy sequence (because a call to my-range returns a lazy-seq), so it, in turn, will only be realized when necessary.
Just for completeness, another way to write this function is as follows:
(defn my-range
[end]
(take end (iterate inc' 1)))
This works because iterate and take both return lazy sequences.
Related
I'm working on a Newton algorithm to count n-th root and I've encountered a problem with non-working loop. Here is the code:
(defn root [nth guess]
(if (<= guess 0) "Root doesn't exists" (count_root nth guess))
)
(defn count_root nth guess [nth guess]
(def result guess)
(def last_result result)
(def temp (power nth result))
(while (> (absolute (- result last_result)) 0.01)
(do
(def last_result result)
(def result ('fn [nth result guess temp] (* (/ 1.0 nth) (+ (* (- nth 1) result) (/ guess temp)))))
(def temp (power nth result))
)
)
(str "Result: " result)
)
(defn power [nth result]
(* result (- nth 1))
)
(defn absolute [x]
(if (>= x 0) x (- x))
)
When I'll comment out (while...) line, it counts one loop pass and the result is correct. But when there is (while...) line included, all code below is ignored.
I've rebuilt above code to something like this:
(defn power [nth result]
(* result (- nth 1))
)
(defn absolute [x]
(if (>= x 0) x (- x))
)
(defn is-good? [prev-result result]
(< (absolute (- prev-result result)) 0.01)
)
(defn improve [nth result temp]
(* (/ 1.0 nth) (+ (* (- nth 1) result) (/ result temp)))
)
(defn count-root [nth number]
(loop [result number
prev-result result
temp (power nth result)]
(let [next-result (* (/ 1.0 nth) (+ (* (- nth 1) result) (/ number temp)))])
(if (is-good? (result next-result)) result (recur next-result)))
)
(defn root [nth number]
(if (<= number 0) "Root doesn't exists" (count-root nth number))
)
But compiler throw error that next-result cannot be resolved...What's going on now?
There are a number of issues with this code. To provide you with a working example let's rewrite the root and count_root functions:
(defn power [nth result]
(* result (- nth 1)))
(defn count-root [nth guess]
(loop [result guess
last_result guess
temp (power nth result)]
(cond
(> (Math/abs (- result last_result)) 0.01)
(let [next-result (* (/ 1.0 nth) (+ (* (- nth 1) result) (/ guess temp)))]
(recur next-result
result
(power nth next-result)))
:else
(str "Result: " result))))
(defn root [nth guess]
(cond
(<= guess 0) "Root doesn't exists"
:else (count-root nth guess)))
Let's look at what was changed here, and try to explain it.
First, in the count-root function:
I suggest that you not use underscores in names. The most commonly followed Clojure convention is to use dashes to separate elements of function and definition names.
To perform a loop-with-definitions, use the loop construct to define where the loop begins, along with any needed definitions, and use recur to perform a recursive invocation of the loop with new values specified for the definitions. Note that if all the necessary definitions were given as parameters to the function count-root then no loop would be necessary and the recursion could go back to the start of the function.
I recommend that you get in the habit of using cond instead of if. The if function looks a whole lot like an if statement in other languages, and that gets us (well, OK, ME :-) into difficulties from time to time. The issue is that when you use if you have to remember to specify BOTH the "true" and "false" actions, because an if form can't be "short-cut". That is, if this was so in "other" languages you'd always have to write:
IF something
THEN true-stuff
ELSE false-stuff
ENDIF
or, in more Clojurist fashion
(if something
true-stuff
false-stuff)
In Clojure you shouldn't write
(if something
true-stuff)
because I've found that this doesn't work correctly. If you invoke the if function and specify only the true argument, as you would often do in "other" programming languages, it will compile and run, but you'll get odd results, things that can't happen will happen, and generally you'll get confused until you realize you've got an if without a "false" half or something like that. Save yourself some trouble - use cond instead of if.
4. I suggest using Math/abs instead of defining your own absolute function.
5. Use a let form to define temporary values where you won't need to loop inside the form. Here I've defined next-result as a temporary value which I'll use in the next form.
6. Use recur to tail-recursively "jump" to the next-earliest recursion point. Here the next-earliest recursion point is the loop form. If we didn't have this loop form, or some other recursion point, the function definition for count-root would serve as a recursion point. When
Next, in the root function:
the definition of the function was incorrect in the original version. I've cleaned it up here such that the function is defined with two arguments, nth and guess.
EDIT
In the original version of count_root you used the while function. Using while requires that its argument has to change, which means that it will have to deal in some manner or other with an atom; that is, it has to deal with a modifiable variable. Most of the time in Clojure, what are usually thought of as "variables" can't actually be changed. This is intentional. Clojure was intended from the outset to be used in writing multi-threaded applications, where coordinating changes to "variables" becomes a significant concern. If "variables" can't actually be changed, the need for that coordination (by means of such constructs as semaphores, critical sections, and etc) disappears. Thus, definitions of values (they're not really "variables" if they can't vary or change) are constant by default. Now, any "real" program has a need for values which change over time, and Clojure provides for such needs - but it's not the default. You must explicitly think about what needs to be modified, and you need to access those modifiable values differently.
Now, an observation for you. You may find that programming in Clojure, or in any language which makes you do things in a different manner than what you're accustomed to, will at first feel very strange, and perhaps even uncomfortably difficult. I know that's what I've gone through when learning new-to-me systems. Quite often, our thought processes get into "ruts", and anything that forces us out of those "ruts" makes us uncomfortable. But sometimes working your way through that "uncomfortable" period ends up with you having learned something valuable. If you stick with Clojure you'll learn a different way to think about software - and having multiple viewpoints from which to consider a problem is in itself a good thing.
When you're learning something new a good guide is helpful. I suggest Clojure For The Brave And True, which has the advantage that it's online edition is free-like-beer.
Best of luck.
I am trying to learn functional programming in Clojure. Many functional programming tutorials begin with the benefits of immutability, and one common example is the loop variable in imperative-style languages. In that respect, how does Clojure's loop-recur differ from them? For example:
(defn factorial [n]
(loop [curr-n n curr-f 1]
(if (= curr-n 1)
curr-f
(recur (dec curr-n) (* curr-f curr-n)))))
Isn't curr-n and curr-f mutable values similar to loop variable in imperative-style languages?
As Thumbnail points out, using loop-recur in clojure has the same form and effect as a classic recursive function call. The only reason it exists is that it is much more efficient than pure recursion.
Since the recur can only occur in the tail position, you are guarenteed that the loop "variables" will never be needed again. Thus, you don't need to preserve them on the stack, so no stack is used (unlike nested function calls, recursive or not). The end result is that it looks & acts very similarly to an imperative loop in other languages.
The improvement compared to a Java-style for loop is that all "variables" are limited to "changing" only when initialized in the loop expression and when updated in the recur expression. No changes to the vars can occur in the body of the loop, nor anywhere else (such as embedded function calls which could mutate the loop vars in Java).
Because of these restrictions on where the "loop vars" can be mutated/updated, there are reduced opportunities for a bug to change them unintentionally. The cost of the restrictions is that the loop is not as flexible as a traditional Java-style loop.
As with anything, it is up to you to decide when this cost-benefit tradeoff is a better choice than the other cost-benefit tradeoffs available. If you want a pure Java-style loop, it is easy to use a clojure atom to simulate a Java variable:
; Let clojure figure out the list of numbers & accumulate the result
(defn fact-range [n]
(apply * (range 1 (inc n))))
(spyx (fact-range 4))
; Classical recursion uses the stack to figure out the list of
; numbers & accumulate the intermediate results
(defn fact-recur [n]
(if (< 1 n)
(* n (fact-recur (dec n)))
1))
(spyx (fact-recur 4))
; Let clojure figure out the list of numbers; we accumulate the result
(defn fact-doseq [n]
(let [result (atom 1) ]
(doseq [i (range 1 (inc n)) ]
(swap! result * i))
#result ))
(spyx (fact-doseq 4))
; We figure out the list of numbers & accumulate the result
(defn fact-mutable [n]
(let [result (atom 1)
cnt (atom 1) ]
(while (<= #cnt n)
(swap! result * #cnt)
(swap! cnt inc))
#result))
(spyx (fact-mutable 4))
(fact-range 4) => 24
(fact-recur 4) => 24
(fact-doseq 4) => 24
(fact-mutable 4) => 24
Even in the last case where we use atoms to emulate mutable variables in Java, at least each place we mutate something it is visibly marked with the swap! function, which makes it harder to miss "accidental" mutation.
P.S. If you wish to use spyx it is in the Tupelo library
Isn't curr-n and curr-f mutable values similar to loop variable in
imperative-style languages?
No. You can always rewrite a loop-recur as a recursive function call. For example, your factorial function can be rewritten ...
(defn factorial [n]
((fn whatever [curr-n curr-f]
(if (= curr-n 1)
curr-f
(whatever (dec curr-n) (* curr-f curr-n))))
n 1))
This is slower and subject to stack-overflow on big numbers.
When it comes to the moment of incarnating the call, recur overwrites the one-and-only stack frame instead of allocating a new one. This works only if the caller's stack frame is never thereafter referred to - what we call tail position.
loop is syntactic sugar. I doubt that it is a macro, but it could be. Except that the earlier bindings should be available to the later ones, as in a let, though I think this issue is currently moot.
I was writing the code that does same thing as 'reduce' function in clojure
ex) (reduce + [1 2 3 4]) = (+ (+ (+ 1 2) 3) 4).
(defn new-reduce [fn coll]
(def answer (get coll 0))
(loop [i 1]
(when (< i (count coll))
(def answer (fn answer (get coll i)))
(recur (inc i))))
answer)
In my code I used the global variable, and for me it was easier for me to understand that way. Apparently, people saying it is better to change the global variable to local variable such as let. So I tried..
(defn new-reduce [fn coll]
(let [answer (get coll 0)]
(loop [i 1]
(when (< i (count coll))
(fn answer (get coll i))
(recur (inc i))))))
To be honest, I am not really familiar with let function and even though I try really simple code, it did not work. Can somebody help me to fix this code and help me to understand how the let (local variables) really work ? Thank you. (p.s. really simple code that has loop inside let function will be great also).
Let does not create local "variables", it gives names to values, and does not let you change them after giving them the name. So introducing a let is more like defining a local constant.
First I'll just add another item into the loop expression to store the value so far. Each time through the loop we will update this to incorporate the new information. This pattern is very common. I also needed to add a new argument to the function to hold the initial state (reduce as a concept needs this)
user> (defn new-reduce [function initial-value coll]
(loop [i 0
answer-so-far initial-value]
(if (< i (count coll))
(recur (inc i) (function answer-so-far (get coll i)))
answer-so-far)))
user> (new-reduce + 0 [1 2 3])
6
This moves the "global variable" into a name that is local to the loop expression can be updated once per loop at the time you jump back up to the top. Once it reaches the end of the loop it will return the answer thus far as the return value of the function rather than recurring again. Building your own reduce function is a great way to build understanding on how to use reduce effectively.
There is a function that introduces true local variables, though it is very nearly never used in Clojure code. It's only really used in the runtime bootstap code. If you are really curious read up on binding very carefully.
Here's a simple, functional solution that replicates the behavior of the standard reduce:
(defn reduce
([f [head & tail :as coll]]
(if (empty? coll)
(f)
(reduce f head tail)))
([f init [head & tail :as coll]]
(cond
(reduced? init) #init
(empty? coll) init
:else (recur f (f init head) tail))))
There is no loop here, because the function itself serves as the recursion point. I personally find it easier to think about this recursively, but since we're using tail recursion with recur, you can think about it imperatively/iteratively as well:
If init is a signal to return early then return its value, otherwise go to step 2
If coll is empty then return init, otherwise go to step 3
Set init to the result of calling f with init and the first item of coll as arguments
Set coll to a sequence of all items in coll except the first one
Go to step 1
Actually, under the hood (with tail-call optimization and such), that's essentially what's really going on. I'd encourage you to compare these two expressions of the same solution to get a better idea of how to go about solving these sorts of problems in Clojure.
Preface
Firstly, I'm new to Clojure and programming, so I thought I'd try to create a function that solves a non-trivial equation using my natural instincts. What resulted is the desire to find a square root.
The question
What's the most efficient way to stop my square-n-map-maker function from iterating past a certain point? I'd like to fix square-n-map-maker so that I can comment out the square-maker function which provides me with the results and format I currently want to see but not the ability to recall the square-root answer (insofar as I know).
I.e. I want it to stop when it is greater than or equal to my input value
My initial thought was that instead of a keyword list, I would want it to be a map. But I'm having a very difficult time getting my function to give me a map. The whole reason I wanted a map where one member of a pair is n and another is n^2 so that I could extract the actual square root from it and it give it back to the user as the answer.
Any ideas on the best way to accomplish this? (below is the function I want to fix)
;; attempting to make a map so that I can comb over the
;; map later and recall a value that meets
;; my criteria to terminate and return result if (<= temp-var input)
(defn square-n-map-maker [input] (for [temp-var {remainder-culler input}]
(map list(temp-var) (* temp-var temp-var))
)
)
(square-n-map-maker 100) => clojure.lang.ArityException: Wrong number of args (0) passed to: MapEntry
AFn.java:437 clojure.lang.AFn.throwArity
AFn.java:35 clojure.lang.AFn.invoke
/Users/dbennett/Dropbox/Clojure Files/SquareRoot.clj:40 sqrt-range-high-end/square-n-map-maker[fn]
The following is the rest of my code
;; My idea on the best way to find a square root is simple.
;; If I want to find the square root of n, divide n in half
;; Then find all numbers in 0...n that return only a remainder of 0.
;; Then find the number that can divide by itself with a result of 1.
;; First I'll develop a function that works with evens and then odds
(defn sqrt-range-high-end [input] (/ input 2))
(sqrt-range-high-end 100) => 50
(defn make-sqrt-range [input] (range (sqrt-range-high-end (+ 1 input))))
(make-sqrt-range 100) =>(0 1 2 3 4 5 6 ... 50)
(defn zero-culler [input] (remove zero? (make-sqrt-range input)))
(zero-culler 100) =>(1 2 3 4 5 6 ... 50)
(defn odd-culler [input] (remove odd? (zero-culler input)))
(odd-culler 100) => (2 4 6 8 10...50)
(defn even-culler [input] (remove even? (zero-culler input)))
(even-culler 100) => (1 3 5 7...49)
(defn remainder-culler [input] (filter #(zero? (rem input %)) (odd-culler input)))
(remainder-culler 100) => (2 4 6 12 18)
(defn square-maker [input] (for [temp-var (remainder-culler input)]
(list (keyword (str
temp-var" "
(* temp-var temp-var)
)
)
)
)
(square-maker 100) => ((:2 4) (:4 16) (:10 100) (:20 400) (:50 2500))
Read the Error Messages!
You're getting a little ahead of yourself! Your bug has nothing to do with getting for to stop "looping."
(defn square-n-map-maker [input] (for [temp-var {remainder-culler input}]
(map list(temp-var) (* temp-var temp-var))))
(square-n-map-maker 100) => clojure.lang.ArityException: Wrong number of args (0) passed to: MapEntry
AFn.java:437 clojure.lang.AFn.throwArity
AFn.java:35 clojure.lang.AFn.invoke
Pay attention to error messages. They are your friend. In this case, it's telling you that you are passing the wrong number of arguments to MapEntry (search for IPersistentMap). What is that?
{} creates a map literal. {:key :value :key2 :value2} is a map. Maps can be used as if they were functions:
> ({:key :value} :key)
:value
That accesses the entry in the map associated with key. Now, you created a map in your first line: {remainder-culler input}. You just mapped the function remainder-culler to the input. If you grab an item out of the map, it's a MapEntry. Every MapEntry can be used as a function, accepting an index as an argument, just like a Vector:
> ([:a :b :c :d] 2)
:c
Your for is iterating over all MapEntries in {remainder-culler input}, but there's only one: [remainder-culler input]. This MapEntry gets assigned to temp-var.
Then in the next line, you wrapped this map in parentheses: (temp-var). This forms an S-expression, and expressions are evaluated assuming that the first item in the expression is a function/procedure. So it expects an index (valid indices here would be 0 and 1). But you pass no arguments to temp-var. Therefore: clojure.lang.ArityException: Wrong number of args.
Also, note that map is not a constructor for a Map.
Constructing a map
Now, on to your problem. Your square-maker is returning a list nicely formatted for a map, but it's made up of nested lists.
Try this:
(apply hash-map (flatten (square-maker 100)))
Read this page and this page to see how it works.
If you don't mind switching the order of the keys and values, you can use the group-by that I mentioned before:
(defn square-maker [input]
(group-by #(* % %) (remainder-culler input)))
(square-maker 100) => {4 [2], 16 [4], 100 [10], 400 [20], 2500 [50]}
Then you can snag the value you need like so: (first ((square-maker 100) 100)). This uses the map-as-function feature I mentioned above.
Loops
If you really want to stick with the intuitive looping concept, I would use loop, not for. for is lazy, which means that there is neither means nor reason (if you use it correctly) to "stop" it -- it doesn't actually do any work unless you ask for a value from it, and it only does the work it must to give you the value you asked for.
(defn square-root [input]
(let [candidates (remainder-culler input)]
(loop [i 0]
(if (= input (#(* % %) (nth candidates i)))
(nth candidates i)
(recur (inc i))))))
The embedded if determines when the looping will cease.
But notice that loop only returns its final value (acquaint yourself with loop's documentation if that sentence doesn't make sense to you). If you want to build up a hash-map for later analysis, you'd have to do something like (loop [i 0, mymap {}] .... But why analyze later if it can be done right away? :-)
Now, that's a pretty fragile square-root function, and it wouldn't be too hard to get it caught in an infinite loop (feed it 101). I leave it as an exercise to you to fix it (this is all an academic exercise anyway, right?).
I hope that helps you along your way, once again. I think this is a great problem for learning a new language. I should say, for the record, though, that once you are feeling comfortable with your solution, you should search for other Clojure solutions to the problem and see if you can understand how they work -- this one may be "intuitive," but it is not well-suited to Clojure's tools and capabilities. Looking at other solutions will help you grasp Clojure's world a bit better.
For more reading:
Imperative looping with side-effects.
How to position recur with loop
The handy into
Finally, this "not constructive" list of common Clojure mistakes
for is not a loop, and it's not iterating. It lazily creates a list comprehension, and it only realizes values when required (in this case, when the repl tries to print the result of the evaluation). There are two usual ways to do what you want: one is to wrap square-maker in
(first (filter some-predicate (square-maker number))) to obtain the first element in the sequence that complies with some-predicate. E.g.
(first (filter #(and (odd? %) (< 50 %)) (range)))
=> 51
The above won't realize the infinite range, obviously.
The other one is not to use a list comprehension and do it in a more imperative way: run an actual loop with a termination condition (see loop and recur).
Example:
(loop [x 0]
(if (and (odd? x) (> x 50))
x
(recur (inc x))))
I am stuck in a Clojure loop and need help to get out.
I first want to define a vector
(def lawl [1 2 3 4 5])
I do
(get lawl 0)
And get "1" in return. Now, I want a loop that get each number in the vector, so I do:
(loop [i 0]
(if (< i (count lawl))
(get lawl i)
(recur (inc i))))
In my mind this is supposed to set the value of i to nil, then if i is lower then the count of the lawl vector, it should get each lawl value and then increase the i variable with 1 and try again, getting the next value in the vector.
However, this does not work and I have spent some time trying to get it working and are totally stuck, would appreciate some help. I have also tried changing "if" to "when" with the same result, it doesn't provide any data the REPL just enters a new line and blink.
EDIT: Fixed the recur.
You need to consider what is "to get each lawl value" supposed to mean. Your get call does indeed "get" the appropriate value, but since you never do anything with it, it is simply discarded; Bozhidar's suggestion to add a println is a good one and will allow you to see that the loop does indeed access all the elements of lawl (just replace (get ...) with (println (get ...)), after fixing the (inc) => (inc i) thing Bozhidar mentioned also).
That said, if you simply want to do something with each number in turn, loop / recur is not a good way to go about it at all. Here are some others:
;;; do some side-effecty thing to each number in turn:
(dotimes [i (count lawl)]
(println (str i ": " (lawl i)))) ; you don't really need the get either
;; doseq is more general than dotimes, but doesn't give you equally immediate
;; acess to the index
(doseq [n lawl]
(println n))
;;; transform the lawl vector somehow and return the result:
; produce a seq of the elements of lawl transformed by some function
(map inc lawl)
; or if you want the result to be a vector too...
(vec (map inc lawl))
; produce a seq of the even members of lawl multiplied by 3
(for [n lawl
:when (even? n)]
(* n 3))
This is just the beginning. For a good tour around Clojure's standard library, see the Clojure -- Functional Programming for the JVM article by Mark Volkmann.
(recur (inc)) should be (recur (inc i))
Even so this code will just return 1 in the end, if you want a listing of the number you might add a print expression :-) Btw index based loops are not needed at all in scenarios such as this.
(loop [list [1 2 3 4 5] ]
(if (empty? list)
(println "done")
(do
(println (first list))
(recur (rest list)))))
OK, I'm about 10-1/2 years too late on this, but here goes:
The problem here is a pretty common misunderstanding of how the arguments to the if function are used. if takes three arguments - the condition/predicate, the code to be executed if the predicate is true, and the code to be executed if the predicate is false. In this case both of the true and false cases are supplied. Perhaps if we fix the indentation and add some appropriate comments we'll be able to see what's happening more easily:
(loop [i 0]
(if (< i (count lawl))
(get lawl i) ; then
(recur (inc i)))) ; else
So the problem is not that the code gets "stuck" in the loop - the problem is that the recur form is never executed. Here's how the execution flows:
The loop form is entered; i is set to 0.
The if form is entered.
The predicate form is executed and found to be true.
The code for the then branch of the if is executed, returning 1.
Execution then falls out the bottom of the loop form.
Right now I hear people screaming "Wait! WHAT?!?". Yep - in an if form you can only have a single form in the "then" and "else" branches. "But...THAT'S STUPID!" I hear you say. Well...not really. You just need to know how to work with it. There's a way to group multiple forms together in Clojure into a single form, and that's done by using do. If we want to group (get lawl i) and (recur... together we could write it as
(loop [i 0]
(if (< i (count lawl))
(do
(get lawl i) ; then
(recur (inc i))
)
)
)
As you can see, we have no "else" branch on this if form - instead, the (get... and (recur... forms are grouped together by the (do, so they execute one after the other. So after recurring its way through the lawl vector the above snippet returns nil, which is kind of ugly. So let's have it return something more informative:
(loop [i 0]
(if (< i (count lawl))
(do
(get lawl i) ; then
(recur (inc i)))
(str "All done i=" i) ; else
)
)
Now our else branch returns "All done i=5".