ho cercato di trovare un'attuazione rapida quelli in Common Lisp, e questo è quello che ho ottenuto finora:Come rimuovere la ridondanza nel codice Lisp?
(defun quick-sort (list)
(if (cdr list)
(let ((pivot (car list)))
(append (quick-sort (remove-if-not (lambda (n) (< n pivot)) list))
(remove-if-not (lambda (n) (= n pivot)) list)
(quick-sort (remove-if-not (lambda (n) (> n pivot)) list))))
list))
A quanto pare funziona, ma penso che ci sia troppa ripetizione in quel codice. In sostanza, abbiamo tre volte:
(remove-if-not (lambda (n) (< n pivot)) list)
L'unico modo in cui le tre chiamate differiscono è di gran >
vs =
vs <
.
Quindi la mia domanda è: come posso rimuovere quella ridondanza e rendere il codice più leggibile e più compatto?
Naturalmente potrei estrarre le cose a una funzione, come ad esempio:
(defun which (operator pivot list)
(remove-if-not (lambda (n) (funcall operator n pivot)) list))
(defun quick-sort (list)
(if (cdr list)
(let ((pivot (car list)))
(append (quick-sort (which #'< pivot list))
(which #'= pivot list)
(quick-sort (which #'> pivot list))))
list))
Ma in qualche modo io non sono davvero convinto se questo è l'approccio migliore. È ancora maldestro dover restituire pivot
e list
ancora e ancora.
Ho anche avuto l'idea di utilizzare flet
, il che rende il corpo reale della funzione più leggibile, ma si muove solo la complessità da qualche altra parte:
(defun quick-sort (list)
(if (cdr list)
(let ((pivot (car list)))
(flet ((left() (remove-if-not (lambda (n) (< n pivot)) list))
(middle() (remove-if-not (lambda (n) (= n pivot)) list))
(right() (remove-if-not (lambda (n) (> n pivot)) list)))
(append (quick-sort (left))
(middle)
(quick-sort (right)))))
list))
Eventuali altri approcci?
Dai un'occhiata a questa implementazione di quicksort in Lisp che Kent Pitman descrive in [Sheep Trick] (http://www.maclisp.info/pitmanual/funnies.html#sheep_trick). –