Вы можете сделать это, составив предикаты. Если у вас есть предикат, который может сравнивать переменные и предикат, который может сравнивать коэффициенты, то вы можете легко создать новый предикат, который проверяет один, возвращая определенный ответ, если первый предикат дает определенный ответ или откладывается на второй предикат , в случае, если это не так. Это будет повторно использоваться для других применений, тоже:
(defun and-then (original-predicate next-predicate)
"Returns a new predicate constructed from ORIGINAL-PREDICATE and
NEXT-PREDICATE. The new predicate compares two elements, x and y, by
checking first with ORIGINAL-PREDICATE. If x is less than y under
ORIGINAL-PREDICATE, then the new predicate returns true. If y is less
than x under ORIGINAL-PREDICATE, then the new predicate returns false.
Otherwise, the new predicate compares x and y using NEXT-PREDICATE."
(lambda (x y)
(cond
((funcall original-predicate x y) t)
((funcall original-predicate y x) nil)
(t (funcall next-predicate x y)))))
Тогда это достаточно легко сделать вызов (и-то «переменной <» коэффициент <).Во-первых, некоторые аксессоров и предикаты:
(defun term-coefficient (term)
(first term))
(defun coefficient< (term1 term2)
(< (term-coefficient term1)
(term-coefficient term2)))
(defun term-variable (term)
(second term))
(defun variable< (term1 term2)
(string< (term-variable term1)
(term-variable term2)))
Теперь тест:
(defparameter *sample*
'((1 x)(2 y)(1 x)(2 x)(3 y)(2 y)))
CL-USER> (sort (copy-list *sample*) 'coefficient<)
((1 X) (1 X) (2 Y) (2 X) (2 Y) (3 Y))
CL-USER> (sort (copy-list *sample*) 'variable<)
((1 X) (1 X) (2 X) (2 Y) (3 Y) (2 Y))
CL-USER> (sort (copy-list *sample*) (and-then 'variable< 'coefficient<))
((1 X) (1 X) (2 X) (2 Y) (2 Y) (3 Y))
Вы могли бы определить сравнения-на функции для создания некоторых из этих функций предиката, которые могли бы сделать их определения немного проще или, возможно, полностью удалить.
(defun compare-by (predicate key)
"Returns a function that uses PREDICATE to compare values extracted
by KEY from the objects to compare."
(lambda (x y)
(funcall predicate
(funcall key x)
(funcall key y))))
Вы можете просто определения предиката:
(defun coefficient< (term1 term2)
(funcall (compare-by '< 'term-coefficient) term1 term2))
(defun variable< (term1 term2)
(funcall (compare-by 'string< 'term-variable) term1 term2))
или избавиться от них полностью:
(defun varsort (p1)
(sort (copy-list p1)
(and-then (compare-by '< 'term-coefficient)
(compare-by 'string< 'term-variable))))
Вклад в Stack Overflow лицензированы в соответствии с условиями, что позволяет копировать и воспроизведение. Это нормально, чтобы копировать и повторно использовать вещи, но атрибуция требуется. Хотя вы изменили фактические имена функций, кажется, что ваши аксессоры ** get-number ** и ** get-variable **, а также тело вашего ** varsort ** в значительной степени копируются из [мой ответ на ваш предыдущий вопрос] (http://stackoverflow.com/a/34043773/1281433). Хорошо воспроизводить их так, но вы должны, вероятно, включить ссылку на ваш более ранний вопрос здесь. –