LISP "Error Illegal function object..." - common-lisp

I just started learning lisp in my class. I'm doing a homework assignment in which I have to program a few very basic functions using some primitives operations such as car, cdr, cons, append, reverse, atom, eq, equal, and null.
So here is my code so far:
(defun union2 (l1 l2)
(cond ((null l1) l2)
((member((car l1) l2)) (union2((cdr l1) l2)))
(t (cons (car l1) (union2((cdr l1) l2)))))
)
When I try to run my test:
(union2 '(5 7 2 3 1) '(3 2 4 6 9))
I get an "Error: Illegal function object: (car l1)." I was under the impression that I was writing the code correctly. What am I doing wrong?
Thank you for your time.

Do not put extra parentheses around argument lists.
(member((car l1) l2)) should be (member (car l1) l2)
(union2((cdr l1) l2)) should be (union2 (cdr l1) l2)

Try using a compiler, like SBCL:
* (defun union2 (l1 l2)
(cond ((null l1) l2)
((member((car l1) l2)) (union2((cdr l1) l2)))
(t (cons (car l1) (union2((cdr l1) l2)))))
)
; in: DEFUN UNION2
; ((CAR L1) L2)
;
; caught ERROR:
; illegal function call
; (MEMBER ((CAR L1) L2))
;
; caught WARNING:
; The function was called with one argument, but wants at least two.
; ((CDR L1) L2)
;
; caught ERROR:
; illegal function call
; (UNION2 ((CDR L1) L2))
;
; caught WARNING:
; The function was called with one argument, but wants exactly two.
; ((CDR L1) L2)
;
; caught ERROR:
; illegal function call
; (UNION2 ((CDR L1) L2))
;
; caught WARNING:
; The function was called with one argument, but wants exactly two.
;
; compilation unit finished
; caught 3 ERROR conditions
; caught 3 WARNING conditions

Related

Prevent double invocation of recursive function in Common Lisp

