Building a list with loops - list

We just covered loops today in class and I've got a few things I need to do. Put simply, I have to build a list using loops instead of recursion. I seem to be at a stumbling block here. For this example, we need to do a simple countdown. The function takes an argument and then returns a list of all the positive integers less than or equal to the initial argument. (countdown 5) => (5 4 3 2 1)
I'm having a hard time getting loops for whatever reason. The ones we talked about was Loop, Do, Dotimes, and Dolist. I've tried this with a couple loops and always end up with a similar result.
(defun countdown (num)
(cond ((= num 0) nil)
(T (let* ((list nil))
(loop
(if (= num 0) (return list)
(setf list (cons list num)))
(setf num (- num 1)))))))
My output shows up like this:
(((((NIL . 5) . 4) . 3) . 2) .1)
update: I've solved the issue. Apparently I needed to reverse the order in the cons, so num comes before list. Does anyone care to explain this? I thought you put the list first and then what you put second would be added to the end of it. At least, that's how I've been using it so far without issue.

Reverse the arguments to cons (and why)
You wrote in an answer (that, since it asks for more information, perhaps should have been a comment):
I've solved the issue. Apparently I needed to reverse the order in the
cons, so num comes before list. Does anyone care to explain this? I
thought you put the list first and then what you put second would be
added to the end of it. At least, that's how I've been using it so far
without issue.
The function is documented in the HyperSpec clearly: Function CONS. The examples in the documentation show, e.g.,
(cons 1 (cons 2 (cons 3 (cons 4 nil)))) => (1 2 3 4)
(cons 'a (cons 'b (cons 'c '()))) => (A B C)
(cons 'a '(b c d)) => (A B C D)
and even the note
If object-2 is a list, cons can be thought of as producing a new list which is like it but has object-1 prepended.
It may help to read through 14.1.2 Conses as Lists, as well, which includes:
A list is a chain of conses in which the car of each cons is an element of the list, and the cdr of each cons is either the next link in the chain or a terminating atom.
Concerning loop
Many of the answers here are pointing out to you that the loop form includes a special iteration language. That's true, but it can also be used in the way that you're using it. That way is called a simple loop:
6.1.1.1.1 Simple Loop
A simple loop form is one that has a body containing only compound
forms. Each form is evaluated in turn from left to right. When the
last form has been evaluated, then the first form is evaluated again,
and so on, in a never-ending cycle. A simple loop form establishes an
implicit block named nil. The execution of a simple loop can be
terminated by explicitly transfering control to the implicit block
(using return or return-from) or to some exit point outside of the
block (e.g., using throw, go, or return-from).
Simple loops probably aren't as common as loops using the nicer features that loop provides, but if you just covered this in class, you might not be there yet. The other answers do provide some good examples, though.

If you speaking about common lisp loop, your countdown may look like this:
(defun countdown (from-number)
(loop :for x :from from-number :downto 1 :collect x))
CL-USER> (countdown 10)
(10 9 8 7 6 5 4 3 2 1)

Using loop, which has its own "special-purpose language" that does not really look like Lisp:
(defun countdown (n)
(loop
for i from n downto 1
collect i))
Or using do:
(defun countdown (n)
(do ((i 1 (1+ i))
(res nil (cons i res)))
((> i n) res)))
See here, especially chapters 7 and 22.

Related

Subset / Subsequence Recursive Procedure in Simply Scheme Lisp

