вопрос по общему лиспу - PullRequest
1 голос
/ 18 апреля 2010

Я схожу с ума от маленькой проблемы здесь, Я получаю сообщение об ошибке, и я не могу понять, почему, код должен изменить диапазон списка, так что если мы дадим ему список со значениями (1 2 3 4), и мы хотим изменить диапазон от 11 до 14, результат будет (11 12 13 14) проблема в том, что последняя функция с именем scale-list выдаст сообщение об ошибке:

Введен отладчик - ошибка Lisp: (неправильный тип аргумента число-или-маркер-ноль)

кто-нибудь знает, почему? Я использую Aquamacs в качестве редактора заранее спасибо

;;finds minimum in a list
(defun minimum (list)
  (car (sort list #'<)))

;;finds maximum in a list
(defun maximum (list)
  (car (sort list #'>)))

;;calculates the range of a list
(defun range (list)
  (- (maximum list) (minimum list)))

;;scales one value to another range
(defun scale-value (list low high n)
   (+ (/ (* (- (nth (- n 1) list)
               (minimum list))
            (- high low))
         (range list))
      low))


;;is supposed to scale the whole list to another range
(defun scale-list (list low high n)
  (unless (= n 0)
   (cons (scale-value list low high n)
         (scale-list list low high (- n 1)))))

(scale-list '(1 2 3 4) 21 24 4)

Ответы [ 3 ]

4 голосов
/ 18 апреля 2010

Определения максимума и минимума нуждаются в улучшении. СОРТ разрушительный. Также неправильно называть SORT с буквальной константой, такой как '(1 2 3 4) - опять же, SORT разрушителен.

Лучшие определения:

(defun minimum (list)
  (reduce #'min list))

(defun maximum (list)
  (reduce #'max list))

Более эффективное определение диапазона:

(defun range (list)
  (loop for e in list
        maximize e into max
        minimize e into min
        finally (return (- max min))))

SCALE-LIST и SCALE-VALUE также не похожи на Lisp. Если вы вызываете NTH как это в рекурсивной функции, то что-то не так. Вы должны пройти по списку, а не по индексу. SCALE-VALUE вызывает RANGE и MINIMUM для каждого вызова. Почему?

Проверить этот вариант:

;;scales one value to another range
(defun scale-value (item low high min range)
   (+ (/ (* (- item min)
            (- high low))
         range)
      low))

;;is supposed to scale the whole list to another range
(defun scale-list (list low high)
  (let ((min (minimum list))
        (range (range list)))
    (labels ((scale-list-aux (list)
               (when list
                 (cons (scale-value (first list) low high min range)
                       (scale-list-aux (rest list))))))
      (scale-list-aux list))))

(scale-list '(1 2 3 4) 21 24)

Что вы можете улучшить еще? Например, я бы избавился от рекурсии и заменил ее на MAPCAR.

0 голосов
/ 18 апреля 2010

Ваш фактический след стека что-то вроде:

-(nil 0.1)
  (* (- (nth ... list) (minimum list)) (- high low))
  (/ (* (- ... ...) (- high low)) (range list))
  (+ (/ (* ... ...) (range list)) low)
  scale-value((0.1) 20 30 3)

Полагаю, вы определили неправильный n-й элемент, и это возвращает nil, что приводит к неправильному вычитанию.

0 голосов
/ 18 апреля 2010

Я публикую код, потому что что-то пошло не так ...

;;finds minimum in a list
(defun minimum(list)
  (car  (sort list #'<)))
;;finds maximum in a list
(defun maximum(list)
  (car (sort list #'>)))
;;calculates the range of a list
(defun range(list)
  (- (maximum list) (minimum list)))

;;scales one value to another range
(defun scale-value(list low high n)
     (+ (/ (* (- (nth (- n 1) list) (minimum list)) (- high low)) (range list)) low))


;;is supposed to scale the whole list to another range
(defun scale-list(list low high n)
  (unless (= n 0)
   (cons (scale-value list low high n) (scale-list list low high (- n 1)))))

(scale-list '(1 2 3 4) 21 24 4)
...