From: Gerald Smith
Subject: User-defined types???
Date: 
Message-ID: <emsFJYyq9GA.310@nih2naac.prod2.compuserve.com>
Really puzzled by a passage in one of my books.

..on mid-page 353 of the book "Common LISPcraft" I will quote:

"We can specify a type consisting of a particular set of data objects using the 
term MEMBER.  The expression (member <obj1> <obj2>...) denotes a type 
consisting of precisely the objects named. Thus (member 17 foo "banana") 
specifies a type consisting of exactly three objects, the number 17, the 
symbol FOO, and the string "banana". (This specification looks superficially 
like a call to the function MEMBER. But, as a type specification, this 
expression is not evaluated. It has an altogether different interpretation as a 
description of a data type.)"


That is the quote, and unfortunately they do not go into detail. 
CLtL2 does not help.

This is as far as I got in my attempt to get it working:

(deftype wierd-type ()
  `(member 17 foo "banana"))

Keep in mind that the above code is just an instruction to the compiler about 
what to do when the symbol   'wierd-type   is encountered.

Now that I have created this new "type", I do not know how to use it.

I can't even use   'wierd-type   as an argument to "typep", if I want a "true" 
value returned by "typep".


..any suggestions?


Gerald

From: Kent M Pitman
Subject: Re: User-defined types???
Date: 
Message-ID: <sfw4swrxiwf.fsf@world.std.com>
Gerald Smith <··········@CompuServe.COM> writes:

> (deftype wierd-type ()
>   `(member 17 foo "banana"))
> 
> Now that I have created this new "type", I do not know how to use it.
> 
> I can't even use   'wierd-type   as an argument to "typep", if I want a "true" 
> value returned by "typep".

First, remember that MEMBER uses EQL and EQL on a random string will likely
always return NIL (unless the compiler has coalesced this constant with
other constants you're using--not something you should rely on in portable
code. ) If you want to refer to an object by its identity, which is what EQL
tests for, you should make sure you have a constructor powerful enough to yield
the EQL object.  e.g., your type is better defined:

 (defvar *canonical-banana* (copy-seq "banana")) ;make unique object at runtime
					         ;even if compiler has coalesced

 (deftype wierd-type ()
   `(member 17 foo ,*canonical-banana*))

Even so, overall, you're better off picking other datatypes for your WIERD-TYPE.

Incidentally, you're free to use any type name you want, but it may be useful
for you to know my spelling mnemonic that "weird has a weird spelling"; i.e. (if
you'll pardon the ill-placed Latin pun), it doesn't follow the regular English
rule "I before E except after C except in NEIGHBOR and WEIGH" (nothing like
nested exceptions in a so-called regular rule :-).  So the right spelling is,
weirdly enough, "weird".  (Fortunately, one can often use "odd" instead, which
has the virtue that if you forget and leave off a "d" you still have a legal
spelling; as most good SCRABBLE players know, "od is an odd spelling of odd".
Ah, English, what an od language.  Thank goodness for the relative consistency 
of CL.)

For info on coalescing, see the glossary of CLHS at 
 http://www.harlequin.com/education/books/HyperSpec/FrontMatter/
As a rule, I think you'll find CLHS a better reference these days than CLTL2
because it's ANSI CL conforming (which most commercial implementations are),
and it's webbed (and you can even download it if you have the 16MB free to
hold it). See 
 http://www.harlequin.com/education/books/HyperSpec/
for pointers to the pretty-minor legal restrictions and to the download info.

But we were going to tell you how to use a user-defined type, huh?   You can use
it any place it predicates a type. e.g., in CHECK-TYPE, DECLARE (with the TYPE 
declaration), and TYPEP.  

Here are some sample uses:

  (defun check-wierd (x)
    (check-type x wierd-type)
    x)

  (defun weird-p (x)
    (typep x 'wierd-type))

  (defun wierd-map (wierd-objects)
    (mapcar #'(lambda (obj)
	        (declare (type wierd-type obj))
		(typecase obj
		  ((symbol) 'bar)
		  ((string) "orange")
	          (otherwise 18)))
	    wierd-objects))

You can't use it for creating typed objects like in MAKE-INSTANCE. e.g.,

  (defclass wierd-type () ())
  (deftype oddd-type () 'wierd-type)
  (make-instance 'wierd-type) => #<WIERD-TYPE 23424>
  (make-instance 'oddd-type) signals an error!


Also, stylistically, I wouldn't put "-TYPE" on the end of my type names,
but again this is just a personal choice.  Imagine CL without types like
SYMBOL or INTEGER and with types instead like SYMBOL-TYPE and INTEGER-TYPE.
This would make forms like (TYPEP X 'SYMBOL-TYPE) longer to no apparent
end.  One already knows from context that the thing being used is a type.

Have a wierd day.
 --Kent
From: Gerald Smith
Subject: Re: User-defined types???
Date: 
Message-ID: <OovkoR1q9GA.273@nih2naac.prod2.compuserve.com>
Lemme violate the rule about giving "thanks" on the newsgroups.

I want to profusely thank Kent Pitman and Rainer Joswig for the 
help on "user defined types".

There is n-o-o place to get info like this in standard Lisp
textbooks.  <wish there was>

Gerald -
From: Rainer Joswig
Subject: Re: User-defined types???
Date: 
Message-ID: <joswig-0907981510270001@pbg3.lavielle.com>
In article <···············@nih2naac.prod2.compuserve.com>, Gerald Smith
<··········@CompuServe.COM> wrote:

> (deftype wierd-type ()
>   `(member 17 foo "banana"))

(setf b1 "banana")

(deftype wierd-type ()
  `(member 17 foo ,b1))

(typep 17 'wierd-type) -> t
(typep 'foo 'wierd-type) -> t
(typep 'bar 'wierd-type) -> nil
(typep "banana" 'wierd-type) -> nil
(typep b1 'wierd-type) -> t


Works for me in MCL 4.2.