From: Bradford W. Miller
Subject: defining new type specifiers that take arguments
Date: 
Message-ID: <miller-ya02408000R2207981931020001@milano.mcc.com>
I need to define a type specifier that takes arguments. For simplicity,
let's imagine that this will be an adjunct to the CONS type, that can, for
instance, specify the length of the list, and the type of each element of the
list (nevermind that I can already do this with arrays, I'm simplifying...).

e.g. (cons-of-lenghth-and-type 12 symbol) would be the type of a cons of
length 12 and whose cars were symbols (only).

The question is, how can I actually do this? Deftype, at best, lets me call
something like satisfies on a symbol, so I'd have to essentially create a
function to test for a specific, constant, type I want, but not for
arbitrary arguments at runtime.

(if only satisfies took a lambda...)

And to fold it into prior discussion, given I had a list

(a b c d e)

Of course type-of should return 

(cons-of-lenght-and-type 5 symbol)

(1/2 :-), since that's the most specific type that covers the argument.
(IMHO probably how type-of should have been defined in the first place...
using conjunction when there were >1 most specific types).

In reality, my problem is to describe the type content of some slots of a
clos class (instance), in the type specifier, e.g. (foo x) would describe a
class foo whose grabgra slot had an object of type x in it. Since x can be
pretty much anything, and I don't really want to construct all the possible
foo-x's ahead of time, since they won't always be known (consider (foo
(integer 1 174)) for all possible ranges of integers)... the satisfies
problem comes back to bite me. But I really need a type specifier that I
can pass to typep (because of the functions that get called with these
things that will do a search on objects of the appropriate type, and I'd
rather not rewrite them all). Of course if typep were generic :-).

I hope I'm missing something obvious!

-- 
Bradford W. Miller
······@mcc.com

