I'm learning Clojure and I've just started on Project Euler and I've run into a problem I cannot figure out. Here is my code:
(defn largest_prime_factor
[x]
(if (prime? x) x)
(loop [running x divider 2]
(if (= 0 (mod running divider))
(let [d (/ running divider)]
(if (prime? d)
d
(recur d 2)))
(recur x (inc divider)))))
(largest_prime_factor 12) ;works
(largest_prime_factor 49) ;works
(largest_prime_factor 147) ;Endless loop!
I realise that this might not be the most efficient way to find the largest prime factor but what I'm trying to figure out is why it gets stuck in a loop. Obviously I'm using loop-recur the wrong way but what am I doing wrong?
A couple of things
(defn largest_prime_factor
[x]
(if (prime? x) x) ; #1
(loop [running x divider 2]
(if (= 0 (mod running divider))
(let [d (/ running divider)]
(if (prime? d)
d
(recur d 2)))
(recur x (inc divider))))) ; #2
The extra closing parenthesis makes this a self-contained if without an else clause. This has no bearing on the infinite loop, but would give the wrong answer (1) for a prime input (unless you start your divider at 1 instead, in which case you can omit this initial test).
This line should recur with running rather than x, otherwise you have not factored out the divisor and the prime? test will ever after be false. This is why you wind up in an infinite loop.
(if (prime? x) x)
I think you mean
(if (prime? x) x
(loop [...
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 filter a list using the loop macro. If I do
(loop for x in (list 1 2 3 4) collect x)
I just get the same list back, which makes sense. However, I would like to do something like
(loop for x in (list 1 2 3 4) collect x if (evenp x))
and get (2 4) back, but that's not legal. For some reason, I can't find the appropriate syntax for this on other documentation. Is this possible?
The correct syntax is
(loop for x in (list ...) when (evenp x) collect x)
I'm still fairly new to clojure, but a pattern that I find myself using frequently in it goes something like this: I have some collections and I want to build a new collection, usually a hash-map, out of them with some filters or conditions. There are always a few ways to do this: using loop or using reduce combined with map/filter for example, but I would like to implement something more like the for macro, which has great syntax for controlling what gets evaluated in the loop. I'd like to produce a macro with syntax that goes like this:
(defmacro build
"(build sym init-val [bindings...] expr) evaluates the given expression expr
over the given bindings (treated identically to the bindings in a for macro);
the first time expr is evaluated the given symbol sym is bound to the init-val
and every subsequent time to the previous expr. The return value is the result
of the final expr. In essence, the build macro is to the reduce function
as the for macro is to the map function.
Example:
(build m {} [x (range 4), y (range 4) :when (not= x y)]
(assoc m x (conj (get m x #{}) y)))
;; ==> {0 #{1 3 2}, 1 #{0 3 2}, 2 #{0 1 3}, 3 #{0 1 2}}"
[sym init-val [& bindings] expr]
`(...))
Looking at the for code in clojure.core, it's pretty clear that I don't want to re-implement its syntax myself (even ignoring the ordinary perils of duplicating code), but coming up with for-like behavior in the above macro is a lot trickier than I initially expected. I eventually came up with the following, but I feel that (a) this probably isn't terribly performant and (b) there ought to be a better, still clojure-y, way to do this:
(defmacro build
[sym init-val bindings expr]
`(loop [result# ~init-val, s# (seq (for ~bindings (fn [~sym] ~expr)))]
(if s#
(recur ((first s#) result#) (next s#))
result#))
;; or `(reduce #(%2 %1) ~init-val (for ~bindings (fn [~sym] ~expr)))
My specific questions:
Is there a built-in clojure method or library that solves this already, perhaps more elegantly?
Can someone who is more familiar with clojure performance give me an idea of whether this implementation is problematic and whether/how much I should be worried about performance, assuming that I may use this macro very frequently for relatively large collections?
Is there any good reason that I should use the loop over the reduce version of the macro above, or vice versa?
Can anyone see a better implementation of the macro?
Your reduce version was also my first approach based on the problem statement. I think it's nice and straightforward and I'd expect it to work very well, particularly since for will produce a chunked seq that reduce will be able to iterate over very quickly.
for generates functions to do output generation anyway and I wouldn't expect the extra layer introduced by the build expansion to be particularly problematic. It may still be worthwhile to benchmark this version based on volatile! as well:
(defmacro build [sym init-val bindings expr]
`(let [box# (volatile! ~init-val)] ; AtomicReference would also work
(doseq ~bindings
(vreset! box# (let [~sym #box#] ~expr)))
#box#))
Criterium is great for benchmarking and will eliminate any performance-related guesswork.
I don't want to quite take your example code of your doc string since it's not idiomatic clojure. But taking plumbing.core's for-map, you can come up with a similar for-map-update:
(defn update!
"Like update but for transients."
([m k f] (assoc! m k (f (get m k))))
([m k f x1] (assoc! m k (f (get m k) x1)))
([m k f x1 x2] (assoc! m k (f (get m k) x1 x2)))
([m k f x1 x2 & xs] (assoc! m k (apply f (get m k) x1 x2 xs))))
(defmacro for-map-update
"Like 'for-map' for building maps but accepts a function as the value to build map values."
([seq-exprs key-expr val-expr]
`(for-map-update ~(gensym "m") ~seq-exprs ~key-expr ~val-expr))
([m-sym seq-exprs key-expr val-expr]
`(let [m-atom# (atom (transient {}))]
(doseq ~seq-exprs
(let [~m-sym #m-atom#]
(reset! m-atom# (update! ~m-sym ~key-expr ~val-expr))))
(persistent! #m-atom#))))
(for-map-update
[x (range 4)
y (range 4)
:when (not= x y)]
x (fnil #(conj % y) #{} ))
;; => {0 #{1 3 2}, 1 #{0 3 2}, 2 #{0 1 3}, 3 #{0 1 2}}
How do I translate the loop part of this working Common Lisp (SBCL v.1.2.3) code into Clojure (v.1.6)? I am a bit frustrated after working on it for some hours/days without results. Somewhere I don't get this functional orientation I suppose ...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Unconditional Entropy
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Probabilities
(setq list_occur_prob '()) ;; init
;; set probabilities for which we want to calculate the entropy
(setq list_occur_prob '(1/2 1/3 1/6)) ;;
;; Function to calculate the unconditional
;; entropy H = -sigma i=0,n (pi*log2(pi)
;; bits persymbol.
(setq entropy 0) ;; init
(setq entropy (loop for i in list_occur_prob
for y = (* (log_base2 i) i)
collect y
))
(setq entropy (* -1 (apply '+ entropy))) ;; change the sign
;; Print the unconditional entropy in bits per symbol.
(print entropy) ;; BTW, here the entropy is 1.4591479 bits per symbol.
Before we dive into the Clojure equivalent of the code, you should take some time to clean up the Common Lisp code. Using setqthe way you're doing it is considered bad style at best and can lead to undefined consequences at worst: setq is intended to assign values to variables, but your variables list_occur_proband entropy aren't defined (via defvar). In addition, this piece of code looks like you're assigning global variables (cf. defvar again), which are dynamic variables, which by convention should be marked with earmuffs, e.g. *entropy*.
However, for this small piece of code, you could just as well use local, non-dynamic variables, introduced via let like this (warning, I don't have any CL or Clojure environment handy):
(let ((list_occur_prob '(1/2 1/3 1/6)))
(loop for i in list_occur_prob
for y = (* (log_base 2 i) i)
collect y into acc
finally (return (* -1 (apply '+ acc)))))
There are ways to optimize the apply clause away into the loop:
(let ((list-occur-prob '(1/2 1/3 1/6)))
(- (loop for i in list-occur-prob
sum (* (log i 2) i))))
Now, Daniel Neal has shown you already a map/reduce based solution, here is one which is more closer to the original looping construct, using a recursive approach:
(defn ent-helper [probs acc]
(if (seq probs)
(recur (rest probs)
(conj acc (* (log_base 2 (first probs)) (first probs))))
acc))
(let [probs 1/2 1/3 1/6
acc (ent-helper probs [])]
(* -1 (apply + acc))
We're using conj instead of collect to gather the results into the accumulator. The call to ent-helper, which is essentially triggered for all values of probs via the recur recursion call, takes an (initially empty) second parameter in which the values build up so far are collected. If we've exhausted all probabilities, we simply return the collected values.
Again, summing up the values so far could be optimized into the loop, instead of mapping over the values.
They key operation you need is map which transforms a sequence using a function.
In the entropy example you gave, the following should work:
(def probabilities [1/2 1/3 1/6])
(defn log [base x]
(/ (Math/log x) (Math/log base)))
(defn entropy [probabilities]
(->> probabilities
(map #(* (log 2 %) %)) ; note - #(f %) is shorthand for (fn [x] (f x))
(reduce +)
(-)))
(entropy probabilities) ; => 1.459
When working with collections, the pipeline operator (->>) is often used
to clearly show a sequence of operations. I personally find it much easier to read than the nested bracket syntax, especially if there are lots of operations.
Here, we're first mapping the pi * log2(pi) function over the sequence,
and then summing it using (reduce +)
I would start with more functional Common Lisp code:
(- (reduce #'+
'(1/2 1/3 1/6)
:key (lambda (i)
(* (log i 2) i))))
You can write imperative code in Lisp, with lots of operations setting variable values, but it is not the best style.
Even a tight LOOP can look okay:
(- (loop for i in '(1/2 1/3 1/6)
sum (* (log i 2) i)))
I endorse the general flavor of schaueho's answer, but if you prefer you can get something closer to the "feel" of the looping approach with Clojure's for macro:
(apply - 0
(for [prob [1/2 1/3 1/6]]
(* (log prob 2) prob)))
I find this much easier to read than schaueho's version with manual recursion, and it also performs much better, in that it doesn't traverse the list twice, doesn't accumulate results into a temporary vector, and so on.
Note that (- (apply + xs)) is the same as (apply - 0 xs), although which one you find clearer is probably a matter of taste. Also, I'm assuming you already have a suitable log function defined elsewhere.
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".