funcall function error cannot take car lisp - lisp

What's wrong with this code?
(defun f (l)
(funcall #'(lambda (ff)
(cond
((null l)nil)
((listp (car l)) (append ff (f (cdr l)) (car ff)))
(t (list (car l)))))
(f (car l))))
If I enter (f '(( 1 2 3))) it gives me an error:
"Cannot take car of 1".
What's wrong?

Here is a more detailed explanation of the comment of #Sylwester, that answers correctly to the question.
If you write (f '((1 2 3)) then the function f is called, l is bound to ((1 2 3)), and the result is the application of the internal function (lambda (ff) (cond ...)) to the value of (f (car l)).
To perform this application, first (f (car l)) is evaluated to produce a value, and since l is bound to ((1 2 3)), its car is (1 2 3).
So, f is applied to the list (1 2 3), which is bound to l in the recursive call. This evaluation again means that fshould apply the internal function (lambda (ff) (cond ...)) to the value of (f (car l)), that is to (f 1).
The process is reapeated, l is bound this time to 1, and again fshould apply the internal function (lambda (ff) (cond ...)) to the value of (f (car l)), but, since l is now 1, the function tries to evaluate the (car 1), which produces the error that you have found.

Related

How the map function implemeted in racket

How does the map function implemented in racket and why, recursion or iteration.
Maybe some implementation example
How to implement map
The map function walks a list (or multiple lists), and applies a given function to every value of a list. For example mappiing add1 to a list results in:
> (map add1 '(1 2 3 4))
'(2 3 4 5)
As such, you can implement map as a recursive function:
(define (map func lst)
(if (empty? lst)
'()
(cons (func (first lst)) (map func (rest lst)))))
Of course, map can accept any number of arguments, with each element passed to the given prop. For example, you can zip two lists together using map list:
> (map list '(1 2 3) '(a b c))
'((1 a) (2 b) (3 c))
To implement this variable arity map, we need to make use of the apply function:
(define (map proc lst . lst*)
(if (empty? lst)
'()
(cons (apply proc (first lst) (map first lst*))
(apply map proc (rest lst) (map rest lst*)))))
Now, this does assume all of the given lists have the same length, otherwise you will get some unexpected behavior. To do that right you would want to run empty? on all lists, not just the first one. But...when you use it, you get:
> (map list '(a b c) '(1 2 3))
'((a 1) (b 2) (c 3))
Note that map here calls itself recursively 3 times. A faster implementation might do some unrolling to run faster. A better implementation would also do proper error checking, which I have elided for this example.
How Racket's map is implemented
If you open up DrRacket (using the latest Racket 7 nightly) and make the following file:
#lang racket
map
You can now right click on map and select Open Defining File. From here, you can see that map is renamed from the definition map2. The definition of which is:
(define map2
(let ([map
(case-lambda
[(f l)
(if (or-unsafe (and (procedure? f)
(procedure-arity-includes? f 1)
(list? l)))
(let loop ([l l])
(cond
[(null? l) null]
[else
(let ([r (cdr l)]) ; so `l` is not necessarily retained during `f`
(cons (f (car l)) (loop r)))]))
(gen-map f (list l)))]
[(f l1 l2)
(if (or-unsafe
(and (procedure? f)
(procedure-arity-includes? f 2)
(list? l1)
(list? l2)
(= (length l1) (length l2))))
(let loop ([l1 l1] [l2 l2])
(cond
[(null? l1) null]
[else
(let ([r1 (cdr l1)]
[r2 (cdr l2)])
(cons (f (car l1) (car l2))
(loop r1 r2)))]))
(gen-map f (list l1 l2)))]
[(f l . args) (gen-map f (cons l args))])])
map))

Check if element is in a tree

I need to write a function in Lisp that checks if an element N is in a tree TREE.
(defun TREE-CONTAINS (N TREE)
(cond ((equal TREE nil) nil)
((listp (CAR TREE)) (or (TREE-CONTAINS(N (CAR TREE)))
(TREE-CONTAINS(N (CDR TREE)))))
(t (cond ((equal N (CAR TREE)) t)
(t TREE-CONTAINS(N (CDR TREE)))))
)
)
For example, (TREE-CONTAINS (1 ((1 2 3) 4 5))) will return true. But I keep getting an error that says "Undefined function N called with arguments ((2 3))" when I test my code with this example: (TREE-CONTAINS 2 '(1 2 3)). Of course N is supposed to be 1 here but I don't know why it thinks N is a function. Any idea?
In the call to tree-contains, or any lisp function, you should not include parentheses around the arguments. It's (function-name arg1 arg2), not (function-name (arg1 arg2)).
So for a start, remove the parentheses around the arguments to the call (tree-contains(n (car tree))) like so: (tree-contains n (car tree)). Similarly for the next call to tree-contains in that or clause. Besides, the last condition: (t TREE-CONTAINS(N (CDR TREE))) should be called like this: (t (tree-contains n (cdr tree))).

List without nil in result Lisp

I have to delete all occurences of an element in a list from all levels.
My code is:
(defun sterge(e l)
(cond
((and (atom l) (equal e l)) nil)
((atom l) (list l))
(t (append (apply #'list (mapcar #' (lambda (l) (sterge e l)) l))))
)
)
(defun sterg(e l)
(car (sterge e l))
)
When I give:
(sterg 1 '(1 2 1 ( 1 2 1( 1 (1) (1)) (1) 3) (1)(2)))
it shows me the output:
((2 (2 (NIL NIL) NIL 3) NIL (2)))
How to delete that nil?? Thank you.
Instead of returning nil, consider returning sterge applied to the rest of the entity l. mapcar is not the best way to approach this problem; a recursive function is better (unless the assignment specifies using mapcar, of course.)
Hint: Treat l as if it were a list and test (car l), e.g., (atom (car l)), apply sterge to (cdr l).

Racket Insertion Sort function that can sort in ascending or descending order

I am attempting to write a DrRacket function that that can sort a list in ascending or descending order (by making the comparison operator a parameter). The sorting algorithm should be insertion sort. I called this second parameter cmp.
There are no warnings when I compile, but when I attempt to test the function; for example, (sort-list '(1 0 2 4) >), I receive this error:
sort-list: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
Here is my function as of now:
(define (sort-list l cmp)
(define first-element (if (not (null? l)) (car l) 0))
(cond ((null? l) (quote ()))
(else (cons (find-shortest l first-element cmp) (sort-list (remove-member l (find-shortest l first-element cmp)))))))
(define find-shortest
(lambda (tl b cmp)
(cond ((null? tl) b)
((cmp (car tl) b) (set! b (car tl)) (find-shortest (cdr tl) b cmp))
(else (find-shortest (cdr tl) b cmp)))))
(define remove-member
(lambda (tl2 a)
(cond ((null? tl2) (quote ()))
((= a (car tl2)) (cdr tl2))
(else (cons (car tl2) (remove-member (cdr tl2) a))))))

Lisp function explanation

I have this example in LISP that removes from every level of a list a given number:
(defun remove_aux (e l)
(cond
((equal e l) nil)
((atom l) (list l))
(t(list(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))))))
(defun remove_el (e l)
(car (remove_aux e l)))
So, if it run like this: (remove_el 2 '(1 2 3 ((2 3 2) 4))) => (1 3 ((3) 4))
What I don't exactly understand is how this line works: (t(list(apply 'append (mapcar #'(lambda (l) (sterge_aux e l)) l))))
If I have the line without list and append ((t(mapcar #'(lambda (l) (remove_aux e l)) l))) the result is ((1) NIL (3) ((NIL (3) NIL) (4)))) if it has append but not list ( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) ) then the result is (1 3 3 4) and I don't get why because I did (apply 'append '((1) NIL (3) ((NIL (3) NIL) (4))))) in the Common Lisp console and the result was ((1 3 (NIL (3) NIL) (4))) so I'm really confused. Can somebody explain to me how this all works step by step?
I've annotated the code below to, I hope, explain what's going on. You're probably getting confused because l is getting redefined within a lambda... so the t line (in your example) has 2 "l"s on it but the first one isn't the same as the second one.
(defun remove_aux (e l)
(cond
((equal e l) nil) ;if e equals l return nil
((atom l) (list l)) ;if l is an atom return a list with just l in it
(t ; otherwise...
(list ;create a list
(apply 'append ; whose contents are created by appending
; together the lists that come out of this mapcar
; (apply the append method)
(mapcar #'(lambda (l) ( ; iterate over each of the elements in list l
; the one after the lambda not the one
; being passed to the lambda.
; (this is a horrible name choice
; lambda(l-item) would be much better)
remove_aux e l
; recursively call this method
; with e (which was passed in at the start)
; and l which isn't the l passed in,
; but is an entry of it (see why naming's
; so important?)
; this returns a list
; which will get appended by the append
; with the results of all the other calls
; to remove_aux for each item in the outer l
)
) l)
)))))
(defun remove_el (e l)
(car (remove_aux e l)
)
)
;; append elements of each list in argument together
(append '(a) '(b) '(c d) '(e)) ; ==> (a b c d e)
;; append elements of each sublist in argument
(apply #'append '((a) (b) (c d) (e))) ; ==> (a b c d e)
;; apply function on each element of list into new list
(mapcar #'(lambda (x) (+ x 1)) '(1 3 5 6)) ; ==> (2 4 6 7)
So what does the default case do in your function.. Well it applies itself to each sublist of lst and wrap it in a list so if l is '(a y 2 z) and e is 2, well then the result from mapcar is '((a) (y) () (z)) which is then the argument to apply-append which connects the elements together into one list again. When connecting the lists the element that was to be removed is an empty list and it's effectively ignored in the concatenation process.
Since all the lists appended you create in the helper, you could replace the apply-append with (mapcan #'(lambda (l) (remove_aux e l)) l). A more obvious way to do this would be using reduce while a more efficient way might use loop.
A procedure that achieve what you want to achieve is essentially like below procedure:
(defun remove-all (e l)"Removes all occurrences of e from a list l."
(cond
((null l) '())
((equal e (car l)) (remove-all e (cdr l)))
((not (atom (car l)))
(cons (remove-all e (car l))
(remove-all e (cdr l))))
(t (cons (car l)
(remove-all e (cdr l))))))
;note: the e is not neccessarily an atom, the l is not necessarily a list of atoms.
The procedure in your question has unnecessarily cluttered pieces, like append, maps etc.
if you recomment below i will explain the algorithm.
have a nice hack.