Помогите уменьшить функцию Lisp - PullRequest
3 голосов
/ 07 февраля 2011

У меня есть функция Lisp, которая возвращает либо MAX двух значений, либо MIN двух значений.Прямо сейчас мой код имеет несколько относительно сложных выражений для оценки VALUE1 и 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)))))

Проблема здесь в том, что COMPLEX_EXPRESSION_1 и COMPLEX_EXPRESSION_2 на самом деле занимают много много строк кода.Я действительно хотел бы не повторять их.Есть ли более эффективный способ вызова этого?

По сути, я пытаюсь сделать унарную функцию, если не значения.Если вы знакомы с C или его вариантами, по сути, я искал следующую концепцию:

((ismin ? min : max) COMPLEX_EXPRESSION_1 COMPLEX_EXPRESSION_2)

, и поэтому я условно выбираю, в какую функцию отправлять аргументы.Имеет ли это смысл?

Ответы [ 4 ]

9 голосов
/ 07 февраля 2011
(defun treemax (bilist &optional ismin)
    (funcall (if ismin #'min #'max) 
             (COMPLEX_EXPRESSION_1) 
             (COMPLEX_EXPRESSION_2)))
9 голосов
/ 07 февраля 2011

Конечно, это лучше:

(defun treemax (bilist &optional (op #'max))
  (funcall op (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2)))

Затем просто введите #'min в качестве аргумента 2, если вы хотите использовать min вместо.

(Конечно, ответ заковыря тоже работает.)

2 голосов
/ 08 февраля 2011

Как правило, если вам нужно написать один и тот же код более одного раза, используйте функцию для захвата кода, а затем вызывайте его несколько раз.

(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))))))
0 голосов
/ 07 февраля 2011

Это одна из тех вещей, в которых Лисп очень хорош. Вы можете назначать функции переменным, а затем передавать им аргументы с помощью apply или funcall (а на схеме это даже проще). Вот пример:

(defun treemax (bilist &optional ismin)
  (let ((op (if ismin #'min #'max)))
    (funcall op (COMPLEX_EXPRESSION_1) (COMPLEX_EXPRESSION_2))))

(Конечно, вы также можете просто связать COMPLEX_EXPRESSION_1 и COMPLEX_EXPRESSION_2 с переменными, но это все равно создаст больше повторений.)

...