Re: KIF and packages
James Rice <Rice@sumex-aim.stanford.edu>
Full-Name: James Rice
Message-id: <2863813354-1163576@KSL-EXP-35>
Sender: RICE@ksl-exp-35.stanford.edu
Date: Mon, 1 Oct 90 16:42:34 PDT
From: James Rice <Rice@sumex-aim.stanford.edu>
To: Tom Gruber <Gruber@sumex-aim.stanford.edu>,
"Matthew L. Ginsberg" <ginsberg@sunburn.stanford.edu>,
interlingua@vaxa.isi.edu
Cc: Daneel Pang <pang@sumex-aim.stanford.edu>
Subject: Re: KIF and packages
In-reply-to: Msg of Wed, 26 Sep 90 15:33:46 PDT from Tom Gruber <Gruber@sumex-aim.stanford.edu>
--> > That certainly will need to be addressed, but it is
--> > unfortunately not that simple. The reason is that
--> > most systems have already got something called
--> > "true" and when you do the use-package, you get a
--> > name conflict. (I know this from my experience
--> > trying to port a system that uses something called
--> > "true".)
--> > My own suggestion would be to make the symbols
--> > exported as Tom suggests, but *not* expect the user
--> > to do a use-package. Simply put the interlingua
--> > document itself in the KIF package and let the
--> > recipient sort it out as appropriate to his system.
--> Of course. There should be no REQUIREMENT or
--> ASSUMPTION that the user does a use-package. In
--> practice I recommend against it when trying to port
--> somebody else's code, and it is especially unfriendly
--> when an application does it "for the user". The fact
--> that there is a significant overlap of symbols in KIF
--> and Lisp, and that many users will, in fact, try to
--> import KIF symbols into a package that also uses
--> common-lisp, motivates the design decision to have the
--> KIF package use the common-lisp. If the user of a
--> system that defines "mypackage::true" wants to read or
--> print KIF KBs, she may want to say
--> (defpackage "MYPACKAGE"
--> (:use "KIF" "COMMON-LISP") (:shadow KIF:TRUE) ...)
--> or she may want to read and print her KBs with
--> KIF:TRUE and KIF:=>.
--> tom
I echo these sentiments. I believe that KIF should be
utterly clear about where its symbols are and I think that
a definition of the KIF package as something like the
following seems reasonable:
(defpackage "KNOWLEDGE-INTERCHANGE-FORMAT"
(:Use "COMMON-LISP")
(:Nicknames "KIF")
(:Export "ALIKE" "IS" "<-" "<--" "CUT" "<==" "==>"
"=>" "<=>" "EXISTS" "FORALL" "DEFOBJECT"
"DEFUNCTION" "DEFPRIMRELATION" "DEFRELATION"
"SEQVARP" "VARP" "TRUE" "DENOTATION" "NAME"
"PROBABILITY" "PREDICATE-COMPLETION"
"CIRCUMSCRIPTION" "CIRC" "ACTION" "PERCEPT"
"CALL" "PROVABLE" "LISP" "=<"))
Notes:
a) The above was put together by looking through KIF 2.0
for symbols that seemed to be defined/mentioned. There
may well be errors in my search so this is intended to be
used mainly for example, not as a concrete proposal,
though I believe that the "real thing" should look not
much different from this.
b) I believe that, like the LISP package, the KIF package
should have no symbols interned in it other than those
symbols that are the documented, exported symbols.
Anything else is part of a KIF implementation and belongs
in some implementation dependent (e.g. KIF-INTERNALS or
actually something like EPIKIT-INTERNALS) package. This
is essential, in practice, since multiple KIF using
implementations might need to coexist in the same address
space. We cannot allow different implementations to
define functions and such in the KIF package since they
might be smashed by other implementations. Similarly, I
believe that the KIF package should not SHADOW any
symbols. This would prevent the KIF definition and hence
package from developing confusing new meanings for already
well understood terms (symbols.)
c) I believe that the KIF package should use the CL
package (as specified in CLtL V.2), not the LISP package.
It would be foolish to assume that KIF users would not
want CLOS and such-like and the act of building on
COMMON-LISP has the beneficial effect of preventing KIF
>From defining any functionality to be associated with a
symbol with a "well understood" meaning. Thus, using this
strategy would prevent us from defining a KIF DefMethod
that would clash in functionality with the CL DefMethod.
d) The issue of TRUE, above, is a little bit of a red
herring, since TRUE is not a CL defined symbol. We would
only have a problem if, for example, we were to try to
define MYPACKAGE as
(defpackage "MYPACKAGE"
(:use "TICL" "KIF" "COMMON-LISP")
...)
without saying:
(defpackage "MYPACKAGE"
(:use "TICL" "KIF" "COMMON-LISP")
(:shadow KIF:TRUE)
...)
where TICL is the name of TI's CL + environment/useful
things package and already includes a definition for
TICL:TRUE. Clearly, in the general case, there will be
symbols in packages that the user might want to use that
share the same PName as KIF symbols. This is a well
understood problem and should not prevent the KIF standard
>From doing the right thing.
e) Since KIF is not part of the LISP standard we cannot
expect the KIF package to be present when a KIF using
application is loaded, thus we would expect to have to
create the KIF package. However, the KIF package might
already have been created by some other application and so
we should make sure that we specify either:
i) exactly the set of symbols that all implementations
should export from the KIF package and exactly which
packages should be used (I believe this should be the
COMMON-LISP package), or
ii) we should specify that implementations of KIF are
allowed to export symbols but are not allowed to unexport
any existing exported symbols that other implementaions
might have exported. A similar argument applies to
package use.
f) KIF should specify a feature. Thus there should be a
(pushnew :KIF *features*)
for any implementation.
g) Some specification is needed as to the meaning of KIF
forms such as DEFRELATION. Is this supposed to be a
macro? If so, who defines it? Can you have multiple
coexistent implementations of KIF macros?
The problem here is one of whether KIF is going to be used
simply as an interchange language, in which case no
symbols in the KIF package need be FBOUND, since the
symbols will be given meaning by the parser for any given
implementation, or whether implementations are going to
choose to use KIF as a subset of themselves. EPIKIT is
sort of an example of this.
I believe that KIF should probably state something like
one of the following:
i) it is an error for any symbol in the KIF package to be
either BOUND, FBOUND, or have any properties associated
with it.
or
ii) It is an error for a user or program to BIND, FDEFINE or
associate a property with a symbol in the KIF package.
Some symbols in the KIF package have the following
definitions/fdefinitions...
It is an error for an implementation of KIF to overwrite
the definition of a KIF symbol.
In the former case we assert that KIF symbols are used
effectively only as parsing tokens by implementations.
Symbols such as 'kif:=> will have to be compiled or
translated into an internal representation of the
appropriate implication for an implementation or
interpreted in order to be operationalised by any
implementation.
The latter states that KIF will provide a set of clearly
defined hooks for implementations such that
implementations will allow users effectively to type pure
KIF sentences to a listener and they will be
operationalized appropriately without the need for an
implementation specific reader/parser. A portable
universal specification for the behavior of the KIF
symbols can be made. Any KIF implementation may make the
appropriate definition of these KIF symbols if they are
not yet defined (see below).
There are doubtless numerous arguments on each side. If
the latter interpretation is chosen, however, then I
believe that some specification of the following form will
be needed in order to allow a true, portable KIF
definition that will allow the modular coexistence of
multiple KIF implementations:
i) There should exist a package called KIF internals
defined by:
(defpackage kif-internals
(:use "COMMON-LISP")
(:export "*KIF-IMPLEMENTATIONS*"
"DEFRELATION-INTERNAL" .....))
This package should be used for the definition of
components of KIF that allow the operationalization of KIF
knowledge bases and their connection to tools that might
manipulate them.
ii) There should exist a variable:
kif-internals:*kif-implementations* [Variable]
A list of all of the currently loaded implementations of
KIF. Implementors or users of KIF are at liberty to add
the name of their systems to this list. Example:
(pushnew :epikit kif:*kif-implementations*)
Each element in the list of implementations will be used
to invoke methods associated with that implementation.
iii) For each macro type of sentence specifier in KIF
define it in a manner such as the following:
DefRelation [Macro]
Defines a new relation. This macro is defined to be
implemented as follows:
(in-package "KIF-INTERNALS")
(defmacro Kif:DefRelation (name (&rest variables) &body body)
`(progn ,@(loop for impl in *kif-implementations*
collect (defrelation-internal impl name variables body))
',name))
(defgeneric defrelation-internal (implementation name variables body)
(:documentation "Generic function to implement DefRelation")
;;; Default method in case an implementation chooses not to implement
;;; anything for this generic function.
(:method ((implementation name variables body) nil)))
Each implementation that uses KIF might choose to provide
an implementation for DefRelation should define a method
of the form:
(in-package "AN-IMPLEMENTATION-PACKAGE") ;; which might use "KIF-INTERNALS"
(defmethod defrelation-internal
((implementation (eql <<:my-impl>>)) name variables body)
;;; The actual implementation of defrelation in the my-impl system.
`(progn .......))
where "<<:my-impl>>" is the name of the implementation that has
been pushed onto the list kif-internals:*kif-implementations*.
Note: this allows a simple, portable (pure CL),
public-domain set of hooks that can be part of any
implementation that might choose to use KIF.
---------------------------------------------------------------
One of the advantages of designing a new language from
scratch is that it allows you to finesse a bunch of
horrible problems that crop up in implementing badly
designed existing languages. Getting the package
structure right and ensuring that different
implementations and applications can coexist is an example
of something that is not hard to do well and acrues huge
benefits when it is done right.
Rice.