#loops #for-loop #foreach #common-lisp
#циклы #for-цикл #foreach #common-lisp
Вопрос:
Недавно я имел дело с некоторыми lisp, я пишу функцию, которая возвращает комбинации элементов. Это работает хорошо, но все равно выдает мне предупреждение об ошибке > Аргумент Y не является ЧИСЛОМ: NIL
мой КОД:
(defun printo (x y z)
(if (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)
))
(defun getDiff (x y)
(return-from getDiff (abs (- x y))))
(defun distcalc (lista)
(loop for k from 0 to (list-length lista)
do (loop for j from 0 to (list-length lista)
do (let ((pivot (nth k lista))(base (nth j lista)))
(if (nth j lista)(printo pivot base (abs (- base pivot))
))
))
))
(distcalc '(1 10 20 25 13))
Поскольку я новичок в этом, я думаю, что, возможно, я где-то пропустил какую-то обработку ошибок, но slime, выводящий меня на экран ошибки, действительно раздражает!
Спасибо за любую помощь.
Ответ №1:
Пожалуйста, используйте стандартное форматирование и именование:
(defun printo (x y z)
(if (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(return-from get-diff (abs (- x y))))
(defun distcalc (lista)
(loop for k from 0 to (list-length lista)
do (loop for j from 0 to (list-length lista)
do (let ((pivot (nth k lista))
(base (nth j lista)))
(if (nth j lista)
(printo pivot base (abs (- base pivot))))))))
(distcalc '(1 10 20 25 13))
Если вам не нужна альтернатива в if
, используйте when
:
(defun printo (x y z)
(when (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(return-from get-diff (abs (- x y))))
(defun distcalc (lista)
(loop for k from 0 to (list-length lista)
do (loop for j from 0 to (list-length lista)
do (let ((pivot (nth k lista))
(base (nth j lista)))
(when (nth j lista)
(printo pivot base (abs (- base pivot))))))))
(distcalc '(1 10 20 25 13))
Вам не нужно return
или return-from
; тело функции возвращает
значения последней формы. Я предполагаю, что вы хотите использовать свой get-diff
:
(defun printo (x y z)
(when (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(abs (- x y)))
(defun distcalc (lista)
(loop for k from 0 to (list-length lista)
do (loop for j from 0 to (list-length lista)
do (let ((pivot (nth k lista))
(base (nth j lista)))
(when (nth j lista)
(printo pivot base (get-diff base pivot)))))))
(distcalc '(1 10 20 25 13))
Ошибка заключается в том, что цикл to
включает конец; вы хотите below
:
(defun printo (x y z)
(when (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(abs (- x y)))
(defun distcalc (lista)
(loop for k from 0 below (list-length lista)
do (loop for j from 0 below (list-length lista)
do (let ((pivot (nth k lista))
(base (nth j lista)))
(when (nth j lista)
(printo pivot base (get-diff base pivot)))))))
(distcalc '(1 10 20 25 13))
Однако индексы вам вообще не нужны, поэтому вы можете просто перебирать список:
(defun printo (x y z)
(when (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(abs (- x y)))
(defun distcalc (lista)
(loop for pivot in lista
do (loop for base in lista
when base
do (printo pivot base (get-diff base pivot)))))
(distcalc '(1 10 20 25 13))
Теперь, возможно, мы можем лучше видеть, что любые nil
s в lista
также будут
проблема во внешнем цикле:
(defun printo (x y z)
(when (and x y z)
(format t "~a and ~a difference: ~a ~%" x y z)))
(defun get-diff (x y)
(abs (- x y)))
(defun distcalc (lista)
(loop for pivot in lista
when pivot
do (loop for base in lista
when base
do (printo pivot base (get-diff base pivot)))))
(distcalc '(1 10 20 25 13))
Комментарии:
1. Черт возьми, спасибо за подробный ответ, это, безусловно, помогает с моим lisp!
2. Извините, что пишу еще раз, но если я пытаюсь собрать различия, команда collect не выводит никакого списка. Что здесь может быть не так?
3. @sdgawerzswer может быть, задать новый вопрос с обновленным кодом и новой проблемой?
4. Я уже понял это, ключ должен был собираться в обоих циклах.
Ответ №2:
Ваша ошибка заключается в том, что (loop for k from 0 to (list-length lista))
выдаст вам k
0-5
, а не 0-4
. (nth 5 '(1 10 20 25 13))
выдаст вам nil
и (- 1 nil)
ту же ошибку. делать nth
каждый раз нехорошо. возможно, вам следует вместо этого сделать:
(defun distcalc (lista)
(loop :for pivot :in lista
:do (loop :for base :in lista
:if base
:do (printo pivot base (abs (- base pivot))))))