From: Damien Kick
Subject: PAIP: case studies in learning Common Lisp
Date: 
Message-ID: <d5wuoxyn.fsf@email.mot.com>
So I'm finally making some time to play with PAIP as a means to
furthering my understanding of programming with Common Lisp.  Having
read as far as the chapter on GPS, I decided to download the source
code <http://www.norvig.com/paip/README.html> so that I could play
with it.  First thing off the bat, I ran into problems attempting to
load/use it becuase of CMUCL package locks and PAIP code attempting to
do things with symbols in the COMMON-LISP package.  I've since found a
Debian package version of the PAIP code
<http://packages.debian.org/unstable/source/cl-paip> that even has an
ASDF system definition for the code.  I haven't tried playing with
this code yet but I'm assuming that someone has already fixed these
problems in this packge, if they've taken the trouble to ASDFify
everything.  However, I did try fiddling with a few things in the
original source code to try and fix things myself.  I've got a few
questions with which I was hoping someone might help me.

My first naive thought was to do the following in "auxfns.lisp":

    (cl:defpackage #:paip
      (:shadow #:debug #:symbol #:exp)
      (:use #:common-lisp))

    (cl:in-package #:paip)

Now, PAIP::SYMBOL should be FBOUNDP with the function provided by
PAIP.  However, I want PAIP::SYMBOL to be a superset of CL:SYMBOL;
e.g. I want PAIP::SYMBOL to name the same type as CL:SYMBOL.
Basically, I want PAIP::SYMBOL to be a synonym for CL:SYMBOL with an
additional SYMBOL-FUNCTION.

    * (describe 'cl:symbol)
    SYMBOL is an external symbol in the COMMON-LISP package.
    It names a class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL (sealed) {28037555}>.
       #<KERNEL::BUILT-IN-CLASS COMMON-LISP:SYMBOL (sealed) {28037555}> is a structure of type BUILT-IN-CLASS.
       CLASS-INFO: #<TYPE-CLASS KERNEL::CLASS>.
       ENUMERABLE: NIL.
       NAME: COMMON-LISP:SYMBOL.
       LAYOUT: #<Layout for COMMON-LISP:SYMBOL {28037585}>.
       STATE: :SEALED.
       DIRECT-SUPERCLASSES: (#<KERNEL::BUILT-IN-CLASS T (read-only) {2800491D}>).
       SUBCLASSES: #<EQ hash table, 1 entry {280375E5}>.
       PCL-CLASS: #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>.
       TRANSLATION: NIL.
    It names a PCL class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>.
       #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}> is a class, it is an
       instance of BUILT-IN-CLASS.
       Its proper name is COMMON-LISP:SYMBOL.
       The direct superclasses are: (T), and the direct
       subclasses are: (NULL).  The class is finalized.  The class precedence list is:
       (COMMON-LISP:SYMBOL T)
       There are 19 methods specialized for this class.
       Its direct slots are:
       
    * 

How can one make PAIP::SYMBOL name the same class as CL:SYMBOL?  Is
there a portable way to do this?  My first thought was to do something
like the following:

    * 
    (setf (find-class 'paip::symbol)
          (find-class 'cl:symbol))
    #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>

This seems to work because it mentions a BUILT-IN-CLASS with the same
name, COMMON-LISP:SYMBOL, but the hex address (?) is different.

    * 
    (defmethod test ((x paip::symbol))
      (print "It worked!"))
    ; Compiling LAMBDA (PCL::.PV-CELL. PCL::.NEXT-METHOD-CALL. X): 
    ; Compiling Top-Level Form: 

    #<STANDARD-METHOD TEST (COMMON-LISP:SYMBOL) {406638B5}>

And this DEFMETHOD form seems to be using COMMON-LISP:SYMBOL, too.
However, DESCRIBEing PAIP::SYMBOL and CL:SYMBOL is confusing me a bit.

    * (describe 'paip::symbol)
    SYMBOL is an internal symbol in the PAIP package.
    Function: #<Interpreted Function SYMBOL {4059AD51}>
    Function arguments:
      (&REST PAIP::ARGS)
    Function documentation:
      Concatenate symbols or strings to form an interned symbol
    Its defined argument types are:
      (&REST T)
    Its result type is:
      (VALUES COMMON-LISP:SYMBOL (MEMBER :INTERNAL :EXTERNAL :INHERITED NIL))
    Its definition is:
      (LAMBDA (&REST PAIP::ARGS) (BLOCK SYMBOL #))
    It names a class #<STANDARD-CLASS SYMBOL {40556E55}>.
       #<KERNEL::STANDARD-CLASS SYMBOL {40556E55}> is a structure of type STANDARD-CLASS.
       CLASS-INFO: #<TYPE-CLASS KERNEL::CLASS>.
       ENUMERABLE: NIL.
       NAME: SYMBOL.
       LAYOUT: NIL.
       STATE: NIL.
       DIRECT-SUPERCLASSES: NIL.
       SUBCLASSES: NIL.
       PCL-CLASS: NIL.
       
Describe is telling me that PAIP::SYMBOL has a STANDARD-CLASS
associated with it, making no mention of the BUILTIN-CLASS that one
finds with CL:SYMBOL.  Also, as CL:SYMBOL has a PCL class associated
with it, having read
<http://www.cons.org/cmucl/doc/pcl-mop-hints.html> but not necessarily
understanding it, I attempted to associate the same PCL class with
PAIP::SYMBOL, but that did not seem to work, at least according to
DESCRIBE.

    * 
    (setf (find-class 'paip::symbol)
          (find-class 'pcl::symbol))
    #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>
    * (describe 'paip::symbol)
    SYMBOL is an internal symbol in the PAIP package.
    Function: #<Interpreted Function SYMBOL {4059AD51}>
    Function arguments:
      (&REST PAIP::ARGS)
    Function documentation:
      Concatenate symbols or strings to form an interned symbol
    Its defined argument types are:
      (&REST T)
    Its result type is:
      (VALUES COMMON-LISP:SYMBOL (MEMBER :INTERNAL :EXTERNAL :INHERITED NIL))
    Its definition is:
      (LAMBDA (&REST PAIP::ARGS) (BLOCK SYMBOL #))
    It names a class #<STANDARD-CLASS SYMBOL {40556E55}>.
       #<KERNEL::STANDARD-CLASS SYMBOL {40556E55}> is a structure of type STANDARD-CLASS.
       CLASS-INFO: #<TYPE-CLASS KERNEL::CLASS>.
       ENUMERABLE: NIL.
       NAME: SYMBOL.
       LAYOUT: NIL.
       STATE: NIL.
       DIRECT-SUPERCLASSES: NIL.
       SUBCLASSES: NIL.
       PCL-CLASS: NIL.
    * 

However, the generic function seems to do the right thing, dispatching
with the CL:SYMBOL that is being returned by the reader even though I
had used PAIP::SYMBOL in the DEFMETHOD form.

    * (test 'some-symbol)
    "It worked!" 
    "It worked!"
    * 

And I can't seem to figure out a way to make PAIP::SYMBOL be a synonym
for the type named by CL:SYMBOL.

    * 
    (deftype paip::symbol ()
      `(cl:symbol))
    Warning:  Redefining class SYMBOL to be a DEFTYPE.


    Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
       NIL is not of type KERNEL:LAYOUT
       [Condition of type TYPE-ERROR]

    Restarts:
      0: [ABORT] Return to Top-Level.

    Debug  (type H for help)

    (LISP::%DEFTYPE SYMBOL #<Interpreted Function (LAMBDA # #) {40708E81}> NIL)
    Source: Error finding source: 
    Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
      target:code/macros.lisp.
    0] 0

I get the feeling that I'm missing something fundamental about the
interaction of types, the symbols that name them, and packages.

    * 
    (pprint
     (macroexpand-1
      '(deftype paip::symbol ()
        `(cl:symbol))))
    (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
      (LISP::%DEFTYPE 'SYMBOL
                      #'(LAMBDA (#:WHOLE-1772)
                          (BLOCK SYMBOL
                            (LET* ()
                              (UNLESS
                                  (<= 0
                                      (LISP::DOTTED-LIST-LENGTH
                                       (THE LIST (CDR #:WHOLE-1772)))
                                      0)
                                (LISP::DO-ARG-COUNT-ERROR 'DEFTYPE
                                                          'SYMBOL
                                                          (CDR #:WHOLE-1772)
                                                          'NIL
                                                          0
                                                          0))
                              (LET* ()
                                '(COMMON-LISP:SYMBOL)))))))
    * 

I'm surprised that the macroexpansion seems to be immune to the
package, turning PAIP::SYMBOL into SYMBOL.

Doh!  A second look at DEFTYPE <> tells me that the symbol is being
used as a name, not a symbol.

    * (symbol-name 'paip::symbol)
    "SYMBOL"
    * (symbol-name 'cl:symbol)
    "SYMBOL"
    * 

Since packages and not relavent to symbol names, then I suppose that
this describes why PAIP::SYMBOL is turned into SYMBOL in the
macroexpansion.  But clearly there is a big difference in the
following forms:

    * (typep 'some-symbol 'cl:symbol)
    T
    * (typep 'some-symbol 'paip::symbol)

    Type-error in KERNEL::OBJECT-NOT-INSTANCE-ERROR-HANDLER:
       NIL is not of type EXTENSIONS:INSTANCE
       [Condition of type TYPE-ERROR]

    Restarts:
      0: [ABORT] Return to Top-Level.

    Debug  (type H for help)

    (KERNEL:CLASS-TYPEP #<Layout for COMMON-LISP:SYMBOL {28037585}>
     #<KERNEL::STANDARD-CLASS SYMBOL {40556E55}> #<unavailable-arg>)
    Source: Error finding source: 
    Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
      target:code/pred.lisp.
    0] 0
    * 

How can one make PAIP::SYMBOL be equivalent to CL:SYMBOL in the above
TYPEP form?

From: Kalle Olavi Niemitalo
Subject: Re: PAIP: case studies in learning Common Lisp
Date: 
Message-ID: <87mzvxjzk8.fsf@Astalo.kon.iki.fi>
Damien Kick <······@email.mot.com> writes:

> I'm surprised that the macroexpansion seems to be immune to the
> package, turning PAIP::SYMBOL into SYMBOL.

Because you evaluated (cl:in-package #:paip), the current package
is PAIP, and PPRINT displays PAIP::SYMBOL as SYMBOL.

If you had loaded auxfns.lisp with LOAD instead of evaluating the
forms directly, then LOAD would have restored the current package
afterwards, presumably leaving you at CL-USER.

> Doh!  A second look at DEFTYPE <> tells me that the symbol is being
> used as a name, not a symbol.

That is not right.  DEFTYPE defines a type specifier whose name
is the symbol.  The symbol in turn has a string as its name, but
DEFTYPE does not care of that.

I think most of the operators that use names of symbols are
specified to treat them as string designators.  And then there is
LOOP.
From: Damien Kick
Subject: Re: PAIP: case studies in learning Common Lisp
Date: 
Message-ID: <ekh8hgwq.fsf@email.mot.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Damien Kick <······@email.mot.com> writes:
> 
> > I'm surprised that the macroexpansion seems to be immune to the
> > package, turning PAIP::SYMBOL into SYMBOL.
> 
> Because you evaluated (cl:in-package #:paip), the current package
> is PAIP, and PPRINT displays PAIP::SYMBOL as SYMBOL.

Right.  I was confusing myself because I was actually in PAIP-USER (I
don't think I included that detail in the previous post) but (eq
'paip::symbol 'paip-user::symbol) is/was true, which was why
PAIP::SYMBOL was printing as SYMBOL in PAIP-USER.

> > Doh!  A second look at DEFTYPE <> tells me that the symbol is
> > being used as a name, not a symbol.
> 
> That is not right.  DEFTYPE defines a type specifier whose name
> is the symbol.  The symbol in turn has a string as its name, but
> DEFTYPE does not care of that.

<nod> Having determined the cause of my confusion regarding symbols
used to name type specifiers, I find I can do the following with
CMUCL:

    * (in-package #:pg-user)
    #<The PLAYGROUND-USER package, 0/9 internal, 0/2 external>
    * (shadow 'symbol)
    T
    * (deftype symbol () 'cl:symbol)
    SYMBOL
    * (setf (find-class 'symbol) (find-class 'cl:symbol))
    #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>
    * (typep 'scord-la-dod 'symbol)
    T
    * 

I don't understand the difference in the output of DESCRIBE for the
two, however.

    * (describe 'symbol)
    SYMBOL is an internal symbol in the PLAYGROUND-USER package.
    It names a type specifier.
    * (describe 'cl:symbol)
    SYMBOL is an external symbol in the COMMON-LISP package.
    It names a class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL (sealed) {28037555}>.
       #<KERNEL::BUILT-IN-CLASS COMMON-LISP:SYMBOL (sealed) {28037555}> is a structure of type BUILT-IN-CLASS.
       CLASS-INFO: #<TYPE-CLASS KERNEL::CLASS>.
       ENUMERABLE: NIL.
       NAME: COMMON-LISP:SYMBOL.
       LAYOUT: #<Layout for COMMON-LISP:SYMBOL {28037585}>.
       STATE: :SEALED.
       DIRECT-SUPERCLASSES: (#<KERNEL::BUILT-IN-CLASS T (read-only) {2800491D}>).
       SUBCLASSES: #<EQ hash table, 1 entry {280375E5}>.
       PCL-CLASS: #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>.
       TRANSLATION: NIL.
    It names a PCL class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}>.
       #<BUILT-IN-CLASS COMMON-LISP:SYMBOL {281B663D}> is a class, it is an
       instance of BUILT-IN-CLASS.
       Its proper name is COMMON-LISP:SYMBOL.
       The direct superclasses are: (T), and the direct
       subclasses are: (NULL).  The class is finalized.  The class precedence list is:
       (COMMON-LISP:SYMBOL T)
       There are 18 methods specialized for this class.
       Its direct slots are:
       
    * 

DESCRIBE of PG-USER::SYMBOL doesn't mention any classes.  Contrasting
this with ACL 6.2:

    CG-USER(1): (in-package #:pg-user)
    #<The PLAYGROUND-USER package>
    PG-USER(2): (shadow 'symbol)
    T
    PG-USER(3): (deftype symbol () 'cl:symbol)
    SYMBOL
    PG-USER(4): (setf (find-class 'symbol) (find-class 'cl:symbol))
    #<BUILT-IN-CLASS COMMON-LISP:SYMBOL>
    PG-USER(5): (typep 'scrod-la-dod 'symbol)
    T
    PG-USER(6): (describe 'symbol)
    SYMBOL is a COMMON-LISP:SYMBOL.
      It is unbound.
      It is INTERNAL in the PLAYGROUND-USER package.
      It names a class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL>
      Its property list has these indicator/value pairs:
    EXCL::DEFTYPE-EXPANDER      #<Interpreted Function SYMBOL @ #x21009312>
    PG-USER(7): (describe 'cl:symbol)
    COMMON-LISP:SYMBOL is a COMMON-LISP:SYMBOL.
      It is unbound.
      It is EXTERNAL in the COMMON-LISP package and accessible in [...]
      It names a class #<BUILT-IN-CLASS COMMON-LISP:SYMBOL>
      Its property list has these indicator/value pairs:
    [...]
    PG-USER(8): 

This mentions the BUILT-IN-CLASS for both PG-USER::SYMBOL and
CL:SYMBOL.  However, I think that I understand most what I
wanted/needed to know from my original question.  Thanks.
From: Kaz Kylheku
Subject: Re: PAIP: case studies in learning Common Lisp
Date: 
Message-ID: <1104366971.226169.36480@z14g2000cwz.googlegroups.com>
Damien Kick wrote:
> Now, PAIP::SYMBOL should be FBOUNDP with the function provided by
> PAIP.  However, I want PAIP::SYMBOL to be a superset of CL:SYMBOL;
> e.g. I want PAIP::SYMBOL to name the same type as CL:SYMBOL.
> Basically, I want PAIP::SYMBOL to be a synonym for CL:SYMBOL with an
> additional SYMBOL-FUNCTION.

This is not possible. Either PAIP::SYMBOL and CL:SYMBOL are the same
symbol, or they are distinct. If they are the same symbol, then there
is only one object to speak of with one set of properties. One function
binding, and so on.

>     * (describe 'paip::symbol)
>     SYMBOL is an internal symbol in the PAIP package.

I.e. it is completely unrelated to CL:SYMBOL. It just has the same
name, but entered in a different package.

> I get the feeling that I'm missing something fundamental about the
> interaction of types, the symbols that name them, and packages.

There is no interaction, really. Symbol names and packages are one
layer, types are another. From the point of view of naming a type, a
symbol's name and package are irrelevant; only its identity matters.

When a symbol names a type, that symbol *object* in memory is
associated with that type. The type has a name, and that name is the
symbol. The symbol also has a name and it is "SYMBOL". But "SYMBOL" is
not that type name; it's a character string which names the symbol, and
by which the symbol is uniquely known within a package.

> I'm surprised that the macroexpansion seems to be immune to the
> package, turning PAIP::SYMBOL into SYMBOL.

SYMBOL is what the printed representation of PAIP::SYMBOL looks like
when the current package is "PAIP". The shorthand notation, without any
colons, resolves to the current package.

Macroexpansion is immune to package issues because it happens after
read time. Packages play a role at read time, when Lisp data is read
from printed form, and symbols are converted from printed
representation into objects.

> Doh!  A second look at DEFTYPE <> tells me that the symbol is being
> used as a name, not a symbol.
>
>     * (symbol-name 'paip::symbol)
>     "SYMBOL"
>     * (symbol-name 'cl:symbol)
>     "SYMBOL"
>     *
>
> Since packages and not relavent to symbol names, then I suppose that
> this describes why PAIP::SYMBOL is turned into SYMBOL in the
> macroexpansion.

It's not the macroexpansion that turns it into SYMBOL, but rather the
Lisp printer, which converts the result of the macroexpansion into
printed form for you to read (the P in REPL, or read-eval-print loop).

Because your current package (as identified by the *package* special
variable) is "PAIP", the printer chooses the short form for printing
symbols which are in that package.

The macroexpansion itself works with the symbol objects themselves
(pointers in memory), not their names.

But clearly there is a big difference in the
> following forms:
>
>     * (typep 'some-symbol 'cl:symbol)
>     T
>     * (typep 'some-symbol 'paip::symbol)

>
> How can one make PAIP::SYMBOL be equivalent to CL:SYMBOL in the above
> TYPEP form?

One straightforward way, since CL:SYMBOL is an exported symbol from the
"CL" package is simply to import the "CL" package into PAIP (and ensure
that you don't locally shadow the symbol called "SYMBOL").

(defpackage "PAIP"
(:use "CL"))

Now you can show that the two notations are exactly the same object:

(eq 'cl:symbol 'paip::symbol)  ==>   T

As such, you can't hang a different set of bindings or other properties
on one versus the other.