I have that Lisp function:
(defun F(l)
(cond
((atom l) -1)
((>(F(car l))0)(+(car l)(F(car l))(F(cdr l))))
(t(F(cdr l)))
)
)
and I want to prevent double invocation of recursive function (F (car l)) in the second line of cond using a lambda function.
I tried that:
(defun F(l)
((LAMBDA (ff)
(cond
((atom l) -1)
((> ff 0)(+(car l) ff (F(cdr l))))
(t(F(cdr l)))
)
) (F (car l)))
)
but I get error :
CAR: 1 is not a list
at call (F '(1 2 3 4)).
Also I'm not sure if that correctly avoids double recursive call.
The reason you are getting this error is that you are calling (car l) always, even when l is, in fact, not a list.
To avoid this, only do that when needed:
(defun F(l)
(if (atom l) -1
(let* ((l1 (car l))
(f1 (F l1))
(f2 (F (cdr l))))
(if (plusp f1)
(+ l1 f1 f2)
f2))))

Palindrome check with recursion in Lisp

I have developed code to check through input to see if it is a palindrome or not but I am having difficulty figuring out how to print the output. I want the output to return "t" if the input is a palindrome and "nil" if not. Also a challenge that I wanted to give myself was to not use the reverse function so thats why my code is not as simple as it could be. Thanks in advance.
(defun palindromep(l)
(cond ((null l) nil (write nil))
(t (append (list (car l)) (palindromep (cdr l)) (list (car l) )))))
(palindromep '(a b b a))
(terpri)
(palindromep '(a b c b a))
(terpri)
(palindromep '(a b c))
(terpri)
(palindromep '(a (d e) (d e) a))
(terpri)
(palindromep '(a (d e) (e d) a))
Firstly, an empty list is a palindrome! If we reverse it, we get the same empty list.
Secondly, Lisp functions don't print their result values; they return these values.
In an interactive session, it is the listener which prints the resulting value(s) that emerge from the expression being evaluated. That expression itself doesn't have to print anything.
Therefore, we begin like this:
(defun palindromep (l)
(cond
((null l) t) ;; the empty list is a palindrome: yield true.
Note, by the way, that if we write this:
((null l) nil t) ;; the empty list is a palindrome: yield true.
that doesn't do anything. The extra nil expression is evaluated, producing nil, which is thrown away. The Lisp compiler will completely eliminate that.
What if the list is not a list at all, but an atom other than nil? Let's just go with that being a palindrome. A clarification of requirements is needed, though:
((atom l) t)
Now we know we are dealing with a non-empty list. If it has exactly one item, then it is a palindrome:
((null (cdr l)) t)
Now we know we are dealing with a list of two or more items. That is a palindrome if the first and last items are the same, and if the items in between them form a palindrome.
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
The whole thing:
(defun palindromep (l)
(cond
((null l) t)
((atom l) t)
((null (cdr l)) t)
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
Code golfing: in the cond construct described by ANSI CL, a clause is permitted to have just one form. If that forms yields a true value, then that value is returned. Thus we can remove the t's:
(defun palindromep (l)
(cond
((null l)) ;; t removed
((atom l)) ;; likewise
((null (cdr l))) ;; likewise
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
Documentation about the functions ldiff and last can be found here.
Further golfing: if we have this pattern (cond (A) (B) ... (t Z)) we can just replace it by (or A B ... Z):
(defun palindromep (l)
(or (null l)
(atom l)
(let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior)))))
cond is like a generalization of or that can specify an alternative result value for the each terminating true case.
To go on with code-golfing, since t or nil is expected, you can use only or and nil to express conditionals (and using short-circuitry of or and nil expressions).
Also it is good to be able to determine a :test keyword - since you want to control the crucial testing behavior.
To be able to use also inner lists, one could e.g. use equalp or even a custom comparison function.
(defun palindromep (l &key (test #'equalp))
(or (null l) (and (funcall test (car l) (car (last l)))
(palindromep (butlast (cdr l)) :test test))))
This evaluates
(palindromep '(a (d e) (d e) a))
as t but
(palindromep '(a (d e) (e d) a))
as nil.
Well, it is maybe a philosophical question, whether the latter should be t and the former nil.
To revert that behavior, we could write a custom testing function.
Like this:
(defun reverse* (l &optional (acc '()))
(cond ((null l) acc)
((atom (car l)) (reverse* (cdr l) (cons (car l) acc)))
(t (reverse* (cdr l) (cons (reverse* (car l) '()) acc)))))
(defun to-each-other-symmetric-p (a b)
(cond ((and (atom a) (atom b)) (equalp a b))
(t (equalp a (reverse* b)))))
Well, I use here some kind of a reverse*.
Then if one does:
(palindromep '(a (d e) (d e) a) :test #'to-each-other-symmetric-p) ;; NIL
;; and
(palindromep '(a (d e) (e d) a) :test #'to-each-other-symmetric-p) ;; T
Just to complete the other answers, I would like to point out that not using reverse will not only complicate your code enormously, but also make it far more inefficient. Just compare the above answers with the classic one:
(defun palindromep (l)
(equal l (reverse l)))
reverse is o(l), i.e. it takes time proportional to the length of the list l, and so does equal. So this function will run in o(l). You can't get faster than this.

CLisp - sorting and combining two lists in quicksort

I'm trying to implement quicksort in CLisp, and so far I'm able to partition the list around a pivot. However, when I try to combine and recursively sort the sublists, I get either a stack overflow or an error with let, and I'm not sure what's going wrong. Here's my code:
(defun pivot (n xs)
(list (getLesser n xs) (getGreater n xs))
)
(defun getLesser (m l)
(cond
((null l) nil)
((<= m (car l)) (getLesser m (cdr l)))
(t (cons (car l) (getLesser m (cdr l)))))
)
(defun getGreater (m l)
(cond
((null l) nil)
((> m (car l)) (getGreater m (cdr l)))
(t (cons (car l) (getGreater m (cdr l)))))
)
(defun quicksort (xs)
(cond
((null xs) nil)
(t
(let (partition (pivot (car xs) xs))
(cond
((null (car partition)) (cons (quicksort (cdr partition)) nil))
((null (cdr partition)) (cons (quicksort (car partition)) nil))
(t (append (quicksort (car partition)) (quicksort (cdr partition)))))))))
My idea was to have a local variable partition that is a list of 2 lists, where car partition is the list of number less than the pivot, and cdr partition is the list of numbers greater than the pivot. Then, in the final cond construct, if there were no numbers less than the pivot I would recursively sort the 2nd list; if there were no numbers greater than the pivot I would sort the 1st list; else I would recursively sort both and append them in order. Can anyone help me out?
Compiling the file gives you hints about wrong syntax.
GNU CLISP produces these diagnostics:
$ clisp -q -c foo.lisp
;; Compiling file /tmp/foo.lisp ...
WARNING: in QUICKSORT in lines 20..28 : Illegal syntax in LET/LET*: (PIVOT (CAR XS) XS)
Ignore the error and proceed
;; Deleted file /tmp/foo.fas
There were errors in the following functions:
QUICKSORT
1 error, 1 warning
SBCL produces similar diagnostics:
$ sbcl --eval '(compile-file "foo.lisp")' --quit
This is SBCL 1.3.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
; compiling file "/tmp/foo.lisp" (written 08 MAY 2019 08:58:54 PM):
; compiling (DEFUN PIVOT ...)
; compiling (DEFUN GETLESSER ...)
; compiling (DEFUN GETGREATER ...)
; compiling (DEFUN QUICKSORT ...)
; file: /tmp/foo.lisp
; in: DEFUN QUICKSORT
; (LET (PARTITION (PIVOT (CAR XS) XS))
; (COND ((NULL (CAR PARTITION)) (CONS (QUICKSORT #) NIL))
; ((NULL (CDR PARTITION)) (CONS (QUICKSORT #) NIL))
; (T (APPEND (QUICKSORT #) (QUICKSORT #)))))
;
; caught ERROR:
; The LET binding spec (PIVOT (CAR XS) XS) is malformed.
;
; compilation unit finished
; caught 1 ERROR condition
; /tmp/foo.fasl written
; compilation finished in 0:00:00.021
You can then look up the expected syntax in CLHS: http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/speope_letcm_letst.html
The syntax for LET is (LET BINDINGS . BODY), where BINDINGS is a list of bindings; each binding is a (SYMBOL VALUE) list. Alternatively, a binding can just be SYMBOL, which stands for (SYMBOL NIL). Your code is:
(let (partition (pivot (car xs) xs))
...)
Let's write one binding per line and normalize all bindings as a proper list:
(let ((partition nil)
(pivot (car xs) xs)))
...)
You can see that the code:
binds partition to NIL
has a malformed second binding: there are three elements, namely pivot, (car xs) and xs, which does not match the expected (SYMBOL VALUE) syntax.

Lisp common elements in a list

We've recently started learning Common Lisp in our class. I am trying to implement a function that takes two list and outputs their common elements. We are restricted to using basic functional forms.
(defun myCommon(L1 L2)
(cond
((null L1) nil) ;;check if the first list is empty
((null L2) nil) ;;check if the second list is empty
((eq (car L1) (car L2)) ((car L1) (myCommon (cdr L1) L2)))
(t (myCommon (cdr L1) L2)) ;;if they are not the same, recurse myCommon with L1 as (cdr L1)
)
)
My problem is that I cannot understand why it results as a type error (offending datum: (CAR L1)). It seems to be expecting a function type as far as I could make sense of it.
Error: TYPE-ERROR :DATUM (CAR L1) :EXPECTED-TYPE FUNCTION
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by COND.
TYPE-ERROR :DATUM (CAR L1) :EXPECTED-TYPE FUNCTION
Broken at COND.
Your problem is due to the fact that in the second branch of the cond, the expression which is evaluated when the condition about the equality of the two cars is true is: ((car L1) (myCommon (cdr L1) L2))).
Here you have a list with two elements ((car L1) (myCommon...)) in a position where a form is required (that is list with a structure like (function argument1 argument2 ...)). So the system gives an error since (car l1) is not a function. What I suppose you want to do is to produce a new list with those two arguments, which could be obtained for instance by “consing” them, like in (cons (car L1) (myCommon...)), so this is your function rewritten:
(defun myCommon(L1 L2)
(cond ((null L1) nil) ;;check if the first list is empty
((null L2) nil) ;;check if the second list is empty
((eq (car L1) (car L2)) (cons (car L1) (myCommon (cdr L1) L2)))
(t (myCommon (cdr L1) L2)))) ;;if they are not the same, recurse myCommon with L1 as (cdr L1)
Note that if you try this function for instance on: (mycommon '(1 2 3) '(1 2 3 4) you will find that the answer is (1) and not (1 2 3). This is because you are “consuming” only the first argument (by recurring on it with (cdr L1)). So, you need to correct the function “consuming” also the second argument when necessary.

Scheme: sequential execution

I need to do something basically like this:
(define test
(λ (ls1 ls2)
(cond
((empty? ls2) null)
(else
(append ls1 (car ls2)) (test ls1 (cdr ls2))) (displayln ls1))))
The issue is the else-clause and the function that follows it. I need both clauses of the else-clause to execute and then I need the last function to execute but I can't get the syntax right.
I need (test '(1 2 3) '(4 5 6)) to result in displaying '(1 2 3 4 5 6) and it has to use the recursive call.
Any advice is appreciated.
Thanks.
There is several problem there. First you make an append on a list and an atom (not a list)... at least if (car l2) is not a list. Second you probably think that (append l1 (list (car l2)) modifies l1. But this is not the case. The result is a new list.
To sequence your operation you can do as larsmans have said. But you can also write the following
(define (test l1 l2)
(if (null? l2)
(displayln l1)
(let ((l1-follow-by-car-l2 (append l1 (list (car l2)))))
(test l1-follow-by-car-l2 (cdr l2)) ))
This has exactly the same behavior.
If you desperately want to solve this recursively, and you don't care about the return value, use
(define (test l1 l2)
(if (null? l2)
(displayln l1)
(test (append l1 (list (car l2))) (cdr l2))))
(This is very inefficient btw: O(n × m) memory allocations.)

Resources