Search code examples
common-lisppredicatedeftype

Common Lisp calling a deftype method


I'm not been able to make this working on. I'm defining a predicate using deftype SameType(x y) method, which evaluates whether the elements of list x and list y are of the same type, and in the same position. The problem comes when I try to call the predicate for testing. I receive an error ERROR: SameType is undefined This is my code:

(deftype SameType (x y)
`(cond 
    ((and (null x) (null y) T))
    (
        (and (numberp (car x)) (numberp (car y)))
        (SameType (cdr x) (cdr y) )
    )
    (
        (and (stringp (car x)) (stringp (car y)))
        (SameType (cdr x) (cdr y) )
    )
    (
        (and (atom (car x)) (atom (car y)))
        (SameType (cdr x) (cdr y) )
    )
    (T nil)
)

)

And this is how I'm calling it

(SameType '(A B C 1 2 4 A) '('() G 2 5 6 A B))

I already checked on various onine resources, even related questions on this site.


Solution

  • deftype can be used to define a type, not a predicate. For instance, to define the type of the lists with only integers, you could write something like:

    (defun intlistp (l)
      "predicate to check if l is a list consisting only of integers"
      (and (listp l)               ; l is a list and
           (every #'integerp l)))  ; every element of l is an integer
    
    (deftype integer-list ()
      "the type of list of integers"
      `(satisfies intlistp))
    

    and then you can check if a value satisfies this type:

    CL-USER> (typep '(1 2 3) 'integer-list)
    T
    CL-USER> (typep '(1 2.5 3) 'integer-list)
    NIL
    

    If you want to check if two lists have the same type according to your definition, then you could define a regular function:

    (defun same-type (l1 l2)
      "check if lists l1 and l2 have the same length and corresponding
       elements of the same CL type"
      (cond ((null l1)        ; if l1 is null
             (null l2))       ; returns true only if also l2 is null
            ((and (consp l1)  ; if l1 is a cons
                  (consp l2)  ; and l2 is a cons too,
                  (typep (car l1) (type-of (car l2)))) ; and their cars have the same CL type
             (same-type (cdr l1) (cdr l2))))) ; go recursively on their cdrs
    
    CL-USER> (same-type '(1 a 3) '(2 b 4))
    T
    CL-USER> (same-type '(1 "a" 3) '(2 "b" 3))
    T
    CL-USER> (same-type '(1 a 3) '(2 b 4.5))
    NIL
    CL-USER> (same-type '(1 a 3) '(2 b 4 3))
    NIL
    CL-USER> (same-type '(1 2 (3 4)) '(1 6 (4 5)))
    T
    CL-USER> (same-type '(1 2 (3 4)) '(1 6 (4 5 6)))
    T
    

    Note that, as you can see from the last example, the type is checked only for the first level of the list.