The usage of lazy-sequences in clojure - clojure

I am wondering that lazy-seq returns a finite list or infinite list. There is an example,
(defn integers [n]
(cons n (lazy-seq (integers (inc n)))))
when I run like
(first integers 10)
or
(take 5 (integers 10))
the results are 10 and (10 11 12 13 14)
. However, when I run
(integers 10)
the process cannot print anything and cannot continue. Is there anyone who can tell me why and the usage of laza-seq. Thank you so much!

When you say that you are running
(integers 10)
what you're really doing is something like this:
user> (integers 10)
In other words, you're evaluating that form in a REPL (read-eval-print-loop).
The "read" step will convert from the string "(integers 10)" to the list (integers 10). Pretty straightforward.
The "eval" step will look up integers in the surrounding context, see that it is bound to a function, and evaluate that function with the parameter 10:
(cons 10 (lazy-seq (integers (inc 10))))
Since a lazy-seq isn't realized until it needs to be, simply evaluating this form will result in a clojure.lang.Cons object whose first element is 10 and whose rest element is a clojure.lang.LazySeq that hasn't been realized yet.
You can verify this with a simple def (no infinite hang):
user> (def my-integers (integers 10))
;=> #'user/my-integers
In the final "print" step, Clojure basically tries to convert the result of the form it just evaluated to a string, then print that string to the console. For a finite sequence, this is easy. It just keeps taking items from the sequence until there aren't any left, converts each item to a string, separates them by spaces, sticks some parentheses on the ends, and voilà:
user> (take 5 (integers 10))
;=> (10 11 12 13 14)
But as you've defined integers, there won't be a point at which there are no items left (well, at least until you get an integer overflow, but that could be remedied by using inc' instead of just inc). So Clojure is able to read and evaluate your input just fine, but it simply cannot print all the items of an infinite result.

When you try to print an unbounded lazy sequence, it will be completely realized, unless you limit *print-length*.

The lazy-seq macro never constructs a list, finite or infinite. It constructs a clojure.lang.LazySeq object. This is a nominal sequence that wraps a function of no arguments (commonly called a thunk) that evaluates to the actual sequence when called; but it isn't called until it has to be, and that's the purpose of the mechanism: to delay evaluating the actual sequence.
So you can pass endless sequences around as evaluated LazySeq objects, provided you never realise them. Your evaluation at the REPL invokes realisation, an endless process.

It's not returning anything because your integers function creates an infinite loop.
(defn integers [n]
(do (prn n)
(cons n (lazy-seq (integers (inc n))))))
Call it with (integers 10) and you'll see it counting forever.

Related

Clojure - Creating a No Divisors function

I am really struggling to do this one function. The function is as follows
Write a function named no-divisors? which takes an input n. The function should return true if none of the numbers between 2 and √𝑛 divide n, and false otherwise. The function should use both your get-divisors function and your divides? function.
Hint: you will probably need to wrap the divides? function in an anonymous function so that you can pass in the value of n.
This is my get-divisors function:
(defn get-divisors [n]
(str (range 2 (inc (Math/floor (Math/sqrt n))))))
This is my divides? function:
(defn divide [a b]
(zero? (mod a b)))
I have tried to create a method in order to try and complete this task, however, to no luck.
This is what I tried:
(defn no-divisors [n]
divide(n (get-divisors n)))
And I received the output:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/x (form-init5516475059937019181.clj:16)`
I have an idea in mind which I would like to share of how I could create this task, however, since this is my first time using Clojure I am not too sure of to implement this function or if it is even possible. I am extremely sorry that I have mixed syntax, it's just I have never used Clojure up until this point, but here is my draft/blueprint:
(defn no-divisors [n]
resultsArray = []
def results((get-divisors n))
for results in get-divisors
resultsArray.append(results)
for i=results[0]; i< results.count; i++
divide(n i)
)
I maybe on the right path or probably (most likely) completely wrong. I am grateful and thankful for any/all help I can possibly receive. Just a side note, both my get-divisors and divides? functions work flawlessly.
Firstly, you can't just put parentheses anywhere in the code like you can in other languages. They mean something specific in Clojure (and other lisps) when evaluating code, namely the first thing in the list is a verb; a function to call. Nested brackets mean repeated calls to the result of a function. So if you have a function alice that returns a function, like this (stay with me, I'm trying to explain the error you're getting ;) ):
(defn alice []
(fn [] :bob))
then you can call it like this
(alice) ;; => #function[user/alice/fn--6930]
and it will return the function that you have created inside, and you can call that anonymous function like this:
((alice)) ;; => :bob
to actually get the result of that function. Apologies if this is a bit much off the bat, but the parens have meaning, and that's the cause of the error you're getting:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
This means that you're trying to call a number as a function. clojure.lang.IFn is Clojure's way of saying "the thing I was expecting was something that I could call as a function". By java.lang.Long, Clojure's mean's "number". ClassCastException means I saw one thing and was expecting the other. So really, what this error is trying to say is you wrote an open paren ( and followed that up with something named a number and not a function. That seems very much like you've written divide(n (get-divisors n)) instead of (divide n (get-divisors n)), because when evaluating divide(n (get-divisors n)) it first tries to evaluate divide and discovers this is a function, but doesn't try and call it. Then it looks at the next form (n (get-divisors n)) and tries asks what n is, and finds it's a number, which can't be called as a function. Make sense?
In your pseudo-code, you have an array that you append data to to collect the results while iterate through a loop to build the results. This is a very imperative way of approaching the problem, and not really the way Clojure is trying to encourage you to solve problems. Clojure tends to learn towards a more data focused way of solving the problem. One way to think about the problem is the way in which it's phrased in English. Given a number n, take all the numbers less than the square-root of it, and check if they divide into n. If that list is empty return true, otherwise return false. In Clojure you could write:
(defn divide? [a b]
(zero? (mod a b)))
(defn no-divisors? [n]
(->> (range 2 n)
(take-while #(< (* % %) n))
(filter (partial divide? n))
empty?))
Here, we use the ->> macro to take a lazy sequence of numbers between 2 and n, then limit that sequence using take-while to only the ones where the square of the number is less than n. Then we check that each one divides into n using the divide? function, and finally ask if the list is empty?. Since Clojure's sequences are lazy, no actual computation occurs until we try to evaluate the result using empty? which will stop when it reaches an element in the sequence. This makes it more efficient than actually traversing the whole list for large values of n.
Hope this helps.
P.S. I'm not sure your implementation of get-divisors is quite correct.
You must test your work as you go along. Let's look at your get-divisors function:
(defn get-divisors [n]
(str (range 2 (inc (Math/floor (Math/sqrt n))))))
Let's try it:
=> (get-divisors 20)
"(2 3 4)"
This is a string of characters, not the collection of numbers it ought to be. Remove the damaging str call:
(defn get-divisors [n]
(range 2 (inc (Math/floor (Math/sqrt n)))))
Now
=> (get-divisors 20)
(2 3 4)
Good. And an edge case, just to make sure:
=> (get-divisors 16)
(2 3 4)
Good again! We can use this function with some confidence.
Now we want to find out whether something is true of none of this collection. There's a handy function called not-any? that does this. For example,
=> (not-any? even? (range 1 100 2))
true
What we want to determine is whether none of the potential divisors of n actually divide n. So the shape of the function might be ...

conj not updating vector inside of loop

I'm trying to teach myself clojure. This is just supposed to be a simple function that takes a value and adds each of its preceding values together and returns the sum of those values.
The problem is that while in the loop function, numbers isn't modified with conj like I would expect it to be - numbers just stays an empty vector. Why is that?
(defn sum
[number]
(do (def numbers (vector))
(loop [iteration number]
(if (> iteration 0)
(conj numbers iteration)
(recur (dec iteration))))
(map + numbers)))
A few hints (not an answer):
Don't use do.
Use let, not def, inside a function.
Use the result returned by conj, or it does nothing.
Pass the result back through the recur.
Besides, your sum function ignores its number argument.
I think you're getting confused between number (the number of things you want to add) and numbers (the things themselves). Remember,
vectors (and other data structures) know how long they are; and
they are often, as in what follows, quickly and concisely dealt with as
sequences, using first and rest instead of indexing.
The code pattern you are searching for is so common that it's been captured in a standard higher order function called reduce. You can get the effect you want by ...
(defn sum [coll] (reduce + coll))
or
(def sum (partial reduce +))
For example,
(sum (range 10))
;45
Somewhat off-topic:
If I were you, and I once was, I'd go through some of the fine clojure tutorials available on the web, with a REPL to hand. You could start looking here or here. Enjoy!
Your function does not work fro three main reasons :
you assumed that conj will update the value of variable numbers (but in fact it returns a copy of it bound to another name)
you used loop/recur pattern like in classical imperative style (it does not work the same)
Bad use of map
Thumbnail gave the idiomatic answer but here are correct use of your pattern :
(defn sum
[number]
(loop [iteration number
numbers []]
(if (<= iteration 0)
(reduce + numbers)
(recur (dec iteration) (conj numbers iteration)))))
The loop/recur pattern executes its body with updated values passed by recur.
Recur updates values listed after the loop. Here, while iteration is strictly positive, recur is executed. However, when iteration reaches 0, (reduce + numbers) (actual sum) is executed on the result of multiple recursions and so the recursion ends.

Common Lisp function for "Reduce and Return Intermediate Results as Sequence"

In Clojure, there is a higher-order function reductions, which you would use with arguments similar to reduce and will return a sequence containing all intermediate results.
Is there an equivalent in Common Lisp? I was unable to find any reference to it online, including the various books/articles on https://common-lisp.net/tutorials/ but given Lisp's heritage as a family of List Processing languages I imagined a list->list function like reductions will exist across dialects.
There is no standard function for it. You could define one easily:
(defun reductions (function sequence &rest args
&key key from-end (start 0) end initial-value)
(declare (ignore key from-end start end initial-value))
"Return a list of intermediate values from reducing SEQUENCE with FUNCTION."
(let* ((reductions (list))
(result (apply #'reduce
(lambda (&rest arguments)
(let ((result (apply function arguments)))
(push result reductions)
result))
sequence
args)))
(values (or (nreverse reductions)
(list result))
result)))
(reductions #'+ '(1 2 3 4 5 6 7 8 9 10) :initial-value 0)
;=> (1 3 6 10 15 21 28 36 45 55)
Edit: Use APPLY with &REST ARGS instead of calling REDUCE directly. Some implementation of REDUCE might not work if NILs are supplied for keyword arguments.
Edit2: The reducing function can be called with 0 or 2 arguments.
Edit3: When REDUCE is called with a list of only one element, the only element is returned as is. The reducing function is not called at all, which means the list of reductions would be empty. I added an OR to return the final result wrapped in a list in that situation (to match Clojures behaviour). I also changed the code to return the final result as a second return value (might be useful and "why not?").

Will last of a lazy seq evaluate all elements in clojure?

Let's assume that we have an expensive computation expensive. If we consider that map produces a lazy seq, then does the following evaluate the function expensive for all elements of the mapped collection or only for the last one?
(last
(map expensive '(1 2 3 4 5)))
I.e. does this evaluate expensive for all the values 1..5 or does it only evaluate (expensive 5)?
The whole collection will be evaluated. A simple test answers your question.
=> (defn exp [x]
(println "ran")
x)
=> (last
(map exp '(1 2 3 4 5)))
ran
ran
ran
ran
ran
5
There is no random access for lazy sequences in Clojure.
In a way, you can consider them equivalent to singly linked lists - you always have the current element and a function to get the next one.
So, even if you just call (last some-seq) it will evaluate all the sequence elements even if the sequence is lazy.If the sequence is finite and reasonably small (and if you don't hold the head of the sequence in a reference) it's fine when it comes to memory. As you noted, there is a problem with execution time that may occur if the function used to get the next element is expensive.
In that case, you can make a compromise so that you use a cheap function to walk all the way to the last element:
(last some-seq)
and then apply the function only on that result:
(expensive (last some-seq))
last will always force the evaluation of the lazy sequence - this is clearly necessary as it needs to find the end of the sequence, and hence needs to evaluate the lazy seq at every position.
If you want laziness in all the idividual elements, one way is to create a sequence of lazy sequences as follows:
(defn expensive [n]
(do
(println "Called expensive function on " n)
(* n n)))
(def lzy (map #(lazy-seq [(expensive %)]) '(1 2 3 4 5)))
(last lzy)
=> Called expensive function on 5
=> (25)
Note that last in this case still forces the evaluation of the top-level lazy sequence, but doesn't force the evaluation of the lazy sequences contained within it, apart from the last one that we pull out (because it gets printed by the REPL).

Clojure: reduce, reductions and infinite lists

Reduce and reductions let you accumulate state over a sequence.
Each element in the sequence will modify the accumulated state until
the end of the sequence is reached.
What are implications of calling reduce or reductions on an infinite list?
(def c (cycle [0]))
(reduce + c)
This will quickly throw an OutOfMemoryError. By the way, (reduce + (cycle [0])) does not throw an OutOfMemoryError (at least not for the time I waited). It never returns. Not sure why.
Is there any way to call reduce or reductions on an infinite list in a way that makes sense? The problem I see in the above example, is that eventually the evaluated part of the list becomes large enough to overflow the heap. Maybe an infinite list is not the right paradigm. Reducing over a generator, IO stream, or an event stream would make more sense. The value should not be kept after it's evaluated and used to modify the state.
It will never return because reduce takes a sequence and a function and applies the function until the input sequence is empty, only then can it know it has the final value.
Reduce on a truly infinite seq would not make a lot of sense unless it is producing a side effect like logging its progress.
In your first example you are first creating a var referencing an infinite sequence.
(def c (cycle [0]))
Then you are passing the contents of the var c to reduce which starts reading elements to update its state.
(reduce + c)
These elements can't be garbage collected because the var c holds a reference to the first of them, which in turn holds a reference to the second and so on. Eventually it reads as many as there is space in the heap and then OOM.
To keep from blowing the heap in your second example you are not keeping a reference to the data you have already used so the items on the seq returned by cycle are GCd as fast as they are produced and the accumulated result continues to get bigger. Eventually it would overflow a long and crash (clojure 1.3) or promote itself to a BigInteger and grow to the size of all the heap (clojure 1.2)
(reduce + (cycle [0]))
Arthur's answer is good as far as it goes, but it looks like he doesn't address your second question about reductions. reductions returns a lazy sequence of intermediate stages of what reduce would have returned if given a list only N elements long. So it's perfectly sensible to call reductions on an infinite list:
user=> (take 10 (reductions + (range)))
(0 1 3 6 10 15 21 28 36 45)
If you want to keep getting items from a list like an IO stream and keep state between runs, you cannot use doseq (without resorting to def's). Instead a good approach would be to use loop/recur this will allow you to avoid consuming too much stack space and will let you keep state, in your case:
(loop [c (cycle [0])]
(if (evaluate-some-condition (first c))
(do-something-with (first c) (recur (rest c)))
nil))
Of course compared to your case there is here a condition check to make sure we don't loop indefinitely.
As others have pointed out, it doesn't make sense to run reduce directly on an infinite sequence, since reduce is non-lazy and needs to consume the full sequence.
As an alternative for this kind of situation, here's a helpful function that reduces only the first n items in a sequence, implemented using recur for reasonable efficiency:
(defn counted-reduce
([n f s]
(counted-reduce (dec n) f (first s) (rest s) ))
([n f initial s]
(if (<= n 0)
initial
(recur (dec n) f (f initial (first s)) (rest s)))))
(counted-reduce 10000000 + (range))
=> 49999995000000