I've just started leaning Common Lisp and I don't know why the code below returns 3:
(progn
(setq lista '(1 2))
(setq listb lista)
(setf (nth 1 listb) 3)
(nth 1 lista))
Can you help me, please?
Setq does not copy things. After (setq listb lista), both names point to the same list. When you modify it using one name, it also changes under the other.
If you want to create a copy, use copy-list, copy-tree, copy-alist, or copy-seq (see the CLHS). Also, don't modify literal data (things you quote (') are literal data).
(let* ((list-a (list 1 2))
(list-b (copy-list list-a)))
(setf (nth 1 list-b) 3)
(nth 1 list-a))
Related
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.
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.
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)
I need a recursive LISP function that enumerates the number of elements in any list of numbers > 3. I'm not allowed to use lets, loops or whiles and can only use basic CAR, CDR, SETQ, COND, CONS, APPEND, PROGN, LIST...
This is my attempt at the function:
(defun foo (lst)
(COND ((null lst) lst)
(T (IF (> (CAR lst) 3)
(1+ (foo (CDR lst)))
(foo (CDR lst)) ) ) ) )
The function call:
(foo '(0 1 2 3 4 5 6))
Your code is pretty close to correct, just a small mistake in the base case:
For the empty list you return the empty list. So if you have the list (6), you add 6 to foo of the empty list, which is the empty list. That does not work because you can't add a number to a list.
You can easily fix it by making foo return 0 instead of lst when lst is empty.
As a style note: Mixing cond and if like this, seems a bit redundant. I would write it like this, using only cond instead:
(defun foo (lst)
(cond
((null lst)
0)
((> (car lst) 3)
(1+ (foo (cdr lst))))
(T
(foo (cdr lst)))))
Some stylistic points:
There's no need to put some Lisp built-ins in uppercase. It's not 1958 anymore!
But if you are going to put built-ins in uppercase, why not DEFUN and NULL?
You have an if inside the last branch of your cond. This is redundant. Since the purpose of cond is testing conditions, why not use it?
There's no need to space out your closing parentheses like that. No-one counts parentheses these days, we have parenthesis-matching editors.
Lisp has separate namespaces for functions and values, so you don't have to call your argument lst to avoid conflicting with the built-in function list.
If you were programming this for real, of course you'd use count-if:
(count-if #'(lambda (x) (> x 3)) '(0 1 2 3 4 5 6))
==> 3
One save you can have on duplication of the recursive call:
(defun foo (l)
(if (null l) 0 ; if list is empty, return 0
(+ (if (> (car l) 3) 1 0) ; else +1 if condition is satisfactory
(foo (cdr l))))) ; plus the result from the rest
I have been searching everywhere for the following functionality in Lisp, and have gotten nowhere:
find the index of something in a list. example:
(index-of item InThisList)
replace something at a specific spot in a list. example:
(replace item InThisList AtThisIndex) ;i think this can be done with 'setf'?
return an item at a specific index. example:
(return InThisList ItemAtThisIndex)
Up until this point, I've been faking it with my own functions. I'm wondering if I'm just creating more work for myself.
This is how I've been faking number 1:
(defun my-index (findMe mylist)
(let ((counter 0) (found 1))
(dolist (item mylist)
(cond
((eq item findMe) ;this works because 'eq' checks place in memory,
;and as long as 'findMe' was from the original list, this will work.
(setq found nil)
(found (incf counter))))
counter))
You can use setf and nth to replace and retrieve values by index.
(let ((myList '(1 2 3 4 5 6)))
(setf (nth 4 myList) 101); <----
myList)
(1 2 3 4 101 6)
To find by index you can use the position function.
(let ((myList '(1 2 3 4 5 6)))
(setf (nth 4 myList) 101)
(list myList (position 101 myList)))
((1 2 3 4 101 6) 4)
I found these all in this index of functions.
find the index of something in a list.
In Emacs Lisp and Common Lisp, you have the position function:
> (setq numbers (list 1 2 3 4))
(1 2 3 4)
> (position 3 numbers)
2
In Scheme, here's a tail recursive implementation from DrScheme's doc:
(define list-position
(lambda (o l)
(let loop ((i 0) (l l))
(if (null? l) #f
(if (eqv? (car l) o) i
(loop (+ i 1) (cdr l)))))))
----------------------------------------------------
> (define numbers (list 1 2 3 4))
> (list-position 3 numbers)
2
>
But if you're using a list as a collection of slots to store structured data, maybe you should have a look at defstruct or even some kind of Lisp Object System like CLOS.
If you're learning Lisp, make sure you have a look at Practical Common Lisp and / or The Little Schemer.
Cheers!
Answers:
(position item sequence &key from-end (start 0) end key test test-not)
http://lispdoc.com/?q=position&search=Basic+search
(setf (elt sequence index) value)
(elt sequence index)
http://lispdoc.com/?q=elt&search=Basic+search
NOTE: elt is preferable to nth because elt works on any sequence, not just lists
Jeremy's answers should work; but that said, if you find yourself writing code like
(setf (nth i my-list) new-elt)
you're probably using the wrong datastructure. Lists are simply linked lists, so they're O(N) to access by index. You might be better off using arrays.
Or maybe you're using lists as tuples. In that case, they should be fine. But you probably want to name accessors so someone reading your code doesn't have to remember what "nth 4" is supposed to mean. Something like
(defun my-attr (list)
(nth 4 list))
(defun (setf my-attr) (new list)
(setf (nth 4 list) new))
+2 for "Practical Common Lisp". It is a mixture of a Common Lisp Cookbook and a quality Teach Yourself Lisp book.
There's also "Successful Common Lisp" (http://www.psg.com/~dlamkins/sl/cover.html and http://www.psg.com/~dlamkins/sl/contents.html) which seemed to fill a few gaps / extend things in "Practical Common Lisp".
I've also read Paul Graham's "ANSI Common Lisp" which is more about the basics of the language, but a bit more of a reference manual.
I have to agree with Thomas. If you use lists like arrays then that's just going to be slow (and possibly awkward). So you should either use arrays or stick with the functions you've written but move them "up" in a way so that you can easily replace the slow lists with arrays later.