From: Barry Margolin
Subject: Re: defining new type specifiers that take arguments
Date: 
Message-ID: <AtJt1.7$fm5.66481@cam-news-reader1.bbnplanet.com>
In article <··································@milano.mcc.com>,
Bradford W. Miller <······@mcc.com> wrote:
>I need to define a type specifier that takes arguments. For simplicity,
>let's imagine that this will be an adjunct to the CONS type, that can, for
>instance, specify the length of the list, and the type of each element of the
>list (nevermind that I can already do this with arrays, I'm simplifying...).
>
>e.g. (cons-of-lenghth-and-type 12 symbol) would be the type of a cons of
>length 12 and whose cars were symbols (only).

Shouldn't this be called LIST-OR-LENGTH-AND-TYPE?

>The question is, how can I actually do this? Deftype, at best, lets me call
>something like satisfies on a symbol, so I'd have to essentially create a
>function to test for a specific, constant, type I want, but not for
>arbitrary arguments at runtime.

It can be defined recursively:

(deftype list-of-length-and-type (length type)
  (if (= length 0)
      'null
      `(cons ,type (list-of-length-and-type ,(1- length) ,type))))

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Bradford W. Miller
Subject: Re: defining new type specifiers that take arguments
Date: 
Message-ID: <miller-ya02408000R2307981611420001@milano.mcc.com>
> It can be defined recursively:
> 
> (deftype list-of-length-and-type (length type)
>   (if (= length 0)
>       'null
>       `(cons ,type (list-of-length-and-type ,(1- length) ,type))))

Mumble, that's what I get for working out of CLtL 2/e instead of the
hyperspec, in the former CONS didn't specialize. (I also note that Allegro
4.3.1, at least doesn't support CONS specializing either). So, **assuming
CONS type specialization doesn't exist** ... it resolves to the same issue
as my real problem.

-- 
Bradford W. Miller
······@mcc.com
From: Barry Margolin
Subject: Re: defining new type specifiers that take arguments
Date: 
Message-ID: <0%Pt1.19$fm5.273589@cam-news-reader1.bbnplanet.com>
In article <··································@milano.mcc.com>,
Bradford W. Miller <······@mcc.com> wrote:
>
>> It can be defined recursively:
>> 
>> (deftype list-of-length-and-type (length type)
>>   (if (= length 0)
>>       'null
>>       `(cons ,type (list-of-length-and-type ,(1- length) ,type))))
>
>Mumble, that's what I get for working out of CLtL 2/e instead of the
>hyperspec, in the former CONS didn't specialize. (I also note that Allegro
>4.3.1, at least doesn't support CONS specializing either). So, **assuming
>CONS type specialization doesn't exist** ... it resolves to the same issue
>as my real problem.

True.  That's why we enhanced the CONS type specifier to allow it to
specialize -- it permits you to define things like this, which weren't
possible beforehand.

I think the reason SATISFIES doesn't take lambda expressions is because we
didn't want to deal with which lexical environment it should be evaluated
in.

DEFTYPE isn't really intended to be a fully general mechanism, it's just an
abbreviation facility, allowing you to give a name to a compound type
specifier.  If you want to check whether a parameter is a list of a certain
length and type, just call a predicate and signal an error.  Using (:TYPE
(LIST-OF-LENGTH-AND-TYPE 5 SYMBOL)) in a slot specifier is not likely to
buy you anything -- many implementations don't do type checking of slot
assignments, and probably can't do any useful optimizations with this type
specifier.  So it mostly serves as documentation, which can be done just as
well with comments or a :DOCUMENTATION attribute.

If you have a predicate that takes parameters (which you presumably would
have called if DEFTYPE allowed you), and you wanted to use CHECK-TYPE with
your defined type, then just replace the CHECK-TYPE call with:

(assert (<predicate> list length type) (list)
  "~S is not a list of length ~D of ~As." list length type)

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Howard R. Stearns
Subject: Re: defining new type specifiers that take arguments
Date: 
Message-ID: <35B78058.30F2439A@elwood.com>
Barry answered your CONS type specifier, issue, but the answer for your
clos question is different.

I don't think there is any CL way to create parametric class-based type
specifiers.  If there were, the answer for your toy problem and your
real problem would be the same, which would be nice.

In Eclipse, part of the metaclass tree looks like:

metaobject
  type
    specializer
      eql-specializer
      class
    type-combination
      type-intersection
      type-union
    type-complement
    ambiguous-type
    limited-type
      limited-numeric-type
      limited-cons-type
      limited-array-type

and TYPEP and SUBTYPEP are generic functions, as are TYPE-COMPLEMENT,
TYPE-UNION, and TYPE-INTERSECTION.  The idea is to allow an extensible
Dylan-like type metaobject protocol, including limited types. While this
has allowed a very well behaved and powerful subtypep and type
simplifier, we haven't come across any need to document it for users.

Even in your case, I'm not sure its needed.  For example, satisfies
might be made to work, despite the fact that it requires a symbol to
name the predicate of one argument.  (Alright, it would be a kludge.) 
Better yet, WHY NOT create the specialized classes as you need them
(FOO-X, etc.) at run time?  (This requires your implementation to
support the MOP, but most support at least enough to let you do this.)



Bradford W. Miller wrote:
> 
> I need to define a type specifier that takes arguments. For simplicity,
> let's imagine that this will be an adjunct to the CONS type, that can, for
> instance, specify the length of the list, and the type of each element of the
> list (nevermind that I can already do this with arrays, I'm simplifying...).
> 
> e.g. (cons-of-lenghth-and-type 12 symbol) would be the type of a cons of
> length 12 and whose cars were symbols (only).
> 
> The question is, how can I actually do this? Deftype, at best, lets me call
> something like satisfies on a symbol, so I'd have to essentially create a
> function to test for a specific, constant, type I want, but not for
> arbitrary arguments at runtime.
> 
> (if only satisfies took a lambda...)
> 
> And to fold it into prior discussion, given I had a list
> 
> (a b c d e)
> 
> Of course type-of should return
> 
> (cons-of-lenght-and-type 5 symbol)
> 
> (1/2 :-), since that's the most specific type that covers the argument.
> (IMHO probably how type-of should have been defined in the first place...
> using conjunction when there were >1 most specific types).
> 
> In reality, my problem is to describe the type content of some slots of a
> clos class (instance), in the type specifier, e.g. (foo x) would describe a
> class foo whose grabgra slot had an object of type x in it. Since x can be
> pretty much anything, and I don't really want to construct all the possible
> foo-x's ahead of time, since they won't always be known (consider (foo
> (integer 1 174)) for all possible ranges of integers)... the satisfies
> problem comes back to bite me. But I really need a type specifier that I
> can pass to typep (because of the functions that get called with these
> things that will do a search on objects of the appropriate type, and I'd
> rather not rewrite them all). Of course if typep were generic :-).
> 
> I hope I'm missing something obvious!
> 
> --
> Bradford W. Miller
> ······@mcc.com