Reputation: 137
I am trying to create a function that accepts a list and a function as parameters and applies that function to each element in the List. Here is my attempt:
(defun filter(fn L)
(if (eq 0 (length L))
(print "list empty")
(print (mapcar (lambda (n) (#'fn n)) L))))
(print (filter #'evenp '(1 2 2 3 4)))
here is a second attempt:
(defvar R nil)
(defun filter(fn L)
(if (eq 0 (length L))
nil
(cons (R (funcall fn (car L)) filter(fn (cdr L))))))
(print(filter #'evenp '(1 2 2 3 4)))
But for some simply confusing and unexplainable reason, I get following error for the first one:
#'FN should be lambda expression.
and this one for the second:
Undefined function R
I have tried so many things but nothing has worked so far.
Edit:: Thank you for the help so far. This:
(defun filter(fn L)
(if (eq 0 (length L))
(print "list empty")
(remove-if-not #'fn '(1 2 3 4 5))))
(print (filter #'evenp '(1 2 2 3 4)))
This should do it. But I am still getting the
Undefined function FN
error. What to do???
Upvotes: 2
Views: 1401
Reputation: 60064
filter
is called remove-if-not
in Common Lisp:
(remove-if-not #'evenp '(1 2 3 4 5))
==> (2 4)
When you try to call a function stored in a variable (or passed into a
function as a parameter), you need to
use funcall
or apply
:
(mapcar (lambda (n) (funcall #'fn n)) L)
or just pass it along
to mapcar
:
(mapcar fn L)
This is a total mess. You need to learn Common Lisp syntax, there are many nice books (see want to learn common lisp).
The specific problem is that R
is in a function position (first list
element) but it is not defined as a function - it is a variable.
Even if you fix this problem, there are more problems there.
You should read a book and then work it out yourself, it will be a
useful exercise.
Basically, in Common Lisp parentheses are meaningful.
E.g., in C you can write x+y
, (x+y)
, (x)+(y)
&c and they all mean
the same.
In Common Lisp R
, (R)
, ((R))
&c are very different.
(defun filter(fn L)
(if (eq 0 (length L))
(print "list empty")
(remove-if-not #'fn '(1 2 3 4 5))))
Here you have a variable fn
, but you are using it as if it were a function (#'fn
).
You need to do
(remove-if-not fn '(1 2 3 4 5))
instead.
print
First, print
is virtually
never the right function to use in code. Use princ
, prin1
or
write
instead.
Second, Common Lisp REPL stands for Read-Eval-Print Loop, so you do NOT need to print the return value of your function explicitly.
You write your code for others (including yourself 6 months down the road) to read, not just for a computer to run. If you follow the conventions, including naming your variables and functions, parentheses placement, indentation &c, you make your code more readable.
zerop
Write (zerop X)
instead of (eq 0 X)
(actually, you should
use eql
for numbers, but this is
getting too hairy for now).
length
can be expensiveDo not scan the whole list if all you need to know is whether it is empty. IOW,
(if (zero (length l))
(print "the list is empty")
(mapcar ... l))
is better written as
(if (null l)
(print "the list is empty")
(mapcar ... l))
Upvotes: 9
Reputation: 85913
#'FN should be lambda expression.
You've got (fn (cdr L)) in your code, and fn can't be called like that. Just like earlier in that line, you need to do (filter fn (cdr L)), not filter(fn (cdr L)).
Undefined function R
Same thing here. You've got (cons (R ...)) where you're trying to call R as a function, but it's not. It's not really clear to me what you're trying to do with R, so I can't really offer any help there.
Upvotes: 2