问题
Say there is a function F. I want to pass a list of functions as an argument into function F.
Function F would go through each function in the list one by one and apply each one to two integers: x and y respectively.
For example, if the list = (plus, minus, plus, divide, times, plus) and x = 6
and y = 2
, the output would look like this:
8 4 8 3 12 8
How do I implement this in common Lisp?
回答1:
There are many possibilities.
CL-USER> (defun f (x y functions)
(mapcar (lambda (function) (funcall function x y)) functions))
F
CL-USER> (f 6 2 (list #'+ #'- #'+ #'/ #'* #'+))
(8 4 8 3 12 8)
CL-USER> (defun f (x y functions)
(loop for function in functions
collect (funcall function x y)))
F
CL-USER> (f 6 2 (list #'+ #'- #'+ #'/ #'* #'+))
(8 4 8 3 12 8)
CL-USER> (defun f (x y functions)
(cond ((null functions) '())
(t (cons (funcall (car functions) x y)
(f x y (cdr functions))))))
F
CL-USER> (f 6 2 (list #'+ #'- #'+ #'/ #'* #'+))
(8 4 8 3 12 8)
CL-USER> (defun f (x y functions)
(labels ((rec (functions acc)
(cond ((null functions) acc)
(t (rec (cdr functions)
(cons (funcall (car functions) x y)
acc))))))
(nreverse (rec functions (list)))))
F
CL-USER> (f 6 2 (list #'+ #'- #'+ #'/ #'* #'+))
(8 4 8 3 12 8)
CL-USER> (defun f (x y functions)
(flet ((stepper (function result)
(cons (funcall function x y) result)))
(reduce #'stepper functions :from-end t :initial-value '())))
F
CL-USER> (f 6 2 (list #'+ #'- #'+ #'/ #'* #'+))
(8 4 8 3 12 8)
And so on.
The first two are readable, the third one is probably how a rookie in a first Lisp course would do it, the fourth one is still the rookie, after he heard about tail call optimization, the fifth one is written by an under cover Haskeller.
来源:https://stackoverflow.com/questions/16116590/passing-a-list-of-functions-as-an-argument-in-common-lisp