I have a Lisp function which returns either the MAX of two values, or the MIN of two values. Right now my code has some relatively complex expressions to evaluate VALUE1 and VALUE2.
(defun treemax (bilist &optional ismin)
(cond
;; Compute minimum
(ismin (min (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))
;; Compute maximum
(t (max (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))))
The problem here is that COMPLEX_EX开发者_运维百科PRESSION_1 and COMPLEX_EXPRESSION_2 actually take up many many lines of code. I would really like to not repeat them. Is there a more efficient way of calling this?
Essentially what I'm trying to do is a unary-if on functions rather than values. If you are familiar with C or its variants, essentially the concept I'm looking for is:
((ismin ? min : max) COMPLEX_EXPRESSION_1 COMPLEX_EXPRESSION_2)
Whereby I conditionally select which function to send the arguments to. Does this make sense?
(defun treemax (bilist &optional ismin)
(funcall (if ismin #'min #'max)
(COMPLEX_EXPRESSION_1)
(COMPLEX_EXPRESSION_2)))
Surely, this is better:
(defun treemax (bilist &optional (op #'max))
(funcall op (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))
Then, simply pass in #'min
as argument 2 if you want to use min
instead.
(Of course, zakovyrya's answer works too.)
Generally, if you need to write the same code more than once, use a function to capture the code and then call it more than once.
(defun treemax (bilist &optional ismin)
(cond
(ismin (min (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))
(t (max (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))))
-->
(defun treemax (bilist &optional ismin)
(flet ((f1 () (COMPLEX_EXPRESSION_1))
(f2 () (COMPLEX_EXPRESSION_2))))
(cond
(ismin (min (f1) (f2)))
(t (max (f1) (f2))))))
This is one of the things that Lisp is very good at. You can assign functions to variables and then pass arguments to them with apply
or funcall
(and in Scheme it's actually even easier). Here's an example:
(defun treemax (bilist &optional ismin)
(let ((op (if ismin #'min #'max)))
(funcall op (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2))))
(You could of course also just bind COMPLEX_EXPRESSION_1
and COMPLEX_EXPRESSION_2
to variables, but that would still create more repetition.)
精彩评论