;;; code commun a toutes les solutions (defclass person () ((age :initarg :age :accessor age) (size :initarg :size :accessor size))) (defparameter *people* (loop for (age size) in '((25 181) (10 152) (55 172) (2 111) (31 163) (29 189) (42 166) (20 172)) collect (make-instance 'person :age age :size size))) ;;; Première solution. Elle n'est pas terrible. Il y a beaucoup ;;; de duplication de code. On utilise la récursivité sur les ;;; listes ce qui n'est pas recommandée. Ce code fait 14 lignes ;;; sans compter les lignes blanches. (defun sum-ages (list) (if (null list) 0 (+ (age (car list)) (sum-ages (cdr list))))) (defun average-age (list) (/ (sum-ages list) (length list))) (defun count-older (list age) (cond ((null list) 0) ((> (age (car list)) age) (1+ (count-older (cdr list) age))) (t (count-older (cdr list) age)))) (defun sum-tall-ages (list size) (cond ((null list) 0) ((> (size (car list)) size) (+ (age (car list)) (sum-tall-ages (cdr list) size))) (t (sum-tall-ages (cdr list) size)))) ;;; Deuxième solution. On factorise le code duplique et on se sert ;;; des fonction existantes pour parcourir la liste. Cette solution ;;; donne 7 lignes de code, soit une économie d'un facteur 2. (defun average-age (list) (/ (reduce #'+ (mapcar #'age list)) (length list))) (defun count-older (list age) (count age list :key #'age :test #'<)) (defun sum-tall-ages (list size) (reduce #'+ (mapcar #'age (remove size list :key #'size :test #'>)))) ;;; Troisième solution. On utilise loop. Cette solution fait 11 ;;; lignes. L'utilisation de loop est souvent plus claire que des ;;; combinaisons imbriquées de reduce, mapcar, remove, etc. De ;;; plus, les version de average-age et sum-tall-ages ci-dessus allouent ;;; de la mémoire alors que les versions avec loop ne le font pas. (defun average-age (list) (/ (loop for person in list sum (age person)) (length list))) (defun count-older (list age) (loop for person in list count (> (age person) age))) (defun sum-tall-ages (list size) (loop for person in list when (> (size person) size) sum (age person)))