I've just started learning lisp, and I'm trying to write a 'foreach'
function, ala perl. Can someone tell me why the following code gets me ***
- EVAL/APPLY: too few arguments given to :LAMBDA?
(defun get-list-entry (l n)
(if (= n 0)
(first l)
(get-list-entry l (- l 1))
)
)
(defun unilist (x)
(if (= (type-of x) (type-of '(x))) x (cons x nil)))
(defun foreach (l cmd)
(if (= (list-length l) 0) nil
(append
(unilist (apply cmd (first l)))
(foreach (rest l) cmd)
)
)
)
(foreach '("x" "y" "z") (lambda (x) (write-line x)))
--
bd has lost all his data - donate your bits to the bd_'s harddrive
restoration drive! One free campaign pin per bit bucket!
Geoffrey Summerhayes wrote:
>
> "bd" <·······@users.sf.net> wrote in message
> ··················@ID-151211.user.dfn.cis.de...
>> I've just started learning lisp, and I'm trying to write a 'foreach'
>> function, ala perl. Can someone tell me why the following code gets me
> ***
>> - EVAL/APPLY: too few arguments given to :LAMBDA?
>
> Already done, read up on map and its relatives.
>
> (mapcar (lambda (x) (write-line x)) '("X" "Y" "Z"))
I don't understand...
> Not the usual idea, if (cmd (first l)) returns 1, (1 1), and 1 you'll get
> (1
> 1 1 1) instead of (1 (1 1) 1)
> Does foreach in perl actually do this?
No, foreach evaluates a given block of code for each element in a list,
putting the elements in a scalar variable each time through.
--
bd has lost all his data - donate your bits to the bd_'s harddrive
restoration drive! One free campaign pin per bit bucket!
bd <·······@users.sf.net> writes:
>
> No, foreach evaluates a given block of code for each element in a list,
> putting the elements in a scalar variable each time through.
Have not read all but as pointed out before the map functions do that
quite well or if you have a list dolist is you're friend
(defun for-each (fun list)
(dolist (item list)
(funcall fun item)))
or using the loop facility
(defun for-each-with-loop (fun list)
(loop for item in list
do (funcall fun item)))
Regards
Friedrich
In article <·············@ID-151211.user.dfn.cis.de>, bd wrote:
>Can someone tell me why the following code gets me ***
> - EVAL/APPLY: too few arguments given to :LAMBDA?
>
> (defun get-list-entry (l n)
> (if (= n 0)
> (first l)
> (get-list-entry l (- l 1))
> )
> )
Lisp has a function called NTH which does this.
(nth 1 '(1 2 3)) yields 2.
> (defun unilist (x)
> (if (= (type-of x) (type-of '(x))) x (cons x nil)))
This is cryptic because the x in '(x) is not evaluated; it is just
a dummy symbol. And note that Lisp has no ``list of 1 element'' type.
The type of '(x) is cons. Also, don't compare types with the =
operator, they are not numbers. So your function means this:
(if (consp x)
x
(cons x nil))
In other words, if x is a cons, then return it, otherwise return a cons whose
CAR is x. The consp function is a standard predicate for asking whether an
object is a cons. To test whether an object is one of several types, and take
action, use the typecase or etypecase macros.
> (defun foreach (l cmd)
> (if (= (list-length l) 0) nil
> (append
> (unilist (apply cmd (first l)))
You want funcall here, since you just want to call a function and give
it a single parameter. The apply function is used when you want to turn the
items of a list into individual parameters. The last parameter of apply must
be a list, so for example
(apply #'mangle 1 2 3 4 (list 5 6))
is equivalent to (mangle 1 2 3 4 5 6). The first four arguments
are passed down straight, and the last one is a list which is
``unpacked'' to produce the remaining arguments.
> (foreach '("x" "y" "z") (lambda (x) (write-line x)))
Of course, Lisp doesn't need your heroic effort, because
the for-each constructs are already there:
(mapc #'write-line '("x" "y" "z"))
(dolist (line '("x" "y" "z"))
(write-line line))
bd <·······@users.sf.net> writes:
> I've just started learning lisp, and I'm trying to write a 'foreach'
> function, ala perl.
First of all it is Perl that has a `foreach' statement similar to the
godzillion ones that have appeared in Lisp over the years :)
Can someone tell me why the following code gets me ***
> - EVAL/APPLY: too few arguments given to :LAMBDA?
>
> (defun get-list-entry (l n)
> (if (= n 0)
> (first l)
> (get-list-entry l (- l 1))
> )
> )
This function you wrote is built in. It is called `elt'.
> (defun unilist (x)
> (if (= (type-of x) (type-of '(x))) x (cons x nil)))
What is that you are trying to do here? Already it looks like you
have a mistake.
(type-of '(x))
will always return
cons
The rest is funky.
>
> (defun foreach (l cmd)
> (if (= (list-length l) 0) nil
> (append
> (unilist (apply cmd (first l)))
> (foreach (rest l) cmd)
> )
> )
> )
(dolist (x l) (cmd x)) ?
>
> (foreach '("x" "y" "z") (lambda (x) (write-line x)))
This is called `map'.
(map nil (lambda (x) (print x)) '("x" "y" "z"))
Or you can do it using the standard DOLIST and LOOP constructs
(dolist (x l)
(funcall (lambda (x) (print x)) x)) ; Note the proper scoping of 'x'!
(loop for x in l
do (funcall (lambda (z) (print z)) z))
Cheers
--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.