обработка ошибок lisp — проверка, равна ли переменная нулю

#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))))))