Cons cells Common Lisp - common-lisp

I am super beginner. So don’t be surprise that my question is that easy.
I have following list (1 3 ((2))(7))
And I have to reconstruct that list just with the function cons.
I have no idea how to cons the third element of the list.
Maybe there is someone how could help me!
Thanks a lot!
(cons '1 (cons '3 (cons '(2) (cons '(7) nil))))
--> (1 3 (2) (7))
There are still missing some brackets. I have no idea to fix it.

We can write us a program to do it.
CL-USER 85 > (defun consify (expression)
(cond ((atom expression)
(typecase expression
(null expression)
(symbol (list 'quote expression))
(otherwise expression)))
(t
(list 'cons
(consify (first expression))
(consify (rest expression))))))
CONSIFY
Above returns the CONS expression.
CL-USER 86 > (consify '(1 3 ((2))(7)))
(CONS 1 (CONS 3 (CONS (CONS (CONS 2 NIL) NIL) (CONS (CONS 7 NIL) NIL))))
We can now evaluate the result from above:
CL-USER 87 > (eval (consify '(1 3 ((2))(7))))
(1 3 ((2)) (7))
Same with your other expression:
CL-USER 88 > (pprint (consify '((Fat Cat)
(In da ((House)) It)
(Might eat (the (treats))))))
(CONS (CONS 'FAT (CONS 'CAT NIL))
(CONS (CONS 'IN (CONS 'DA (CONS (CONS (CONS 'HOUSE NIL) NIL)
(CONS 'IT NIL))))
(CONS (CONS 'MIGHT
(CONS 'EAT (CONS (CONS 'THE
(CONS (CONS 'TREATS NIL)
NIL))
NIL)))
NIL)))
CL-USER 89 > (eval (consify '((Fat Cat)
(In da ((House)) It)
(Might eat (the (treats))))))
((FAT CAT) (IN DA ((HOUSE)) IT) (MIGHT EAT (THE (TREATS))))

The fix for your problem would be this: (please keep reading tho, this is not the final answer)
(cons '1 (cons '3 (cons (cons '(2) nil) (cons '(7) nil))))
You were really really close with your solution: (cons '1 (cons '3 (cons '(2) (cons '(7) nil)))) the thing was that, as you said, there was some parethesis missing on the 2. You managed to make (2) which is a list containing 2, but the goal was to make a ((2)) which means: A list containing a list containing 2. So we simply changed '(2) to (cons '(2) nil)
Now, that being said, i would consider the use of '(2) as cheating, since if you are allowed to use quotes, you could just do '(1 3 ((2)) (7)) or the equivalent (quote (1 3 ((2)) (7)))) and you are done. Clearly there is no challenge in that. So what you probably have to do is use ONLY cons without beign able to use quote at all, in that case the soluion would look like this:
(cons 1 (cons 3 (cons (cons (cons 2 nil) nil) (cons (cons 7 nil) nil))))
And this is a lot more pure, which is probably what you were assigned to do, this WOULD be a valid answer
We could even go extreme purist and replace nil with () (They both represent the empty list) and we get this
(cons 1 (cons 3 (cons (cons (cons 2 ()) ()) (cons (cons 7 ()) ()))))
Which really shows the beauty of "Everything is a list" which lisp has. But let's face it, that's overkill
Now, if something is still not clear, you might need to study a little bit more on what lists really ARE in lisp. I'm not the best person to explain this (I'm a programer, not a teacher) but i can try. I do recomend you to do a little bit of research on your own tho, that beign said:
Theory time!
Feel free to skip this whole if you fell you are solid on the theory
Cons is one of the fundamental building blocks of lisp, it's a very very simple concept, It's a container that holds two... things. What those things are is beyond the scope of what we need to know, but is a very intresting topic on its's own. The important point is that we can call cons on two things (Eg. two numbers) like this (cons 3 4) and the interpreter would print something that looks like this (3 . 4), you can get the first argument by calling car and the second one by calling cdr like this:
(car (cons 3 4)) ; 3
(cdr (cons 3 4)) ; 4
Well, i said that a cons can hold to things, not just numbers, for example we could hold a number and the empty list NIL like (cons nil 7) and as you might expect (car (cons nil 7)) indeed returns NIL
We can also place a cons inside another cons! like this (cons (cons 3 4) (cons 6 7)) Which you could think of like a tree with to branches (So a binary tree), and each one of them also having two branches, and ad the end of those is the node holding each of the numbers. We can still use car and cdr to get the left and right elements ((3 . 4) and (6 . 7) respectively)
Ok, that easy, a little bit too easy, how are we suposed to get lists by just being able to make pairs? The answer is abstraction! There is a concept in computer science called a Linked List. There are many ways to make it in a lot of programing languages, usually with pointers and stuff. The idea behind a Linked List is that you can encode a list of things a series of Nodes, one "node" is nothing more than a thing that hold a value, and a way to get the next node. We also need to encode the concept of "There ISN'T a next node, you reached the end of the list". And if you are clever enough, you can start to see how the pieces come together and allows you to construct a linked list using just cons.
If we wanted to make a linked list (Which i would simply call a "list") of numbers in lisp we can define nodes using cons. We can place a number as the first argument and the next node as the second argument. We can also denote the terminating node, that tells us that we are at the end of the list with nil, so if then next node is nil, that means we reached the end of the list
The boring example would then be a list containing one element which would look something like this
(cons 8 nil)
We could get the element in this node with car, which would return 8, and get the next node with cdr. In this case cdr will return NIL, which is the terminating node and that would signal that we are in the last node of the list
It's not very exiting, but it's all we need to model our linked list! Lets try making a list of two elements now
(cons 8 (cons 9 nil))
Same logic as before, we can get the value of the first node with car and we can get the next node with cdr which would return the (cons 9 nil). And we can get the value of that node with car and it's corresponding next node which is the terminator and we reached the end
And indeed, if you type (cons 8 (cons 9 nil)) into the interpreter, you will get the same result as if you were to type (list 8 9). Since behind the scenes the ARE the same thing
Lets make a few more examples:
What about a list that contains one list? for example, we learned how to do (8 9) but what about ((8 9))?
We could simply take our whole (cons 8 (cons 9 nil)) thing and place into another node (cons VALUE NEXT) where next is nil (There is no next element) and value is our whole list, resulting in: (cons (cons 8 (cons 9 nil)) nil). And indeed, the interpreter prints ((8 9))
Armed with this knowledge let's give another go at your exercise. But let's be more fundamental about it, we can see that is is a list of four elements (lets call them a b c and d). We can make a list of them by connecting 4 nodes so:
(cons a
(cons b
(cons c
(cons d nil)
)
)
)
now let's thing about what a b c and d are. We can tell a and be are just numbers so they can be replaced pretty easily like this
(cons 1
(cons 3
(cons c
(cons d nil)
)
)
)
d is also pretty easy, is just a list containing a single element, we made one of those already and it looks like this (const 7 nil) so we can replace that as well
(cons 1
(cons 3
(cons c
(cons (cons 7 nil) nil)
)
)
)
And finally c is the most complicated one, because it is a list holding a list, but we can handle that no problem, we simply make a list of a single element (cons VALUE nil) and replace value with another list of a single element (cons 2 nil) and replace value with it so we get (cons (cons 2 nil) nil). Which we can replace in our final answer to get:
(cons 1
(cons 3
(cons (cons (cons 2 nil) nil)
(cons (cons 7 nil) nil)
)
)
)
Or back in a single line:
(cons 1 (cons 3 (cons (cons (cons 2 nil) nil) (cons (cons 7 nil) nil) )))
And there we go! You probably get the drill now it's a very simple concept, but it has a LOT of implications, which take a while to wrap your head around, and when you eventually do it, you get a glimpse of the ultimate power of the lisp programing language

