From: Vassil Nikolov
Subject: mutually recursive types
Date: 
Message-ID: <snzve01r34x.fsf@luna.vassil.nikolov.name>
Hello,

Just checking I didn't miss anything: because of

   Recursive expansion of the type specifier returned as the expansion
   must terminate, including the expansion of type specifiers which
   are nested within the expansion.

(quoting from DEFTYPE's specification), mutually recursive types as in
the example below cannot be defined, can they?

  (deftype foo () '(or bar baz))
  (deftype bar () 'symbol)
  (deftype baz () '(cons foo foo))
  ;; with the intention of e.g. (typep 'x 'foo) => t

I suppose the way to go is to use SATISFIES---or is there another way?

(And no, this is not an implicit critique of Common Lisp.)

---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: Joshua Taylor
Subject: Re: mutually recursive types
Date: 
Message-ID: <0dac2634-128f-41d5-98bc-034db9387dba@2g2000hsn.googlegroups.com>
On Jun 22, 9:49 am, Vassil Nikolov <···············@pobox.com> wrote:
> Hello,
>
> Just checking I didn't miss anything: because of
>
>    Recursive expansion of the type specifier returned as the expansion
>    must terminate, including the expansion of type specifiers which
>    are nested within the expansion.
>
> (quoting from DEFTYPE's specification), mutually recursive types as in
> the example below cannot be defined, can they?
>
>   (deftype foo () '(or bar baz))
>   (deftype bar () 'symbol)
>   (deftype baz () '(cons foo foo))
>   ;; with the intention of e.g. (typep 'x 'foo) => t
>
> I suppose the way to go is to use SATISFIES---or is there another way?
>
> (And no, this is not an implicit critique of Common Lisp.)
>
> ---Vassil.
>
> --
> Peius melius est.  ---Ricardus Gabriel.

The cited paragraph makes it sound as though the example you provided
isn't legal. SATISFIES would be one option. Depending on your specific
case, arguments to the types might be applicable. The following is
probably an abuse of the type system, but seems to be legal:

(deftype integer-between (low high)
  (assert (and (integerp low)
               (integerp high)
               (<= low high)))
  (if (eql low high)
    `(eql ,high)
    `(or (eql ,low)
         (integer-between ,(1+ low) ,high))))

(typep 35 '(integer-between 40 50)) => NIL
(typep 45 '(integer-between 40 50)) => T

Similar things might be done with mutually recursive types (though not
for the exact case that you gave as an example).

//JT