Hey guys I need help with lisp function. I am supposed to create:
(myLast L)
Evaluates to the last element of list L.
eg. (myLast ‘(p a e g)) → g
I cant use all of the predefined forms for lisp only the ones we have been given in class:
(atom X)
(quote X)
‘X
(eq X Y)
(cons X L)
(car L)
(cdr L)
(list A B C)
(if X Y Z)
(cond (C1 S1) (C2 S2) …… (Cn Sn))
I thought I had it right when I put in:
(defun myLast (L)
(if ((eq L '()) (cdr L))
(car L)
(myLast (cdr L))))
However I am getting an error:
Error: The variable MYHW4.LISP is unbound.
Error signalled by EVAL
Backtrace: EVAL
Broken at SYSTEM::GCL-TOP-LEVEL.
I am completely new to LISP and trying to complete this assignment. I was hoping you guys could help me out and let me know why I am getting this error, and is my logic for the last functional form correct? Thanks!
There are multiple problems with your code.
You have excess parentheses. ((eq L '()) is not allowed as the only expression allowed at operator position is an anonymous function.
Your if only have a consequence expression but not a alternative. It isn't the last expression so it's dead code.
The you do car, also not in real position so far code also.
Tail expression is the recursion and is done unconditionally. It's called infinite recursion.
I think perhaps you meant something like this:
(defun myLast (list)
(if (null (cdr list))
(car list)
(myLast (cdr list))))
The error message is unrelated to your code. You probably typed (load myhw4.lisp) without quotes in which case your Lisp rightly think that you wanted to take the value bound to the variable myhw4.lisp, which does not exist. You need to quote strings "like so".
Also, ((eq L '()) ...) is problematic, since the first form is (eq ...) which is not a function or a lambda. That will signal an error..
The above makes your code wrong, but you are not far from it.
Related
I am trying to add a new atom after the search atom in the list.
when I try to call the function appendConst recursively, I am getting the below error -
[1]> (defun appendConst (OLD NEW L)
(cond
((null L) ())
((EQ (car L) OLD) (appendConst (cons OLD (cons NEW (cdr L)))) )
(T (cons (car L) (appendConst OLD NEW (cdr L))))
))
APPENDCONST
[2]> (appendConst 'a 'd '(a c d e a m k))
*** - EVAL/APPLY: Too few arguments (1 instead of at least 3) given to APPENDCONST
The following restarts are available:
ABORT :R1 Abort main loop
Break 1 [3]>
Here, using my input, after every occurrence of 'a' I want to add a 'd' in the whole list given.
I am new to this, how to call the function recursively here?
TIA.
Your first recursive call (where you add NEW) does in fact have only the one argument that the error says it does. Just adding the missing OLD and NEW won’t work, since the recursive call would find OLD again. So just do the consing outside the call as in your other case:
(cons OLD (cons NEW (appendConst OLD NEW (cdr L))))
Note that neither case is tail-recursive: to avoid stack usage proportional to the length of the list, you’d have to modify the list in place or do something more complicated like passing the head and the tail of the new list when recursing.
Lisp newbie here.
I am reading Paul Graham's book, ANSI Common Lisp.
On page 38 is an uncompress function. It takes a list of pairs, where the first item in the pair is a number to indicate how many of the second item there should be. For example, uncompressing this:
((3 a) (2 b) c)
should produce this:
(A A A B B C)
I typed the uncompress function into a Lisp interpreter (GCL-2.6.2-ANSI) and then tested it like this:
(uncompress '((3 A) B (2 C) (5 D)))
That produced this error message:
Error in IF [or a callee]: Too many arguments.
Fast links are on: do (use-fast-links nil) for debugging
Broken at IF. Type :H for Help.
1 (Abort) Return to top level.
Below is the uncompress function. I think that I faithfully typed what was written in the book. I have tested each piece and each piece seems to work correctly. Truthfully, I'm stuck. I don't know what's causing the error. I'd appreciate your help.
(defun uncompress (lst)
(if (null lst)
nil
(let (elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest))))
(defun list-of (n elt)
(if (zerop n)
nil
(cons elt (list-of (- n 1) elt))))
If you use editor indentation tools, the code looks like this:
(defun uncompress (lst)
(if (null lst)
nil
(let (elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest))))
That would have made it easier to spot this error. Syntactically it is wrong, since the IF does not take more than three forms.
(defun uncompress (lst)
(if (null lst) ; the IF has four subforms, one too many
nil
(let (elt (car lst)) ;<- variables ELT and CAR? Makes no sense
(rest (uncompress (cdr lst)))) ; <- not using the result?
(if (consp elt) ; <- fourth form in IF? Does not make sense.
(append (apply #'list-of elt)
rest)
(cons elt rest))))
In Common Lisp both IF and LET are special operators with built-in syntax.
In Lisp the syntax for LET usually is:
let ({var | (var [init-form])}*) form* => result*
In Common Lisp it is possible to add declarations on top of the body forms of the LET:
let ({var | (var [init-form])}*) declaration* form* => result*
The syntax for IF in Common Lisp is:
if test-form then-form [else-form] => result*
Indentation
Generally it is not a good idea to manually indent Lisp code. Let the editor or IDE do it. Make sure that all code is properly indented.
If you have a syntax problem: first re-indent the expression -> this makes sure that the code is properly indented and then makes finding problems easier. Next compile the code and read the compiler error message. Common Lisp has great compilers and some have quite good error reporting.
The code
The code is not great anyway: it uses recursion where higher-order functions exist or a LOOP would be better
This version got both: the higher-order MAPCAN and a LOOP:
(defun uncompress (list)
(mapcan #'expand-item list))
(defun expand-item (item)
(typecase item
(atom (list item))
(cons (destructuring-bind (n element) item
(loop repeat n collect element)))))
You have the most typical common lisp syntax error: incorrect use of parentheses!
Here is the correct version:
(defun uncompress (lst)
(if (null lst)
nil
(let ((elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest)))))
Since these kind of errors are so common when no specialized editor is used, I advise you to use an editor like Emacs or Vim to edit your programs.
I cannot think of a way to search a list to make sure it has all integers. I want to immediately return nil if there is non-integer data, and continue my function if there is not.
The recursive function I am trying to make will cons the car with the cdr of the list. With the attempts I have made, I am not able to return nil. I have only been able to ignore the non-integer data. E.g., (add-1-all '(1 2 3 a)) will return (2 3 4) after adding one to each number.
(defun add-1-all (L)
(if (null L)
L
(if (integerp (car L))
(cons (+ (car L) 1) (add-1-all (cdr L)))
nil)))
I do understand that the cons is making this happen, as the recursion is adding on to the list.
Your first sentence,
I cannot think of a way to search a list in Lisp to make sure it has all integers.
makes it sound like you want to check whether a list is all integers. You can check whether a list is all integers using every:
CL-USER> (every 'integerp '(1 2 3 4))
;=> T
CL-USER> (every 'integerp '(1 2 a 4))
;=> NIL
every will take care of short-circuiting, i.e., returning nil as soon as the first element failing the predicate is found.
However, your code makes it sound like you want to map over a list, collecting the value of a function applied to each integer and returning the collected values, except that if you encounter a non-integer, you return null. Perhaps the easiest way to do this is using the loop macro. A solution looks almost identical to the English specification:
CL-USER> (loop for x in '(1 2 3 4)
if (not (integerp x)) return nil
else collect (1+ x))
;=> (2 3 4 5)
CL-USER> (loop for x in '(1 2 a 4)
if (not (integerp x)) return nil
else collect (1+ x))
;=> NIL
Doing this with loop also has some advantages over a recursive solution. While some languages in the Lisp family (e.g., Schema) require tail call optimization, and some Common Lisp implementations do it too, it's not required in Common Lisp. As a result, it can be safer (e.g., you won't run out of stack space) if you use an iterative solution (e.g., with loop) rather than a recursive (even a tail-recursive) implementation.
The key is to use a helper function, and for that helper function to carry the answer along with it as it recurses, so that it can discard the whole thing at any time if necessary. Incidentally, this will also be tail recursive, meaning that it can deal with extremely long lists without running out of stack space.
(defun add-1-all (L)
(add-1-all-helper L nil))
(defun add-1-all-helper (L answer)
(if (null L)
answer
(if (integerp (car L))
(add-1-all-helper
(cdr L)
(cons (+ (car L) 1) answer)))))
I'm writing a function for a CLOS class that reverses the list element of an object of said class.
I have a method that will return the reverse list, but how do I make it set the object's list to that list? Can I have a instance variable in the function that stores the list then set the element to that? Or is there an easier way?
Here's the method as it is now:
(defun my-reverse (lst)
(cond ((null lst) ‘())
(t (append (my-reverse (cdr lst)) (car lst)))))
The object it is passed is (l my-list) and the accessor would then be (my-list-ls l).
Edit: Realized that cons doesn't work on 2 lists.
Edit2: What I assume the right code would be:
(defun my-reverse (l my-list)
(cond ((null (my-list-ls l) ‘())
(t (setf (my-list-ls l) (append (my-reverse (cdr (my-list-ls l)))
(car (my-list-ls l)))))))
If you want to modify an object's slot, you need to pass that object itself to your function, not just the value of the slot you want to change.
EDIT: regarding the edit2 of the question
I assume my-list is the name of the class, and you don't actually want to pass it to the function, right? In that case, you should substitute the defun with a defmethod. Also, it should be better to change the instance only once, after you reversed the whole list, instead of at each step. You could use an inner function for that:
(defmethod my-reverse ((l my-list))
(labels ((inner (list acc)
(if (endp list)
acc
(inner (rest list) (cons (first list) acc)))))
(setf (my-list-ls l) (inner (my-list-ls l) ()))))
EDIT 2: detailed explanation
defmethod is the alternative to defun for defining (polymorphic) methods. Though, if you don't need polymorphism, you could just use (defun my-reverse (l) for the first line.
labels is for inner function definitions. Here, it defines an inner function named inner with the two parameters list and acc. inner is the function that does the actual reversing, and it's a tail-recursive function because reversing goes naturally with tail-recursion. (It can build its result with cons and is therefore of linear complexity, whereas your solution needs append and thereby is of quadratic complexity, because cons itself is constant, but append is linear.)
first and rest are just alternate names for car and cdr, endp is mostly just an alternate name for null, with the difference that endp will signal an error if its argument isn't actually a list.
Finally, the last line calls inner with the original and an empty list as arguments, and assigns the result to the slot (aka instance variable).
I'm trying to write a function which checks if every element in the list x has property a, so I wrote:
(defun check (a x)
(if (listp x)
(eval (cons 'and (mapcar #'a x)))))
but it doesn't work. (Basically I want a to be the name of a function, say blablabla, and in the body of the check-function, by #'a I want to mean the function blablabla, instead of a function called a.) Now the code above doesn't work. I think in Lisp one should be able to plug in functions. How can I fix it?
(It is literally my first day on lisp, so it might be a stupid question ;)
and BTW I'm using Lispworks 6.0 personal version.)
There is no need to use the sharp-quote syntax here. Its purpose is to use a function name in a variable position, but a is a variable already. Just write a instead of #'a.
You don't need eval you can use apply.
To the problem: You need funcall because you provide a as argument. (Edit: Not in this case.) By quoting you just refer to the function a not the a in this function.
(defun check (a xs)
(if (listp xs)
(every #'identity (mapcar a
xs))))
Better, use loop:
(defun check (a xs)
(if (listp xs)
(loop for x in xs
always (funcall a x))))
Best, use every:
(defun check (a xs)
(if (listp xs)
(every a xs)))
Here is how I would write something like your check function. I tried to give it a more descriptive name.
(defun are-all-elements-fullfilling-fun-p (fun ls)
(every #'identity (mapcar fun ls)))
Edit: Note that a shorter and better definition is
(defun are-all-elements-fullfilling-fun-p (fun ls)
(every fun ls)))
Now let's say we want to call it with this function. Note that I tend to use declarations when possible. I quite often screw something up and debugging is easy if the compiler can figure the error out. Also the code will run faster.
(defun is-even-p (n)
(declare (type number n))
(the boolean (= 0 (mod n 2))))
You have to place the #' here:
(are-all-elements-fullfilling-fun-p #'is-even-p '(1 2 3 4))
(are-all-elements-fullfilling-fun-p #'is-even-p '(38 2 4))