Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

deftype list-of-things?

29 views
Skip to first unread message

Kevin Mayall

unread,
Jan 21, 1997, 3:00:00 AM1/21/97
to

I'm having trouble defining a CL type, which I want to denote a list
where all the elements of the list of type Thing (Thing being a CLOS
class).

My books aren't helping too much and my unsuccessful attempt is below:

(deftype list-of-things (lis)
`(and List (every #'(lambda (obj) (typep obj 'Thing)) ,lis)))

I would like to be able to evaluate forms such as
(typep '(chair table lamp) 'list-of-things)

Any help is much appreciated.

Cheers..........

Kevin Mayall

--
--------------------------------Bermuda Massive
Kevin Mayall kma...@uwaterloo.ca
http://www.fes.uwaterloo.ca/u/kmayall/
School of Planning, University of Waterloo

Seth Tisue

unread,
Jan 21, 1997, 3:00:00 AM1/21/97
to

In article <E4D8...@watserv3.uwaterloo.ca>,

Kevin Mayall <kma...@cousteau.uwaterloo.ca> wrote:
>I'm having trouble defining a CL type, which I want to denote a list
>where all the elements of the list of type Thing (Thing being a CLOS
>class).
>
>My books aren't helping too much and my unsuccessful attempt is below:
>
>(deftype list-of-things (lis)
> `(and List (every #'(lambda (obj) (typep obj 'Thing)) ,lis)))
>
>I would like to be able to evaluate forms such as
>(typep '(chair table lamp) 'list-of-things)

I think you want to allow the empty list to be of type list-of-things
(there being no counterexample to prove otherwise). So I'd get rid of
the (AND LIS ...) part.

But your main difficulty is that you've misunderstood deftype. The
body of a deftype isn't allowed to expand into just any Lisp code.
It's supposed to expand into a valid type specifier. Type specifiers
sometimes look like code, but aren't really. Try:

(defun list-of-things-p (lis)
(every #'(lambda (obj) (typep obj 'thing)) lis))

(deftype list-of-things ()
'(and list
(satisfies list-of-things-p)))
--
== Seth Tisue <s-t...@nwu.edu> http://www.cs.nwu.edu/~tisue/

Erik Naggum

unread,
Jan 22, 1997, 3:00:00 AM1/22/97
to

* Kevin Mayall
| Thank you very much Seth. I needed "satisfies". What is satisfies
| anyway? It's not a function, but it looks like one, and judging from
| CLtL2, the (and ... ) form is evaluated, no?

`satisfies' is part of the specification of the type. it is no more
evaluated than (vector character) in a type specifier is a function call.

see Chapter 4 in CLtL2 or 4.2.3 in ANSI X3.226:1994, "Type Specifiers".

#\Erik
--
1,3,7-trimethylxanthine -- a basic ingredient in quality software.

Kevin Mayall

unread,
Jan 22, 1997, 3:00:00 AM1/22/97
to

Seth Tisue wrote:
> But your main difficulty is that you've misunderstood deftype. The
> body of a deftype isn't allowed to expand into just any Lisp code.
> It's supposed to expand into a valid type specifier. Type specifiers
> sometimes look like code, but aren't really. Try:
>
> (defun list-of-things-p (lis)
> (every #'(lambda (obj) (typep obj 'thing)) lis))
>
> (deftype list-of-things ()
> '(and list
> (satisfies list-of-things-p)))

Thank you very much Seth. I needed "satisfies". What is satisfies

Barry Margolin

unread,
Jan 23, 1997, 3:00:00 AM1/23/97
to

In article <32E628...@uwaterloo.ca>,

Kevin Mayall <kma...@uwaterloo.ca> wrote:
>Thank you very much Seth. I needed "satisfies". What is satisfies
>anyway? It's not a function, but it looks like one, and judging from
>CLtL2, the (and ... ) form is evaluated, no?

(SATISFIES f) is a type specifier. (typep x '(satisfies f)) is true iff (f
x) is true.

No, type expressions are *not* evaluated. They're represented using list
structure of the form (<operator> <parameters>), so they look alot like
function calls, but that's just coincidence. Just as EVAL implements
execution by interpreting list structure, TYPEP implements type testing by
interpreting the list structure of the type argument.
--
Barry Margolin
BBN Planet, Cambridge, MA
bar...@bbnplanet.com - Phone (617) 873-3126 - Fax (617) 873-5508
(BBN customers, please call (800) 632-7638 option 1 for support)

Mark McConnell

unread,
Jan 23, 1997, 3:00:00 AM1/23/97
to

> > (defun list-of-things-p (lis)
> > (every #'(lambda (obj) (typep obj 'thing)) lis))
> >
> > (deftype list-of-things ()
> > '(and list
> > (satisfies list-of-things-p)))

I'm wondering about the usefulness of types defined using
"satisfies". In a program tuned for speed, all those extra calls
to list-of-things-p might slow things down. On the other hand,
they might be optimized out by some compilers(?), and so would be
useless.

However, having the type list-of-things would be invaluable
during debugging. Also, I have been using lots of type declarations
lately (though not ones with "satisfies"), and it really helps me
reread the code a few months later.

Howard R. Stearns

unread,
Jan 24, 1997, 3:00:00 AM1/24/97
to

I should realy reread the spec rather rather than giving out information
off the top of my head, but as I recall...

1. No implementation is required to confirm that type declarations are,
in fact, correct. In other words, the compiler is allowed to trust the
type declarations you give it in order to perform optimizations. If you
want to confirm that a place holds a value of a certain type, you must
use CHECK-TYPE. (CMUCL is one implementation that DOES confirm type
declarations at run time.) Whether type specifiers are trusted or
confirmed at run time is usually dependent on optimization settings.

2. If you're explicitly testing that some value is of a particular type,
either through TYPEP, CHECK-TYPE, or some analysis of your compiler's
treatment of type declarations, then a type specification involving
SATISFIES shouldn't be much different than explicitly using the
predicate (such as list-of-things-p). However...

3. ANSI does not specify whether type specifications are expanded at
compile-time, load-time or run-time (or multiple times), so you may
incur a run-time cost for expanding any list form type specifier.

4. The spec allows SUBTYPEP to give up on type specifiers involving
SATISFIES, so it is very unlikely that any implementation will be able
to make use of type specifiers involving SATISFIES for optimization.
However, some implementations (ACL) do provide non-portable "typep
accelerators" involving predicates.

5. ANSI allows type specifiers like '(cons item), which could, in
principle, be used to check/optimize a list who's head is an item.
However, you can't specify something like:
(deftype item-list '(or null (cons item item-list))
because the expansion of type specifiers must terminate. However, if
you know exactly how long the list is you might try:
(deftype item-list '(cons item (cons item (cons item nil))
However, if this were the case, you might be better off with defstruct
or an array.

6. Interestingly, it is possible to specify a type specifier for a
constructor for item-list which indicates that all the elements are
items. For example:

(declaim (ftype (function (&rest item) list) make-item-list)
(defun make-item-list (&rest items)
(copy-list items)) ;If you ever want to modify the list!
(dolist (item (make-item-list a b c)) ...)

But it seems unlikely to me that an existing compilers would optimize
this. (It is possible they might inline the definition of
make-item-list and perform some optimizations based on that, but I
suspect the ftype specifier would not be used in optimizing the
iteration.


Conclusion:

If you want to test that some data is of a particular type, you can use
CHECK-TYPE or a TYPEP, giving either the list form of the CONS specifier
or a specifier using SATISFIES.
* A good compiler might ALSO be able to optimize based on this test,
using flow analysis.
* A bad compiler won't optimize, and may even require run time
expansion of the type specifier.
* If in doubt, use an inlined explicit predicate test, which a good
compiler should be able to make as much use of as TYPEP.

If you don't need any tests performed, but just want to tell your
compiler what's going on:
* You're most likely to have the compiler catch your drift using a
standard, non-list form specifier, like just LIST.
* Some compilers might be able to do something with '(cons item).
* Forget about type specifiers involving SATISFIES.
Better yet, don't use lists.

0 new messages