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

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?").

Related

elisp how to apply a lambda to a list?

What I'm trying to do seems simple enough, and whatever's wrong must be a really dumb mistake, since I couldn't find other people getting the same error. I just want to apply a lambda to a list - the lambda here isn't what I actually want to do, but it gives the same error.
(apply
(lambda (arg)
(+ 5 arg)
)
(list 2 3 4)
)
When I try to run this, it tells me that I'm passing the lambda an invalid number of arguments. Do you have any advice?
apply calls the function once, passing it the list you've given as the arguments. I think you instead want to use mapcar:
M-: (mapcar (lambda (arg) (+ 5 arg)) (list 2 3 4)) RET
will return the list (7 8 9).
Just to make the problem a bit clearer:
This form
(apply
(lambda (arg)
(+ 5 arg))
(list 2 3 4))
is basically similar to
(funcall
(lambda (arg)
(+ 5 arg))
2
3
4)
In above we try to call a function with one parameter arg with three arguments.
Now if you want to pass more than one argument and receive it as a single list you would need a function with a &rest parameter:
(lambda (&rest args) ...)
You say
I just want to apply a lambda
This is not what you want. You want to map the function over a list. Which means calling the function for each element of the list and returning a new list with the results. This operation is called in Lisp mapping. See the answer by Stefan for an example.
Applying a function to a list would be: call the function with the arguments taken from the list.

The usage of lazy-sequences in 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.

Clojure seq returning function vs direct 'def' of seq

