Scheme: Recursion with list append - recursion

I have a recursive function that basically keeps appending elements to a list recursively until a condition has been met. There's an issue though, and that's to use append, we must give it a quoted list. So doing
(append (1 2) 3)
gives us an error.
The problem is when I first pass a list to the argument, I can put the ' to make it a quoted list. However, once I append something to that list and it gets recursively passed to the same function again, the second time append tries to work, it will see the list is no longer quoted, so Scheme thinks it's a procedure rather than a list. Let me show you a simplified version of the code:
(define simple
(lambda (x y)
(if (equal? x '())
(display 'success!)
(simple (cdr x) (append y (car x))))))
We run the function by doing (simple '(1 2 3) '())
I realize the program above is useless; it's just to demonstrate what I'm saying.
Thanks!

The trouble with the code you posted isn't that Scheme is confusing a procedure with a list; the trouble is with the call to append.
It can be helpful to trace the execution of a procedure when debugging. Here's what's shown when I run your code with tracing turned on for simple and append, using trace-define in Petite Chez Scheme:
> (simple '(1 2 3) '())
|(simple (1 2 3) ())
| (append () 1)
| 1
|(simple (2 3) 1)
| (append 1 2)
Because (append () 1) returns 1, in the first recursive call to simple, the second argument is 1 rather than a list. So, you get an error on the next call to append.
You could fix it by wrapping your (car x) call in a call to list:
(define simple
(lambda (x y)
(if (equal? x '())
(display 'success!)
(simple (cdr x) (append y (list (car x)))))))
Here's a trace of the fixed version running:
> (simple '(1 2 3) '())
|(simple (1 2 3) ())
| (append () (1))
| (1)
|(simple (2 3) (1))
| (append (1) (2))
| (1 2)
|(simple (3) (1 2))
| (append (1 2) (3))
| (1 2 3)
|(simple () (1 2 3))
success!|#<void>

To append an element to the end of a list, put the element inside a list (append is defined only between lists). For example, in your code do this:
(append y (list (car x)))
Of course, that doesn't change the fact that the procedure is doing nothing as it is. At least, return the value accumulated in y:
(define simple
(lambda (x y)
(if (equal? x '())
y
(simple (cdr x)
(append y (list (car x)))))))

Related

Scheme error says "attempt to apply non-procedure" when flipping tuples in a list

I'm working through a textbook on programming languages, and one of the exercises was to make a function in Scheme that flips tuples in a list. Here's my code:
; invert : Listof(List(Int,Int)) -> Listof(List(Int,int))
; usage: (invert '((a 1) (a 2) (1 b) (2 b))) -> ((1 a) (2 a) (b 1) (b 2))
(define invert
(lambda (lst)
(if (null? lst)
'()
(cons
(flip (car lst))
(invert (cdr lst))))))
; flip : List(Int,Int) -> List(Int,int)
; usage: (flip '(a 1)) -> (1 a)
(define flip
(lambda (tuple)
(if (not (eqv? (length (tuple)) 2))
(eopl:error 'flip
"Tuple is not length 2~%")
(cons (cdr tuple) (car tuple)))))
I tried testing my program in chez-scheme. When I use the test case in the usage comment, I get this error: Exception: attempt to apply non-procedure (a 1). I've never worked with Scheme before, so I'd greatly appreciate any help and advice. Thanks!
You have a coupe of errors in flip, this should fix them:
(define flip
(lambda (tuple)
(if (not (= (length tuple) 2))
(eopl:error 'flip "Tuple is not length 2~%")
(list (cadr tuple) (car tuple)))))
In particular:
The specific error reported was because of this expression: (tuple). We must not surround variables with (), unless they're procedures that we intend to call.
We should use = for comparing numbers, not eqv?.
In this expression: (cons (cdr tuple) (car tuple)) there are two issues, for building a list of two elements we use list, not cons. And for accessing the second element we use cadr, not cdr - you should read a bit about how cons, car and cdr are used for building lists.
Notice that there's a simpler way to solve this problem if we use map; I'll skip error checking for simplicity:
(define (invert lst)
(map (lambda (tuple) (list (cadr tuple) (car tuple)))
lst))

Common lisp recursive macro in matrix addition

I have to write a recursive macro for list addition in Common Lisp (homework). What I have so far is :
(defmacro matrix-add-row (r1 r2 sum_row)
(if (not (and r1 r2)) `sum_row
(progn
`(matrix-add-row (cdr r1) (cdr r2) (cons sum_row (+ (car r1) (car r2))))
(reverse sum_row)
)
)
)
I call this function with
(matrix-add-row `(1 2) `(3 4) ())
and as an output I get unvaluated code instead of numbers (which leads going to infinite loop).
How to put , ` properly (or call the macro properly)?
Firstly, to me this seems a rather bizarre thing to do with a macro. I assume the point is that you use the macro to transform (matrix-add-row '(1 2) '(3 4)) to an explicit list of sums like (list (+ 1 3) (+ 2 4)).
Also, what you have written has several problems which look like you don't quite understand how the backtick works. So I think the easiest way to help is to solve an example for you.
Since this is homework, I'm going to solve a different (but similar) question. You should be able to take the answer and use it for your example. Suppose I want to solve the following:
Write a macro, diffs, which computes all differences of pairs of successive elements in a list. For example,
(diffs '(1 2 3)) should expand to (list (- 2 1) (- 3 2)), which will then evaluate to (1 1).
Note that my macro won't do the actual subtraction, so I can use it even if I don't know some of the numbers until runtime. (The reason I think this sort of question is a bit weird is that it does need to know the length of the list at compile time).
My solution is going to be used as a macro with one argument but if I want to use recursion I'll need to pass in an accumulator too, which I can start with nil. So I write something like this:
(defmacro diffs (lst &optional accumulator)
...)
Now what do I do with lst? If lst is nil, I want to bottom out and just return the accumulator, with a call to list at the front, which will be code to make my list. Something like this:
(defmacro diffs (lst &optional accumulator)
(cond
((null lst)
;; You could write `(list ,#accumulator) instead, but that seems
;; unnecessarily obfuscated.
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
Let's try it!
CL-USER> (diffs nil)
NIL
Not hugely exciting, but it looks plausible. Now use macroexpand, which just does the expansion without the evaluation:
CL-USER> (macroexpand '(diffs nil))
(LIST)
T
And what if we'd already got some stuff from a recursion?
CL-USER> (macroexpand '(diffs nil ((- a b) (- b c))))
(LIST (- A B) (- B C))
T
Looks good! Now we need to deal with the case when there's an actual list there. The test you want is consp and (for my example) it only makes sense when there's at least two elements.
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
(list 'diffs (cdr lst)
(cons (list '- (cadr lst) (car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
This seems almost to work:
CL-USER> (macroexpand '(diffs (3 4 5)))
(LIST (- 5 4) (- 4 3))
T
but for two problems:
The list comes out backwards
The code is a bit horrible when we actually construct the recursive expansion
Let's fix the second part first by using the backtick operator:
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
`(diffs ,(cdr lst)
,(cons `(- ,(cadr lst) ,(car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
Hmm, it's not actually much shorter, but I think it's clearer.
For the second part, we could proceed by adding each item to the end of the accumulator rather than the front, but that's not particularly quick in Lisp because lists are singly linked. Better is to construct the accumulator backwards and then reverse it at the end:
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
`(diffs ,(cdr lst)
,(cons `(- ,(cadr lst) ,(car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list (reverse accumulator)))
(t
(error "Aargh. Unhandled"))))
Now we get:
CL-USER> (macroexpand '(diffs (3 4 5)))
(LIST (- 4 3) (- 5 4))
T
Much better!
Two last things. Firstly, I still have an error clause in my macro. Can you see how to trigger it? Can you think of a better behaviour than just outputting an error? (Your macro is going to have to deal with the same problem)
Secondly, for debugging recursive macros like this, I recommend using macroexpand-1 which just unfolds one level at once. For example:
CL-USER> (macroexpand-1 '(diffs (3 4 5)))
(DIFFS (4 5) ((- 4 3)))
T
CL-USER> (macroexpand-1 *)
(DIFFS (5) ((- 5 4) (- 4 3)))
T
CL-USER> (macroexpand-1 *)
(LIST (- 4 3) (- 5 4))
T
There are two problems with your logic. First you are calling reverse on each iteration instead of at the end of the iteration. Then you are accumulating the new values, through cons, in the cdr of the cons cell as opposed to the car.
Also I don't see why this have to be a macro so using a function.
(defun matrix-add-row (r1 r2 sum-row)
(if (or (endp r1) (endp r2))
(reverse sum-row)
(matrix-add-row (cdr r1)
(cdr r2)
(cons (+ (car r1) (car r2))
sum-row))))
(matrix-add-row '(1 2) '(3 4) ())
;; => (4 6)

lisp functions ( count numbers in common lisp)

I am working on program related to the different of dealing with even numbers in C and lisp , finished my c program but still having troubles with lisp
isprime function is defined and I need help in:
define function primesinlist that returns unique prime numbers in a lis
here what i got so far ,
any help with that please?
(defun comprimento (lista)
(if (null lista)
0
(1+ (comprimento (rest lista)))))
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number number-list)
(when (isprime number)
( number result)))
(nreverse result)))
You need to either flatten the argument before processing:
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number (flatten number-list))
(when (isprime number)
(push number result)))
(delete-duplicates (nreverse result))))
or, if you want to avoid consing up a fresh list, flatten it as you go:
(defun primesinlist (number-list)
(let ((result ()))
(labels ((f (l)
(dolist (x l)
(etypecase x
(integer (when (isprime x)
(push x result)))
(list (f x))))))
(f number-list))
(delete-duplicates (nreverse result))))
To count distinct primes, take the length of the list returned by primesinlist.
Alternatively, you can use count-if:
(count-if #'isprime (delete-duplicates (flatten number-list)))
It sounds like you've already got a primality test implemented, but for sake of completeness, lets add a very simple one that just tries to divide a number by the numbers less than it up to its square root:
(defun primep (x)
"Very simple implementation of a primality test. Checks
for each n above 1 and below (sqrt x) whether n divides x.
Example:
(mapcar 'primep '(2 3 4 5 6 7 8 9 10 11 12 13))
;=> (T T NIL T NIL T NIL NIL NIL T NIL T)
"
(do ((sqrt-x (sqrt x))
(i 2 (1+ i)))
((> i sqrt-x) t)
(when (zerop (mod x i))
(return nil))))
Now, you need a way to flatten a potentially nested list of lists into a single list. When approaching this problem, I usually find it a bit easier to think in terms of trees built of cons-cells. Here's an efficient flattening function that returns a completely new list. That is, it doesn't share any structure with the original tree. That can be useful, especially if we want to modify the resulting structure later, without modifying the original input.
(defun flatten-tree (x &optional (tail '()))
"Efficiently flatten a tree of cons cells into
a list of all the non-NIL leafs of the tree. A completely
fresh list is returned.
Examples:
(flatten-tree nil) ;=> ()
(flatten-tree 1) ;=> (1)
(flatten-tree '(1 (2 (3)) (4) 5)) ;=> (1 2 3 4 5)
(flatten-tree '(1 () () 5)) ;=> (1 5)
"
(cond
((null x) tail)
((atom x) (list* x tail))
((consp x) (flatten-tree (car x)
(flatten-tree (cdr x) tail)))))
Now it's just a matter of flatting a list, removing the number that are not prime, and removing duplicates from that list. Common Lisp includes functions for doing these things, namely remove-if-not and remove-duplicates. Those are the "safe" versions that don't modify their input arguments. Since we know that the flattened list is freshly generated, we can use their (potentially) destructive counterparts, delete-if-not and delete-duplicates.
There's a caveat when you're removing duplicate elements, though. If you have a list like (1 3 5 3), there are two possible results that could be returned (assuming you keep all the other elements in order): (1 3 5) and (1 5 3). That is, you can either remove the the later duplicate or the earlier duplicate. In general, you have the question of "which one should be left behind?" Common Lisp, by default, removes the earlier duplicate and leaves the last occurrence. That behavior can be customized by the :from-end keyword argument. It can be nice to duplicate that behavior in your own API.
So, here's a function that puts all those considerations together.
(defun primes-in-tree (tree &key from-end)
"Flatten the tree, remove elements which are not prime numbers,
using FROM-END to determine whether earlier or later occurrences
are kept in the list.
Examples:
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7))
;;=> (2 3 5 7)
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7) :from-end t)
;;=> (2 7 3 5)"
;; Because FLATTEN-TREE returns a fresh list, it's OK
;; to use the destructive functions DELETE-IF-NOT and
;; DELETE-DUPLICATES.
(delete-duplicates
(delete-if-not 'primep (flatten-tree list))
:from-end from-end))

Dr. Racket Recursion count occurrences

I'm new to Racket and trying to learn it. I'm working through some problems that I'm struggling with. Here is what the problem is asking:
Write a definition for the recursive function occur that takes a data expression a and a list s and returns the number of times that the data expression a appears in the list s.
Example:
(occur '() '(1 () 2 () () 3)) =>3
(occur 1 '(1 2 1 ((3 1)) 4 1)) => 3 (note that it only looks at whole elements in the list)
(occur '((2)) '(1 ((2)) 3)) => 1
This is what I have written so far:
(define occur
(lambda (a s)
(cond
((equal? a (first s))
(else (occur a(rest s))))))
I'm not sure how to implement the count. The next problem is similar and I have no idea how to approach that. Here is what this problem says:
(This is similar to the function above, but it looks inside the sublists as well) Write a recursive function atom-occur?, which takes two inputs, an atom a and a list s, and outputs the Boolean true if and only if a appears somewhere within s, either as one of the data expressions in s, or as one of the data expression in one of the data expression in s, or…, and so on.
Example:
(atom-occur? 'a '((x y (p q (a b) r)) z)) => #t
(atom-occur? 'm '(x (y p (1 a (b 4)) z))) => #f
Any assistance would be appreciated. Thank you.
In Racket, the standard way to solve this problem would be to use built-in procedures:
(define occur
(lambda (a s)
(count (curry equal? a) s)))
But of course, you want to implement it from scratch. Don't forget the base case (empty list), and remember to add one unit whenever a new match is found. Try this:
(define occur
(lambda (a s)
(cond
((empty? s) 0)
((equal? a (first s))
(add1 (occur a (rest s))))
(else (occur a (rest s))))))
The second problem is similar, but it uses the standard template for traversing a list of lists, where we go down on the recursion on both the first and the rest of the input list, and only test for equality when we're in an atom:
(define atom-occur?
(lambda (a s)
(cond
((empty? s) #f)
((not (pair? s))
(equal? a s))
(else (or (atom-occur? a (first s))
(atom-occur? a (rest s)))))))

Scheme accumulative recursion with lists

How can I pass a list as a parameter to a function adding elements to it recursively,and have it unmodified when it comes out of recursion?
I want to use the list at each level of recursion with the list having the values added by deeper recursion levels.
To be more specific I want to do a DFS search on a graph and I want to store in the list the nodes I visited.
One method of doing this is just to return the list so you have access to it at higher levels of recursion.
Another method is to have your list be stored in a variable outside of the recursion. In other words not stored on the stack. Since it is not a good idea to use a global variable for this we need to have some local recursion.
The following code is a foolish way to reverse a list but it does illustrate the technique I am talking about.
(define (letrecreverse lst)
(letrec ((retlist '())
(reverse (lambda (lst)
(if (null? lst)
'()
(begin
(set! retlist (cons (car lst) retlist))
(reverse (cdr lst)))))))
(reverse lst)
retlist))
(letrecreverse '(1 2 3 4))
;outputs '(4 3 2 1)
Can you adopt this technique for your purposes?
If you build a new list by consing a value onto an old list, that old list is unmodified.
(define old '(1 2 3))
(define new (cons 55 old))
new
>(55 1 2 3)
old
>(1 2 3)
The 'tail' of the first cons in "new" is the list "old". But old hasn't changed.
(cdr new)
> (1 2 3)
If I understood your question correctly, this could be one solution:
;; Just a helper to print the current list.
(define (show list)
(display "list = ")
(display list)
(newline)
(flush-output))
;; Maximum depth of recursion
(define max-recur 5)
;; Original list is backed-up here.
(define orig-list null)
(define (recur list depth)
(if (null? orig-list)
(set! orig-list list))
(cond ((< depth max-recur)
(show list)
(recur (cons (random max-recur) list) (add1 depth)))
(else orig-list)))
Sample run:
> (recur '(1) 0)
list = (1)
list = (1 1)
list = (2 1 1)
list = (3 2 1 1)
list = (4 3 2 1 1)
(1) ;; In the end you get the original list back.

Resources