sdgaw erzswer
sdgaw erzswer

Reputation: 2382

lisp error handling - check if variable nil

I've been recently dealing with some lisp, I am writing a function, which returns combinations of elements. It works nice, but it still throws me a warning error > Argument Y is not a NUMBER: NIL

my CODE:

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

As I am a beginner in this, I think I might have missed some error handling somewhere, but slime throwing me on that error screen is really annoying!

Thanks for any help.

Upvotes: 2

Views: 762

Answers (2)

Svante
Svante

Reputation: 51501

Please use standard formatting and naming:

(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 you do not need the alternative in an if, use 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))

You do not need to return or return-from; a function body returns the values of the last form. I guess that you want to use your 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))

The error is that looping to includes the end; you want 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))

However, you do not need the indices at all, so you can simply loop over the list:

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

We can now perhaps better see that any nils in lista would also be a problem in the outer loop:

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

Upvotes: 7

Sylwester
Sylwester

Reputation: 48745

Your error is that (loop for k from 0 to (list-length lista)) will give you k 0-5, not 0-4. (nth 5 '(1 10 20 25 13)) will give you nil and (- 1 nil) the same error. doing nth every time is not good. you should perhaps instead do:

(defun distcalc (lista)
  (loop :for pivot :in lista
        :do (loop :for base :in lista
                  :if base
                  :do (printo pivot base (abs (- base pivot))))))

Upvotes: 3

Related Questions