Related

Racket macro that recursively processes a list argument

I'm trying to write a macro that recursively 'unwraps' the values of a list into individual values. For example, unwrap '(1 2 3)) would produce (separately):
(car '(1 2 3)) ; 1
(car (cdr '(1 2 3)) ; 2
(car (cdr (cdr '(1 2 3)) ; 3
This would be used like (+ (unwrap '(1 2 3))) ==> (+ 1 2 3). (I know you can use the standard libary apply for this, but I'm trying to write my own version).
My problem is that in writing the macro, I don't know how to recursively process the list argument passed into the unwrap macro. Here's what I've tried:
(define-syntax (unwrap stx)
(syntax-case stx ()
[(_ lst)
#`(begin (car lst) ; error at the last step since (car '()) is invalid
(unwrap (cdr lst)))]))
or
(define-syntax (unwrap stx)
(syntax-case stx ()
[(_ lst)
#`(if (null? lst)
'()
(car (unwrap (cdr lst))))])) ; infinite loops
These are both obviously wrong, but essentially I don't know write a macro that check the value of the input list (or matches against an empty list pattern) and returns something different in either scenario. It's also possible I'm approaching this entirely wrong, so any help would be greatly appreciated. Thank you!
You want
(+ (unwrap '(1 2 3))) ==> (+ 1 2 3)
but this is impossible. You are asking for unwrap to macroexpand to three disconnected forms, which is not allowed. Any macro must expand into exactly one form. So as you say in your question, for the example you gave, apply is the right answer.
For other possible usages, the answer is to back up a step and ask why you think this unwrap function would be useful: what cases do you hope to use it in? Then design a different solution, that works within the constraints of the language.

Reverse list in CLISP

I'm trying to write my own function to reverse list in LISP. The problem is input
(revert '(2 3 (4 5 (6))))
My code looks like this:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l)) (list (car l)))))
It returns
((4 5 (6)) 3 2)
instead of this:
(((6) 5 4) 3 2)
How can I fix it to work correctly?
Since you want to reverse sublists as well, you have to use REVERT on the CAR as well as CDR:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l))
(list (revert (car l))))))
This however requires you to handle the possibility that L might be an atom, which should be returned as is. Since NIL is also an atom you can just change the condition to check for ATOM instead of NULL.
(defun revert (list)
(if (atom list)
list
(append (revert (cdr list))
(list (revert (car list))))))
(revert '(2 3 (4 5 (6))))
;=> (((6) 5 4) 3 2)
In Common Lisp, it's preferred to use full words for names, so it's better to name l list. You could also name the function something like tree-reverse.

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)

