i just have started to learn function programming and it is a bit confusing for me, i have a task now: remove all duplicates from the row with lists, so: input row:
(SETQ X (LIST 2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-3))
I want output be like this : (2 -3 (4 3 0)(-4)()) I want to make it with recursion. I have some conceptual questions: how can i remove an element from list or i should make a new one for output? In other programming languages every step of recursion has it own scope for variables, is it same here? Please, can you describe the way, how would you do this?
Btw, i am trying to run this code:
(SETQ X (LIST 2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-3))(DEFUN SEARCHDEEP (WHAT WHERE)
(COND
((NULL WHERE) NIL)
(T (OR
(COND
((ATOM (CAR WHERE)) (EQUAL WHAT (CAR WHERE)))
(T (SEARCHDEEP WHAT (CAR WHERE)))
)
(SEARCHDEEP WHAT (CDR WHERE))
)
)
))
(DEFUN REMDOUBLES (INPUT OUTPUT)(
(COND
((NULL INPUT) NILL)
(T
(REMDOUBLES (CDR INPUT) OUTPUT)
(PRINT INPUT)
)
)))
(REMDOUBLES X NIL)
But i am getting this error, what does it mean?
SYSTEM::%EXPAND-FORM: (COND ((NULL INPUT) NILL) (T (REMDOUBLES (CDR INPUT) OUTPUT) (PRINT INPUT))) should be a lambda expression
In functional programming you don't remove elements from the arguments so you most definitely will make a new list, however in many cases you can share structure (tails) that are the same in the argument and the result.
Common Lisp is lexically scoped. That means that free variables that existed when the function was created plus the global scope is known in addition to bound variables, which would be bound unqiuely for each use just like the other languages you might know.
"something should be a lambda expression" is a Common Lisp error when you try to have an expression in operator position. eg. the Scheme code ((if (< x 10) + -) 5 10)
becomes either 15
or -5
based on what function the expression in operand position evaluates to. In Common lisp you can either have a symbol, eg. like +
in (+ 1 2)
or a lambda eg. ((lambda (x) (* x x)) 10)
. You tried ((cond ...))
which would work in Scheme but not in Common Lisp. In Common Lisp you need to do (funcall (if (< x 10) #'+ #'-) 5 10)
. Since the parentheses are almost put as curlies in C# I guess they are misplaced just as if someone would add a esxtra set of () in the end of a statement someFun(arg)()
when someFun
doesn't return a function.
I would have solved your code like this:
;; setq is for mutating, defparameter is a good option to make a global variable
(defparameter *test* '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -3))
(defun unique-elements (lst)
(let ((h (make-hash-table :test 'equal)))
(labels ((aux (lst)
(cond ((null lst) '())
((consp (car lst))
(let ((a (aux (car lst))))
(if (null a)
(aux (cdr lst)) ; don't include empty elements
(cons a (aux (cdr lst))))))
((gethash (car lst) h)
(aux (cdr lst)))
(t (setf (gethash (car lst) h) t)
(cons (car lst) (aux (cdr lst)))))))
(aux lst))))
(unique-elements *test*) ; ==> (2 -3 (4 3 0) (-4))