I am working my way through Simply Scheme in combination with the Summer 2011 CS3 Course from Berkley. I am struggling with my understanding of the subset / subsequence procedures. I understand the basic mechanics once I'm presented with the solution code, but am struggling to grasp the concepts enough to come up with the solution on my own.
Could anyone point me in the direction of something that might help me understand it a little bit better? Or maybe explain it differently themselves?
This is the basis of what I understand so far:
So, in the following procedure, the subsequences recursive call that is an argument to prepend, is breaking down the word to its basest element, and prepend is adding the first of the word to each of those elements.
; using words and sentences
(define (subsequences wd)
(if (empty? wd)
(se "")
(se (subsequences (bf wd))
(prepend (first wd)
(subsequences (bf wd))))))
(define (prepend l wd)
(every (lambda (w) (word l w))
wd))
; using lists
(define (subsequences ls)
(if (null? ls)
(list '())
(let ((next (subsequences (cdr ls))))
(append (map (lambda (x) (cons (car ls) x))
next)
next))))
So the first one, when (subsequences 'word) is entered, would return:
("" d r rd o od or ord w wd wr wrd wo wod wor word)
The second one, when (subsequences '(1 2 3)) is entered, would return:
((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())
So, as I said, this code works. I understand each of the parts of the code individually and, for the most part, how they work with each other. The nested recursive call is what is giving me the trouble. I just don't completely understand it well enough to write such code on my own. Anything that might be able to help me understand it would be greatly appreciated. I think I just need a new perspective to wrap my head around it.
Thanks in advance for anyone willing to point me in the right direction.
EDIT:
So the first comment asked me to try and explain a little more about what I understand so far. Here it goes:
For the words / sentence procedure, I think that it's breaking the variable down to it's "basest" case (so to speak) via the recursive call that appears second.
Then it's essentially building on the basest case, by prepending.
I don't really understand why the recursive call that appears first needs to be there then.
In the lists one, when I was writing it on my own I got this:
(define (subseq lst)
(if (null? lst)
'()
(append (subseq (cdr lst))
(prepend (car lst)
(subseq (cdr lst))))))
(define (prepend i lst)
(map (lambda (itm) (cons i itm))
lst))
With the correct solution it looks to me like the car of the list would just drop off and not be accounted for, but obviously that's not the case. I'm not grasping how the two recursive calls are working together.
Your alternate solution is mostly good, but you've made the same mistake many people make when implementing this (power-set of a list) function for the first time: your base case is wrong.
How many ways are there to choose a subset of 0 or more items from a 0-element list? "0" may feel obvious, but in fact there is one way: choose none of the items. So instead of returning the empty list (meaning "there are no ways it can be done"), you should return (list '()) (meaning, "a list of one way to do it, which is to choose no elements"). Equivalently you could return '(()), which is the same as (list '()) - I don't know good Scheme style, so I'll leave that to you.
Once you've made that change, your solution works, demonstrating that you do in fact understand the recursion after all!
As to explaining the solution that was provided to you, I don't quite see what you think would happen to the car of the list. It's actually very nearly the exact same algorithm as the one you wrote yourself: to see how close it is, inline your definition of prepend (that is, substitute its body into your subsequences function). Then expand the let binding from the provided solution, substituting its body in the two places it appears. Finally, if you want, you can swap the order of the arguments to append - or not; it doesn't matter much. At this point, it's the same function you wrote.
Recursion is a tool which is there to help us, to make programming easier.
A recursive approach doesn't try to solve the whole problem at once. It says, what if we already had the solution code? Then we could apply it to any similar smaller part of the original problem, and get the solution for it back. Then all we'd have to do is re-combine the leftover "shell" which contained that smaller self-similar part, with the result for that smaller part; and that way we'd get our full solution for the full problem!
So if we can identify that recursive structure in our data; if we can take it apart like a Russian "matryoshka" doll which contains its own smaller copy inside its shell (which too contains the smaller copies of self inside itself, all the way down) and can put it back; then all we need to do to transform the whole "doll" is to transform the nested "matryoshka" doll contained in it (with all the nested dolls inside -- we don't care how many levels deep!) by applying to it that recursive procedure which we are seeking to create, and simply put back the result:
solution( shell <+> core ) == shell {+} solution( core )
;; -------------- ----
The two +s on the two sides of the equation are different, because the transformed doll might not be a doll at all! (also, the <+> on the left is deconstructing a given datum, while {+} on the right constructs the overall result.)
This is the recursion scheme used in your functions.
Some problems are better fit for other recursion schemes, e.g. various sorts, Voronoi diagrams, etc. are better done with divide-and-conquer:
solution( part1 <+> part2 ) == solution( part1 ) {+} solution( part2 )
;; --------------- ----- -----
As for the two -- or one -- recursive calls, since this is mathematically a function, the result of calling it with the same argument is always the same. There's no semantic difference, only an operational one.
Sometimes we prefer to calculate a result and keep it in memory for further reuse; sometimes we prefer to recalculate it every time it's needed. It does not matter as far as the end result is concerned -- the same result will be calculated, the only difference being the consumed memory and / or the time it will take to produce that result.

Recursively adding to a list using Scheme

I'm brand new to functional programming, and relatively new to programming as a whole. So I'm pretty lost trying to understand the syntax of Scheme. But this is a pretty simple question. I'm trying to create a function that recursively fills and prints a list from numbers x to y. Between recursion and this being a new language for me, I'm quite stuck.
(define (gen-list x y)
(if (> start end)
'()
(append '() (gen-list ((+ 1 x) y)) ) ))
If I were to enter in (gen-list 1 5) I would expect the result to be 1 2 3 4 5. This is currently giving me an error of "application: not a procedure" when it tries to call itself again. I have gotten around the error, but not been able to print anything remotely like what I'd like to. Any help is appreciated.
You have a couple of errors:
The parameters are called x and y, but you refer to them as start and end (I'd suggest to use start and end instead, they make the code easier to understand.)
You have more parentheses than needed in the last line. This is very important and an endless source of confusion for beginners. Don't surround all expressions with () unless you want to call a procedure.
We recursively build new lists with cons, append is for concatenating existing lists.
You're not actually using start, which is the current element in the recursion, to build the new list - you're just appending empty lists.
A list is an element consed to another list, or the empty list '(). That's why we return '() in the base case. For example, this is how a two-element list looks like: (cons 1 (cons 2 '())).
With all said and done, this is the proper way to build our list:
(define (gen-list start end)
(if (> start end)
'()
(cons start
(gen-list (+ start 1) end))))
As a final comment: the above procedure already exists in Racket, you don't need to rewrite it. Read about range in the documentation.
One of the problems with the 'obvious' answer to this question is that it doesn't really work very well. Consider this:
(define (gen-list start end)
(if (> start end)
'()
(cons start
(gen-list (+ start 1) end))))
Well, if start is much less than end there are going to be a huge number of recursive calls on the stack, because this is a properly recursive function: the recursive call to gen-list is a real call and has to return before the call to cons (which is a tail call) can happen.
The way to deal with this is to turn patterns which look like (cons x (<recursive-call> ...)) into patterns which look like (<tail-call> ... (cons x ...)): you need a function with an extra argument, an accumulator. This means that the calls which were previously recursive are now tail calls and everything is therefore good: the process is now iterative.
The problem with this is that lists come out backwards (you need to think about why this is, but it's obvious after a bit of thought). So you then need to reverse the result. Fortunately reversing a list is also an iterative process, so that's OK.
But in this case, well, you can just count backwards! So a simple-minded approach looks like this, using a locally-defined auxiliary function (this can be defined as a top-level function, but why bother?):
(define (gen-list low high)
(define (gla i result)
(if (< i low)
result
(gla (- i 1) (cons i result))))
(gla high '()))
You can see this is counting backwards: the initial call to gla starts with high & then constructs the list backwards. So, now:
> (gen-list 1 3)
'(1 2 3)
As we want.
This is such a common pattern in Scheme that there is a special construct for it: named let. So we can rewrite the above more idiomatically as:
(define (gen-list low high)
(let gla ([i high] [result '()])
(if (< i low)
result
(gla (- i 1) (cons i result)))))
This is exactly the same as the previous answer: it just moves the initial call to the top and combines it with the local definition of gla. This is probably the idiomatic Scheme way to do something like this (although people who write more Scheme than me might differ: I'm really a CL person and have inevitably poor taste).
This is where the story should end, but I can't resist adding the following. In the bad old days of comp.lang.lisp, people used to ask obvious homework questions and since there was no karma system one approach was to give an answer which solved the problem ... while being absurdly opaque.
So first of all we can turn gla into a function which gets passed a continuation to call rather than knowing it must call itself:
(define (gen-list low high)
(let ([gla (λ (cont i result)
(if (< i low)
result
(cont cont (- i 1) (cons i result))))])
(gla gla high '())))
And then, of course we can turn (let ([x y]) ...) into ((λ (x) ...) y):
(define (gen-list low high)
((λ (gla)
(gla gla high '()))
(λ (cont i result)
(if (< i low)
result
(cont cont (- i 1) (cons i result))))))
And that's a nice, pure answer ... which no student would ever come up with.
An alternative approach which is even more malicious is just to explicitly use the Y combinator, of course.
Just adding tail call recursive version
(define (gen-list start end (acc '()) #:step (step 1))
(cond ((> start end) (reverse acc))
(else (gen-list (+ start step) end (cons start acc)))))
Personally I love cond because you have all the conditions then below each other (or an else) - this is the style of The little Schemer a very good book for learning recursive thinking.
You need more than just the (> start end) base case, you also need a (= start end) base case in which you return (list start)

What's the point of building a list with a non-list tail?

The Emacs lisp manual states about the function nconc that:
Since the last argument of nconc is not itself modified, it is reasonable to use a constant list, such as '(4 5), as in the above example. For the same reason, the last argument need not be a list
And indeed I can write
(setq x '(1 2 3))
=> (1 2 3)
(nconc x 0)
=> (1 2 3 . 0)
but that yields a totally broken list:
(length x)
=> eval: Wrong type argument: listp, 0
(butlast x)
=> butlast: Wrong type argument: listp, 0
How can I retrieve the original list? (reverse (cdr (reverse '(1 2 3 . 0)))) doesn't cut it either.
In which contexts is this a useful pattern? In the standard distribution some functions in minibuffer.el use it, in particular completion-all-completions and the like.
They're not "broken" lists; they're actually known as improper lists (as opposed to nil-terminated lists, which are proper lists). Many list functions, such as length and butlast that you just named, expect proper lists, and listp returns true only for proper lists.
Improper lists are used in association lists (where the associations are often not proper; though the alist itself must be proper).
If you want to make an improper list proper, you have two options:
Remove the "improper" element.
Treat the improper element as the last element of the proper list.
Here's a procedure I wrote called properise which will do the former:
(defun properise (x)
(let ((r nil))
(while (consp x)
(push (pop x) r))
(nreverse r)))
(If you want the latter behaviour, add (unless (null x) (push x r)) just before the nreverse line.)
Generally I would avoid creating data structures like that, where the last element is a cons cell with some object other than NIL in the cdr... It makes debugging harder, it's a hack, makes code more difficult to understand, ...
I'm still unsure why this is a good pattern, but here's an easy way of getting a proper list out of an improper one, without making a copy:
(defun nmake-proper-list (x)
(let ((y (last x)))
(setcdr y nil)
x))

(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.

How to Implement a counter for every number inside a list with Scheme?

Okay I want to count the number of times each [number] has appeared inside a list using Scheme.
How can I do that ? I also would like to store the counter of the given number and re-construct a new list.
For example I have the following list ((1 2)(2 5)(5 7)(7 8)(6 8)(4 6)(3 4)(1 3)(4 8))
I was thinking first flatten the list, and then set a counter for each number (don't know how to do it). And then reconstruct a new list corresponding to the original number. (this can be tricky ? I need to store a temporary variable ?)
Say from this example the number 1 appeared twice, number 2 appeared twice, number 3 twice etc... so I would like to recreate a new list to something like this:
(1 2) (2 2) (3 2) (4 3) (5 2) (7 2) (6 2) (8 3)
any idea how I can achieve this ?
Update:
I was thinking to implement an increment counter helper something like this ?
(define inc-counter
(let ((counter 0))
(lambda () (set! counter (+ counter 1)))))
A good answer mostly depends on your implementation (modulo R6RS). In the case of PLT scheme, here's a quick definition that does that. It avoids flattening the list -- you only need to scan each item, so there's no point in constructing a new copy when scanning a tree is so simple. Also, this function sorts the resulting list (since it will be all scrambled on its way out of the hash table). Even if you're using some completely different implementation, it should be easy to translate:
(define (counts x)
(define t (make-hash))
(define (scan x)
(if (list? x)
(for-each scan x)
(hash-set! t x (add1 (hash-ref t x 0)))))
(scan x)
(sort (hash-map t list) < #:key car))
(Note, BTW, that if this is any kind of HW question, then this code is much too practical to be useful as an answer...)
Use an accumulator parameter to flatten which keeps an association list of how many times each has appeared. That way you'll have all the data you need each time around the loop.
For example, you might write factorial like this:
(define (factorial num accum)
(if (= num 0) accum (factorial (- num 1) (* accum num)))
And call it with (factorial 10 1). At the end, the value of the accumulator is the result of the function. In your example, you'd write a little helper function that would call flatten and keep track of the number of times each number has appeared.
Perhaps not the most efficient solution, but I think you could achieve this by partitioning the list by its first element until there are no more elements in the list. The list of in-elements would then be all of the numbers in the list that were the same as the first number. This process could be repeated on the list of out-elements until there were no more elements in the list.
You could use a hashtable mapping the number to its number of occurrences. Create it with (make-hash).