How would one interleave elements of 2 lists in LISP?

Given 2 lists, how can you produce an output of a 3rd list which has its elements as an interleaved set of L1 and L2? If they are uneven length, nil should be inserted for holes. On a second note, how can I reverse a list? I am super new to LISP and simply modifying existing code... I'd really love to have a good explanation, not just code.
First, I guess you use Common Lisp, as it is the one most used in Lisp courses. So, my examples will be in CL. If you use Scheme, you will get almost the same code. If modern Clojure, it will need some changes, through an idea will be the same.
Interleave
To interleave 2 lists you must go through both of them, collecting elements by turns. You can use loop statement or recursion for this. I'll use recursion since it has more functional style and may be used in any lisp, not only CL. Also note, that there's a feature called tail recursion, which lets you write recursive function that will be compiled to a loop.
So, base skeleton for our function will be:
(defun interleave (l1 l2)
??????
(interleave ?????))
To collect items in recursive functions you will need to return them from each call and then cons together (for a tail recursion you must have one more parameter, which will accumulate values). So, the end of the function will be (cons current-value (interleave ????)).
Also you must alternate lists to take elements from with each other. You may have additional parameter, but you also may just swap them in a recursive call. So, code becomes:
(defun interleave (l1 l2)
?????
(cons current-value (interleave l2 l1)))
Any recursion must stop somewhere. In this case, it must stop when both lists are empty (nil).
This is one condition (let give it number 1), and there are some more conditions:
2. if the list to take from is empty, and the other one is not, we must take nil instead.
3. if both lists are not empty, take first element as a current-value and proceed with it's tail.
There's only one more condition that 2 lists can be in: list to take from is not empty, and the second one is. But in fact we don't care about this and may go forward with a rule number 3.
So, the code (and this is the final one):
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
Reverse
I'll show two implementations of this function: one with cond and another with built-in reduce function which is extremely useful in practice.
First approach for cond version is to go through the all list with a recursive calls and then go back, collecting elements:
(defun reverse-1-1 (li)
(if (eql li nil)
nil
(append (reverse-1-1 (rest li))
(list (first li)))))
But this is extremely inefficient, since append is O(n), and you must pass n elements, so the final complexity is O(n^2).
To reduce it you may use one more argument to the function (and make it tail recursive, if compiler lets you):
(defun reverse-1-2 (li)
(reverse-aux li nil))
(defun reverse-aux (li accumulator)
(if (eql li nil)
accumulator
(reverse-aux (rest li) (cons (first li) accumulator))))
That's you use one more parameter to collect your elements in while passing through the list, and then just return this accumulator.
There's one more interesting option. Lisp has extremely powerful function reduce (in other functional languages it is sometimes called fold, foldr, foldl or something like that). You may find description for it here, and I'll just show an example:
(defun reverse-2 (li)
(reduce #'cons li :from-end t :initial-value nil))
:from-end tells function to go through the the list from the end, and :initial-value tells to use as the very first reduced argument nil.
Note: in some implementations reduce with option :from-end true may first reverse list by itself, so if you need to create it from scratch or use the most efficient version, use reverse-1-2 instead.
In Common Lisp:
(defun merge-lists (lst1 lst2)
(let ((m (max (length lst1) (length lst2))))
(flatten (mapcar (lambda (a b) (list a b))
(append-nulls lst1 m)
(append-nulls lst2 m)))))
Examples:
(merge-lists '(1 2 3 4) '(5 6 7 8)) ;; => (1 5 2 6 3 7 4 8)
(merge-lists '(1 2 3 4) '(5 6 7)) ;; => (1 5 2 6 3 7 4 NULL)
(merge-lists '(1 2) '(5 6 7 8)) ;; => (1 5 2 6 NULL 7 NULL 8)
The helper functions flatten and append-nulls:
(defun flatten (tree)
(let ((result '()))
(labels ((scan (item)
(if (listp item)
(map nil #'scan item)
(push item result))))
(scan tree))
(nreverse result)))
(defun append-nulls (lst n)
(if (< (length lst) n)
(dotimes (i (- n (length lst)))
(setq lst (append lst (list 'null)))))
lst)
The answer above:
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
If one of your lists is longer than the other, you will get something like (1 2 3 4 nil 5).
Replace:
((eql l1 nil) (cons nil (interleave l2 l1)))
with:
((null l1) l2)
:P
An example of a more idiomatic solution in Common Lisp:
(defun interleave (a b)
(flet ((nil-pad (list on-list)
(append list (make-list (max 0 (- (length on-list) (length list)))))))
(loop for x in (nil-pad a b)
for y in (nil-pad b a)
append (list x y))))

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