Xavier Maldonado
Xavier Maldonado

Reputation: 300

Check the type of an argument without using COND, IF, WHEN, UNLESS, or CASE

I have this function that is working fine when the inputs are number: it returns T if both inputs have the same sign, NIL otherwise. However, when I give for example two 'a, I get this error:

a is not a real number

I'm finding it tricky to filer non numbers without using COND, IF, WHEN, UNLESS, or CASE. Here is the function definition I have so far.

(defun same-sign (x y)
  (or (and (>= x 0) (>= y 0))
      (and (< x 0) (< y 0))))

Upvotes: 1

Views: 114

Answers (3)

Xavier Maldonado
Xavier Maldonado

Reputation: 300

(defun same-sign (x y)
    (and (typep x 'real) (typep y 'real)
    (or (and (>= x 0) (>= y 0))
        (and (< x 0) (< y 0)))))

Upvotes: 0

Svante
Svante

Reputation: 51501

You can use check-type:

(defun same-sign (x y)
  (check-type real x)
  (check-type real y)
  (= (signum x) (signum y)))

Since signum can also work with complex numbers, you could use number instead of real here, if it makes sense for your application.

Signum treats 0 separately, though, so you might use minusp instead (wrapping to potentially un-generalize the boolean):

(defun binary-sign (n)
  "Returns -1 if n is negative, 1 otherwise."
  (check-type real n)
  (if (minusp n) -1 1))

(defun same-sign-p (x y)
  "Returns whether both given real numbers are either both negative or both
non-negative."
  (= (binary-sign x) (binary-sign y)))

As you see, you can avoid writing two checks by putting the check into the more detailed function. However, you can imagine that minusp already has such a check, so you can be reasonably sure that an appropriate type-error will be signalled anyway if you don't call this with reals.

Upvotes: 4

zut
zut

Reputation: 816

You might mean type real and not number. Type number consists of real (integers and floats) and complex (2 real components) values. An example of a complex number is #C(1 2) = 1 + 2i

Try (and (realp x) ...) to filter real numbers, equivalent to (and (typep x 'real) ...).

Also (typecase x (real ..)) or using a generic function and (defmethod foo ((x real)) ..) work, except you seem to want to restrict yourself to basic logical operators.

Upvotes: 1

Related Questions