On Aug 12, 2008, at 03:48 , Nikodemus Siivola wrote:
...
DEFSTRUCT also gives you the ability to define what amount to mutually recursive types:
(defstruct one (two nil :type (or null two))) (defstruct two (one nil :type (or null one)))
This mostly works. However, LW warns you that TWO is not a valid type specifier (while compiling a file containing the two definitions. AFAIU, this behavior is "conforming".
All in all, I would be perhaps more interested in a SIMPLE-LIST type, (where CAR is always of the same type), then recursive DEFTYPE in general:
(deftype int-list () '(simple-list integer))
In terms of what implmenentations do, what does Allegro do for
(compile nil '(lambda (x) (typep x 'int-list)))
CL-USER> (deftype int-list () '(or null (cons integer int-list)))
INT-LIST CL-USER> (compile nil (lambda (x) (typep x 'int-list))) #<Function (:ANONYMOUS-LAMBDA 3) @ #x105e6862> NIL NIL CL-USER> (funcall * '(a s d)) NIL CL-USER> (funcall * '(1 2)) T
and
(deftype fixnum-list () '(or null (cons fixnum fixnum-list)))
(compile nil '(lambda (x) (declare (fixnum-list x) (optimize speed)) (let ((a (first x)) (b (second x))) (when (and a b) (+ a b))))
? (That is, does it implement recursive types for the compiler as well, or do they just work in full calls to TYPEP?)
CL-USER> (deftype fixnum-list () '(or null (cons fixnum fixnum-list))) FIXNUM-LIST CL-USER> (compile nil '(lambda (x) (declare (fixnum-list x) (optimize speed)) (let ((a (first x)) (b (second x))) (when (and a b) (+ a b))))) #<Function (:ANONYMOUS-LAMBDA 5) @ #x106d2e7a> NIL NIL CL-USER> (funcall * '( 1 2 )) 3 CL-USER> (funcall * '( 1 a ))
;;; This is the SLIME backtrace
`A' is not of the expected type `NUMBER' [Condition of type TYPE-ERROR]
Restarts: 0: [ABORT-REQUEST] Abort handling SLIME request. 1: [ABORT] Abort entirely from this (lisp) process.
Backtrace: 0: (SWANK::DEBUG-IN-EMACS #<TYPE-ERROR @ #x1070970a>) 1: (SWANK:SWANK-DEBUGGER-HOOK #<TYPE-ERROR @ #x1070970a> #<Function SWANK-DEBUGGER-HOOK>) 2: (ERROR TYPE-ERROR :DATUM A :EXPECTED-TYPE NUMBER :FORMAT-CONTROL "~@<`~s' is not of the expected type `~s'~:@>" :FORMAT-ARGUMENTS (A NUMBER)) 3: ((:ANONYMOUS-LAMBDA 7) (1 A)) 4: (FUNCALL #<Function (:ANONYMOUS-LAMBDA 7) @ #x1070769a> (1 A))
So it looks like you get a TYPE-ERROR as expected, but I think this is coming from the call to +.
Cheers -- Marco Antoniotti