una domanda su Common Lisp
-
27-09-2019 - |
Domanda
sto diventando pazzo con un piccolo problema qui,
Continuo a ricevere un errore e non posso sembrare calcolare fuori perché,
il codice dovrebbe modificare l'intervallo di una lista,
quindi se gli diamo un elenco con i valori (1 2 3 4)
e vogliamo modificare l'intervallo di 11 a quattordici il risultato sarebbe (11 12 13 14)
il problema è che l'ultima funzione chiamata scale-list
restituirà un errore che dice:
Debugger è entrato - Errore di Lisp: (sbagliato-tipo-argomento numero-o-marcatore-p nullo)
qualcuno ha un indizio perché? Io uso Aquamacs come editor grazie in anticipo
;;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)
Soluzione
Le definizioni di massima e minima necessità di essere migliorata. SORT è distruttivo. E 'anche sbagliato chiamare SORT con una costante letterale come '(1 2 3 4) -. Ancora una volta, SORT è distruttiva
Definizioni Better:
(defun minimum (list)
(reduce #'min list))
(defun maximum (list)
(reduce #'max list))
Una definizione più efficiente della gamma:
(defun range (list)
(loop for e in list
maximize e into max
minimize e into min
finally (return (- max min))))
SCALE-LIST e scale-valore sono, inoltre, non Lisp-like. Se si chiama NTH come questo in una funzione ricorsiva, allora qualcosa non va. Si dovrebbe ricorsione sulla lista, non è l'indice. SCALE-VALORE chiama RANGE e minima per ogni chiamata. Perché?
Controlla questa variante:
;;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)
Che cosa si può migliorare di più? Per esempio avrei sbarazzarsi della ricorsione e sostituirlo con mapcar.
Altri suggerimenti
I re pubblicare il codice perché qualcosa è andato storto ...
;;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)
Il tuo stack trace reale è qualcosa di simile:
-(nil 0.1)
(* (- (nth ... list) (minimum list)) (- high low))
(/ (* (- ... ...) (- high low)) (range list))
(+ (/ (* ... ...) (range list)) low)
scale-value((0.1) 20 30 3)
Credo che a determinare un elemento ennesima sbagliato e questo ritorna NIL, che scombina la sottrazione.