How to get rid of extra list levels in scheme? - recursion

My function below must accept an input that looks like this:
(getlist '(a b '(a b) 1 2 '() '(1 2)) )
The function must then output a list of all of the lists within the original list. So the output should be like
"((a b)()(1 2))"
but I am getting this:
"((quote (a b)) (quote ()) (quote (1 2)))"
I am getting the right values but they are all wrapped inside an extra list with the quotes attached. How do I fix this?
Thank You
;function to return all lists in a list
(define (getlist lst)
;if list is empty
(if (null? lst)
;true
'()
;false
(if (list? (car lst))
;true
(cons (car lst) (getlist (cdr lst)))
;false
(getlist (cdr lst)))))

That's because the input list really does contain the lists (quote (a b)), (quote ()), and (quote (1 2)).
The symbol quote is never evaluated.
' is not a "list-building" operator.
It's shorthand for the quote special form, which causes its arguments to not be evaluated.
Since the entire list is quoted, you're not evaluating '(a b)– that is, (quote (a b))– and the result is the list (quote (a b)).
The fix is to remove all the quotes except the outermost one:
> (getlist '(a b (a b) 1 2 () (1 2)))
'((a b) () (1 2))

Related

I'm trying to understand this piece of Scheme code, can someone explain it to me?

I found this Scheme code on the internet, it outputs all subsets given a list, can someone explain how it works?
(define (subsets s) (if (null? s)
(list ())
(let ((rest (subsets (cdr s))))(append rest (map (lambda (x) (cons (car s) x)) rest)))))
(subsets '(a b c))
You really need to format it:
(define (subsets s)
(if (null? s)
(list ())
(let ((rest (subsets (cdr s))))
(append rest
(map (lambda (x)
(cons (car s) x))
rest)))))
What it does is return (()) for the argument '()
For a one element argument eg. '(b) if binds rest to the subsets of every element execept the first.. Which is no elements so rest is (()) and then it returns a list consisting of all the elements in rest as well as each list element of rest with b added to front. Thus (() (b)).
For a two element argument eg. '(a b) it binds rest to the subsets of every element except the first. Which is (b) so we know from above that it is (() (b)) and we know it will use those as well as every element with a added to the beginning: (() (b) (a) (a b))
I could go on but I'm guessing you get the picture?

How to check whether a list contains a character in common lisp

I am learning lisp and i encountered a problem, I have this code
(defun createlist(list)
(if (characterp (car lst))
(list (car lst))))
> (print (createlist '(a v a (3))))
how do I get a list with a character in it without writing
>(print (createlist '(#\a b 1)))
That's the only way to write a character literal. If you want to detect a as well as #\a, you need to check for a symbol whose name is one character long, e.g.
(let ((elt (car list)))
(if (or (characterp elt)
(and (symbolp elt)
(= (length (symbol-name elt)) 1)))
(list elt)))
(mapcar #'character (remove-if-not #'symbolp '(a b c 1 2)))
;; (#\A #\B #\C)
(mapcar #'list
(mapcar #'character
(remove-if-not #'symbolp
'(a b c 1 2 d))))
;; ((#\A) (#\B) (#\C) (#\D))

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)

Recursion through nested lists in LISP

I am trying to find the other element in the nested list when querying the first one. Something like this. (findOther 'a '((a b) (b c) (a d)))--> b and d. I have done this so far: The problem is I only get b.
(defun findOther (elem L)
(cond (NIL (null L))
((eq elem (caar L)) (cdar L))
((findOther elem (cdr L)))))
First some comments on the original code:
(defun findOther (elem L)
(cond
;; NIL is always false, so you *never* end up using this
;; case. You probably want something like ((null l) '()),
;; NULL is still pretty common for this, but since you're
;; expecting a list, you could use the slighly more
;; descriptive ENDP.
(NIL (null L))
;; When you find an element, you immediately return its
;; counterpart, and don't collect it and continue on to
;; the rest of the list. It's also easier to read if
;; you use more descriptive names like FIRST and SECOND,
;; as in ((eq elem (first (first l))) (second (first l))).
;; It's worth noting that unless you have a specific reason
;; to use EQ, you might want to use EQL, which is the
;; default comparison in most CL functions.
((eq elem (caar L)) (cdar L))
;; Else, you continue to the rest of the list. In my
;; opinion, REST would be more decriptive than CDR here,
;; but recursing and returning the value *is* what you
;; want to do here.
((findOther elem (cdr L)))))
Taking some of those into consideration, we could do something like this:
(defun others (element list)
(cond
((endp list) '())
((eql element (first (first list)))
(list* (second (first list))
(others element (rest list))))
((others element (rest list)))))
All that said, the functions in the standard library
would make this much easier. E.g. using mapcan:
(defun others (element list)
(mapcan (lambda (sublist)
(when (eql (first sublist) element)
(rest sublist)))
list))
(others 'a '((a b) (b c) (a d)))
;=> (B D)
I am not sure if you are looking for pair of two elements or may be more elements in list as well. Just in case you have more elements and you want all of them as well and also of some of them are not really pairs,
(defun pair-of (elem lis)
(let ((temp nil))
(cond
((and (listp lis) (not (null lis)))
(mapcar
#'(lambda (x)
(cond
((and (listp x) (not (null x)) (eql elem (car x)))
(push (cdr x) temp))))
lis)))
(nreverse temp)))
USAGE:(pair-of 'a '((a b) (b c) (a d w) 1))
OUTPUT: ((B) (D W))
But in case you want them combined in one list,
(reduce #'append (pair-of 'a '((a s) (a 3 8) (2 5 1))):initial-value '())
=> (S 3 8)

Flattening a List of Lists

I'm new to Scheme and functional programming in general. Can someone explain this code — specifically what kons and knil are? The goal is to flatten a list of lists.
(define (fold1 kons knil lst)
(if (null? lst)
knil
(fold1 kons (kons (car lst) knil) (cdr lst))))
I'm fairly certain kons is a function as it's being applied to two arguments but still not totally sure about its functionality.
This is a (weird) fold
This is a generalized folding procedure. In Lisps, lists are represented by cons cells and the empty list, where each (proper) list is either the empty list (), or a cons cell whose car is an element of the list and whose cdr is the rest of the list. E.g., a list (1 2 3 4 5) can be produced by
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 '())))))
The fold1 function that you've shown:
(define (fold1 kons knil lst)
(if (null? lst)
knil
(fold1 kons (kons (car lst) knil) (cdr lst))))
is a a way of taking a list like the one shown above and transforming it to:
(kons 5 (kons 4 (kons 3 (kons 2 (kons 1 knil)))))
This is a fold. This is an efficient generalization of lots of operations. For instance, if you use 0 as knil and + as kons, you compute the sum of the elements in the list.
Usually folds are right or left associative. A proper left-associative fold would transform to
(kons (kons (kons (kons (kons knil 1) 2) 3) 4) 5)
which might be clearer when viewed with + and infix notation:
(((((0 + 1) + 2) + 3) + 4) + 5)
The right associative fold would become
(1 + (2 + (3 + (4 + (5 + 0)))))
The left associative fold can be more efficient because the natural implementation is tail recursive, and elements are consumed from the list in the order that they can be extracted from the list. E.g., in the proper left associatve example, (kons knil 1) can be evaluated first to produce some value v, and then, in the same stack space, (kons v 2) can be evaluated, and so on. The right associative method requires traversing to the end of the list first. A naïve implementation requires stack space proportional to the length of the list.
This fold1 mixes things up a bit, because it's processing the elements of the list in a left associative manner, but the order of the arguments to the combining function is reversed.
This type of definition can be used any time that you have a algebraic datatype. Since a list in Lisps is either the empty list, or an element and a list combined with cons, you can write a function that handles each of these cases, and produces a new value by “replacing” cons with a combination function and the empty list with some designated value.
Flattening a list of lists
So, if you've got a list of lists, e.g., ((a b) (c d) (e f)), it's constructed by
(cons '(a b) (cons '(c d) (cons '(e f) '())))
With a right associative fold, you transform it to:
(append '(a b) (append '(c d) (append '(e f) '())))
by using append for kons, and '() for knil. However, in this slightly mixed up fold, your structure will be
(kons '(e f) (kons '(c d) (kons '(a b) knil)))
so knil can still be '(), but kons will need to be a function that calls append, but swaps the argument order:
(define (flatten lists)
(fold1 (lambda (right left)
(append left right))
'()
lists))
And so we have:
(flatten '((a b) (c d) (e f)))
;=> (a b c d e f)
Flattening deeper lists of lists
Given that this is a folding exercise, I expected that the list of lists are nested only one layer deep. However, since we've seen how to implement a simple flatten
(define (flatten lists)
(fold1 (lambda (right left)
(append left right))
'()
lists))
we can modify this to make sure that deeper lists are flattened, too. The kons function now
(lambda (right left)
(append left right))
simply appends the two lists together. left is the already appended and flattened list that we've been building up. right is the new component that we're taking on now. If we make a call to flatten that, too, that should flatten arbitrarily nested lists:
(define (flatten lists)
(fold1 (lambda (right left)
(append left (flatten right))) ; recursively flatten sublists
'()
lists))
This is almost right, except that now when we call (flatten '((a b) (c d))), we'll end up making a call to (flatten '(a b)), which will in turn make a call to (flatten 'a), but flatten is a wrapper for fold1, and fold1 expects its arguments to be lists. We need to decide what to do when flatten is called with a non-list. A simple approach is to have it return a list containing the non-list argument. That return value will mesh nicely with the append that's receiving the value.
(define (flatten lists) ; lists is not necessarily a list of lists anymore,
(if (not (pair? lists)) ; perhaps a better name should be chosen
(list lists)
(fold1 (lambda (right left)
(append left (flatten right)))
'()
lists)))
Now we have
(flatten '(a (b (c)) (((d)))))
;=> (a b c d)
The procedure shown is an implementation of fold:
In functional programming, fold – also known variously as reduce, accumulate, aggregate, compress, or inject – refers to a family of higher-order functions that analyze a recursive data structure and recombine through use of a given combining operation the results of recursively processing its constituent parts, building up a return value
Take note:
The kons parameter is a two-argument function that's used for "combining" the current element of the list being processed with the accumulated value
The knil parameter is the accumulated output result
To see how this works, imagine for a moment that we have a function such as this:
(define (reverse knil lst)
(if (null? lst)
knil
(reverse (cons (car lst) knil) (cdr lst))))
(reverse '() '(1 2 3 4))
=> '(4 3 2 1)
In the above knil is used to accumulate the result, and it starts in a value of '() because we're building a list as output. And kons is called cons, which builds lists. Let's see another example:
(define (add knil lst)
(if (null? lst)
knil
(add (+ (car lst) knil) (cdr lst))))
(add 0 '(1 2 3 4))
=> 10
In the above knil is used to accumulate the result, and it starts in a value of 0 because we're building a number as output. And kons is called +, which adds numbers.
By now you must have realized that both examples share the same structure of a solution, both consume an input list and the only things that change is how we "combine" the values pulled from the list and the starting accumulated value. If we're smart, we can factor out the parts that change into a higher order procedure, that receives the changing parts as parameters - thus fold1 is born:
(define (fold1 kons knil lst)
(if (null? lst)
knil
(fold1 kons (kons (car lst) knil) (cdr lst))))
And both of the above examples can be easily expressed in terms of fold1, just pass along the right parameters:
(define (reverse lst)
(fold1 cons '() lst))
(define (add lst)
(fold1 + 0 lst))
Now for the second part of the question: if you want to flatten a list with fold1 you can try this:
(define (helper x lst)
(if (pair? x)
(fold1 helper lst x)
(cons x lst)))
(define (flatten lst)
(reverse (helper lst '())))
(flatten '(1 2 (3) (4 (5)) 6))
=> '(1 2 3 4 5 6)
Following code using 'named let' and 'for' loop can be used to flatten the list of elements which themselves may be lists:
(define (myflatten ll)
(define ol '())
(let loop ((ll ll))
(for ((i ll))
(if (list? i)
(loop i)
(set! ol (cons i ol)))))
(reverse ol))
(myflatten '(a () (b e (c)) (((d)))))
Output:
'(a b e c d)
However, it uses 'set!' which is generally not preferred.
The 'for' loop can also be replaced by 'named let' recursion:
(define (myflatten ll)
(define ol '())
(let outer ((ll ll))
(let inner ((il ll))
(cond
[(empty? il)]
[(list? (first il))
(outer (first il))
(inner (rest il))]
[else
(set! ol (cons (first il) ol))
(inner (rest il))])))
(reverse ol))
Even shorter
(define (myflatten lists)
(foldr append empty lists))
(myflatten (list (list 1 2) (list 3 4 5) (list 6 7) (list 8 9 10)))
> (list 1 2 3 4 5 6 7 8 9 10)

Resources