Newbie Clojure question. What are the pros and cons of the following two ways to implement/represent the Fibonacci sequence? (In particular, is there anything to completely rule out one or the other as a bad idea.)
(ns clxp.fib
(:gen-class))
; On the one hand, it seems more natural in code to have a function that
; returns 'a' Fibonacci sequence.
(defn fib-1
"Returns an infinite sequence of Fibonnaci numbers."
[]
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
; > (take 10 (fib-1))
; (0 1 1 2 3 5 8 13 21 34)
; On the other hand, it seems more mathematically natural to define 'the'
; Fibonacci sequence once, and just refer to it.
(def fib-2
"The infinite sequence of Fibonnaci numbers."
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
; > (take 10 fib-2)
; (0 1 1 2 3 5 8 13 21 34)
a) What are the pros and cons of these two approaches to defining an infinite sequence? (I am aware that this is a somewhat special case in that this particular sequence requires no args to be provided - unlike, say, an infinite sequence of multiples of 'n', which I believe would require the first approach, in order to specify the value of 'n'.)
b) Is there any over-arching reason to prefer one of these implementations to the other? (Memory consumption, applicability when used as an argument, etc.)
fib-2 is preferable in favor of time performance if its elements are looked up multiple times, because in a lazy seq they only need to be calculated one time.
Due to the global binding the seq is unlikely to ever become garbage collected, so if your program will step through a million fibonaccis to make some calculation once, even more so if it doesn't need to hold the seqs head, invoking fib-1 in a local context is preferable in favor of space performance.
It depends on your usage, and how critical it is not to have to recalculate fib seq multiple times. However, from my experiments below, I had issues with the def when using long sequences.
If you're going to be referring to a lot of elements, then you'll need to watch out for head retention, as Leon mentioned.
This can be illustrated as follows (these are extending a couple of examples from Clojure Programming):
(let [[t d] (split-with #(< % 10) (take 1e6 (fib-1)))]
[(count d) (count t)])
=> OutOfMemoryError Java heap space
(let [[t d] (split-with #(< % 10) (take 1e6 (fib-1)))]
[(count t) (count d)])
=> [7 999993]
Note, i had to change your implementation to use the initial vector [0 1N] to avoid ArithmeticException integer overflow when taking large sequences of fib numbers.
Interesting, changing to using fib-2 instead yields same OOM error for holding head case, but the non-head holding version breaks:
(let [[t d] (split-with #(< % 10) (take 1e6 fib-2))]
[(count t) (count d)])
=> [7 270036]
The latter figure should be 999993.
The reason for the OOM in both cases is as stated in Clojure Programming:
Since the last reference of t occurs before the processing of d, no
reference to the head of the range sequence is kept, and no memory
issues arise.

(list) in lazy-seq causes infinite recursion but (cons) does not

In attempting to understand lazy-seq, I came up with this example:
(defn zeroes []
(list 0 (lazy-seq (zeroes))))
(take 5 (zeroes)) ; too much recursion error
This however triggers a too much recursion error. Replacing (list) with (cons) fixes the problem, but I don't understand why:
(defn zeroes []
(cons 0 (lazy-seq (zeroes))))
(take 5 (zeroes)) ; returns (0 0 0 0 0)
My understanding of lazy-seq is that it immediately returns a lazy-seq instance but that its body is not evaluated until a call to first or rest on that instance. So I would think (zeroes) would just return a simple Cons of 0 and a LazySeq with a yet unevaluated body.
As an additional curiosity, I'm puzzled why this hangs the repl (because the repl attempts to print an infinite sequence) but doesn't trigger a 'too much recursion' error.
(defn zeroes []
(cons 0 (lazy-seq (zeroes))))
(zeroes) ; hangs the repl
(In case it's relevant, I'm trying these examples in the ClojureScript repl at http://himera.herokuapp.com/index.html.)
You asked two questions...
1) Why does using list instead of cons in the following code result in infinite recursion?
(defn zeroes []
(cons 0 (lazy-seq (zeroes))))
(take 5 (zeroes)) ; too much recursion error
The version using cons produces an infinite sequence of zeros, like this:
(0 0 0 0 ...)
If you use list instead, you produce a totally different result. You get an infinite nesting of lists of two elements each (with head=0 and tail=another list):
'(0 (0 (0 (0 (...))))
Since the top-level list only has two elements, you end up with the whole thing when you call (take 5). You get the "too much recursion" error when the REPL tries to print out these infinitely-nested lists.
Note that you could safely substitute the list* for cons. The list* function takes a variable number of arguments (as does list), but unlike list it assumes the last argument is a seq. This means (list* a b c d) is essentially just shorthand for (cons a (cons b (cons c d))). Since (list* a b) is basically the same as (cons a b), it follows that you can make the substitution in your code. In this case it probably wouldn't make much sense, but it's nice if you're cons-ing several items at the same time.
2) Why does the following diverge (hang) rather than throw a "too much recursion" error like we saw above?
(defn zeroes []
(cons 0 (lazy-seq (zeroes))))
(zeroes) ; hangs the repl
The zeros function produces a "flat" sequence of zeros (unlike the nested lists above). The REPL probably uses a tail-recursive function to evaluate each successive lazy element of the sequence. The tail-call optimization allows recursive functions to recur forever without blowing the call stack—so that's what happens. Recursive tail-calls in Clojure are denoted by the recur special form.

clojure partial clarification

I'm reading a book on clojure, and I came by an example that I dont fully understand..
Here is the code in repl:
user=> (repeatedly 10 (rand-int 10))
ClassCastException java.lang.Integer cannot be cast to clojure.lang.IFn clojure.core/repeatedly/fn--4705 (core.clj:4642)
user=> (repeatedly 10 (partial rand-int 10))
(5 0 5 5 2 4 8 8 0 0)
My question is:
why is the partial needed here, and how does that fit into partial definition,
and repeatedly definition & syntax. Partial ...
Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args.
So how does this fit in?
Partial is just an easier way of defining an anonymous function that fixes some of the arguments to a function and then passes the rest from the arguments to the created function.
In this case
user> (repeatedly 10 (partial rand-int 10))
(3 1 3 6 1 2 7 1 5 3)
is equivalent to:
user> (repeatedly 10 #(rand-int 10))
(9 5 6 0 0 5 7 6 9 6)
Partial is a misnomer here because partial is being used to fix in advance all the arguments (or rather the only one) to rand-int.
a more intersting use of partial illustrates it's function better:
(partial + 4)
produces the equivalent of:
(fn [& unfixed-args] (apply + (concat [4] unfixed-args)))
(it does not literally produce this)
The idea being to build a function that takes the un-fixed arguments, combines them with the fixed ones, and calls the function you passed to partial with enough arguments to work properly.
user> ((fn [& unfixed-args] (apply + (concat [4] unfixed-args))) 5 6 7 8 9)
39
user> ((partial + 4) 5 6 7 8 9)
39
I only use partial in practice when the number of arguments is variable. Otherwise I have a personal preference towards using the anonymous function reader form #( ... )
partial does not actually check which arities its first argument supports; an arguably more accurate docstring would say that it "takes a function f and some arguments to f". (Clearly if you supply too many arguments, the resulting partially applied function will be broken, though that will only be observable when you try to call it.) So that's why (partial rand-int 10) is ok even though the number of arguments to rand-int supplied is not "fewer than normal".
The reason why either partial or something like #(rand-int 10) is needed here is that repeatedly expects its final argument to be a function which it can repeatedly call, whereas (rand-int 10) would be a number.
Compare this to repeat which returns a sequence with the supplied item repeated the specified number of times (or infinitely many times in the unary case). Here (rand-int 10) would be an appropriate second argument, but of course it would be some particular number, so the result would look like (8 8 8 8 8 ...); repeatedly will make a separate call to (partial rand-int 10) for each item of the sequence returned, so you'll get from it a sequence of (likely different, independent) random numbers.
repeatedly signature we are interested in: (repeatedly number function)
In this case partial will simply wrap rand-int 10 into a function that can be returned and used by the outer function, in this case repeatedly.
Without partial(or #) inner expressions are resolved before the outer ones(there are exceptions, but let's keep it simple for now), so when repeatedly is called without partial, what's gonna be passed to it is a return value of rand-int, that is Int and not a function.