Symbols and Packages

Symbols

A symbols is assured to be unique if it is interned in a package. The uniqueness is tested by symbol’s print-names. There are no duplicated symbols in a package which have the same print-name as other symbols in the package. When EusLisp is running, there always is a special package called the current package, which is referred by lisp:*package*. When a symbol without a package name is read by the reader, the current package is searched for to locate the symbol with the same print-name. If no such symbol is found, search is continued in the packages listed in the package use list of the current package. If still no such symbol is found, a new symbol object with the designated print-name is created and is interned in the current package. The package can be specified by prefixing the package name followd by a colon(:). If a symbol name is preceeded by a package name, the search begins in the designated package.

Every symbol may have at most one home package. If a symbol has no such home package, it is said to be an uninterned symbol. Uninterned symbols can be created by the gensym or make-symbol function, and they are prefixed by “#:” when printed. Since these symbols are not interned, two such symbols with the same print-name are not guaranteed to be equal.

Usually, when the lisp reader encounters a symbol, the reader converts the print-name string of the symbol to uppper case. Thus, for example, if you input (symbol-name ’car), EusLisp responds “CAR” instead of “car”. Note that (make-symbol “car”) returns \(|\)car\(|\) instead of car or CAR. If you want the reader to make symbols constituted by lower case letters, use reader’s escapes, \(\backslash\) and \(|...|\).

symbolp object

returns T if object is an instance of CLASS symbol or its subclasses.

symbol-value symbol

gets symbol’s special value. Lexical (local) variables’ values cannot be retrieved by this function.

symbol-function symbol

gets symbol’s global function definition. Lexical (local) function cannot be taken by this function.

symbol-package sym

returns the package where sym is interned.

symbol-name sym

returns sym’s print-name. Note that symbol-name does not copy the pname string, whereas string does. Thus, if you change the string returned by symbol-name, the symbol becomes inaccessible through normal intern procedure.

symbol-plist sym

Returns sym’s property list (plist). EusLisp’s plist takes the same form as an association list, which consists of dotted pairs of an attribute name and its value. This is incompatible with Common Lisp definition which requests a plist to have linear lists of attribute name and value. In EusLisp, plist is not the unique facility of symbols. Any objects instantiated from a class that inherits propertied-object can have property lists. To set and retrieve these plists in propertied-objects, propertied-object-plist macro should be used instead of symbol-plist. However, get and putprop work for either object.

boundp symbol

Checks if symbol has a globally bound value. Note that symbols used for local and object variables always have bound value and boundp cannot test the bound state of these local variables.

fboundp symbol

Checks if symbol has a globally bound function definition.

makunbound symbol

is forced to be unbound (to have no special value). Note that lexical (local) variables always have values assigned and cannot be makunbounded.

get sym attribute

retrieves sym’s value associated with attribute in its plist. = (cdr (assoc attribute (symbol-plist sym)))

putprop sym val attribute

Putprop should be replaced with the combination of setf and get.

remprop sym attr

removes attribute-value pair from sym’s property list.

setq &rest forms

for each form in forms, assigns the second element to the first element, which is either a symbol or a dotted-pair. The first element is searched for in the name spaces of local variables, object variables, and special variables in this order unless explicitly declared special.

set sym val

assigns val to the special value of sym. Set cannot assign values to local or object variables.

defun symbol lambda-list &rest body

defines a global function to symbol. First element in body can be a documentation string. Use flet or labels for defining local functions.

defmacro symbol lambda-list &rest body

defines a global macro. EusLisp does not have facilities for defining locally scoped macros.

defvar var &optional (init nil) doc

If var symbol has any special value, defvar does nothing. If var is unbound, it is declared to be special and init is set to its value.

defparameter var init &optional doc

declares var to be special and init is set to its value, even if var already has value.

defconstant sym val &optional doc

sets val as sym’s special value. Unlike defvar, defparameter and setq, the value set by defconstant cannot be altered by these forms. If the value of a constant symbol is tried to be changed, an error is reported. However, another defconstant can override the previous constant value, issuing a warning message.

keywordp obj

T if obj is a symbol and its home package is KEYWORD.

constantp symbol

T if the symbol is declared to be constant with defconstant macro.

documentation sym &optional type

retrieves documentation string of sym.

gensym &optional x

creates a new uninterned symbol composed of a prefix string and a suffix number like g001. Uninterned symbols are denoted by the #: package prefix indicating no package is associated with the symbols. Symbols with #: prefix are unreadable symbols and the reader cannot create references to these uninterned symbols. X can either be a string or an integer, which is used as the prefix or the suffix.

gentemp &optional (prefix “T”) (pkg *package*)

creates a new symbol interned in pkg. In most applications, gensym is preferable to gentemp, because creation of uninterned symbols is faster and uninterned symbols are garbage collect-able.

Packages

Packages provide separate name spaces for groups of symbols. Common Lisp introduced the package system in order to reduce the symbol (function and variable name) conflict problems in the course of developing huge software systems which require more than one programmer to work together. Each package may have internal symbols and external symbols. When a symbol is created in a package, it is always internal, and it becomes external by export. External symbols in different packages are referenced by prefixing the package name and a single colon, as x:*display*, while referencing internal symbols in other packages requires double colons, as sys::free-threads. In order to omit this package prefixing, a package may symbols from other packages. Moreover, allows importing all external symbols from another package at once. When symbols are exported or imported, symbol name conflicts can be detected, since every symbol in any packages must have the unique print name. allows creating a symbol with the same print name as the existing symbol in a package by virtually removing the old symbol from the package.

EusLisp defines following eight packages;

lisp:
All the lisp functions, macros, constants, etc.
keyword:
keyword symbols
unix:
unix system calls and library functions
system:
system management or dangerous functions; nicknames=sys,si
compiler:
EusLisp compiler; nicknames=comp
user:
User’s work space
geometry:
geometric classes and functions
xwindow:
X-window interface; nickname=x

These packages and user-defined packages are linked in the system’s package list, which can be obtained by list-all-packages. Each package manages two hash tables to find and locate internal and external symbols. Also, a package records its name (string or symbol) and a list of nick names, and a list of other packages that the package is using. Package* is a special variable that holds the current package for read and print. If is not user:, top-level prompt changes to indicate the current package, like mypkg:eus$.

*lisp-package* **

Lisp package.

*user-package* **

User package.

*unix-package* **

Unix package.

*system-package* **

System Package.

*keyword-package* **

Keyword Package.

find-symbol string &optional (package *package*)

finds and locates the symbol which has string as its print name in package. If found, the symbol is returned, NIL otherwise.

make-symbol string

makes a new uninterned symbol by the print name of string.

intern string &optional (package *package*) (klass symbol)

tries to find a symbol whose print-name is same with string. If the search succeeds, the symbol is returned. If fails, a symbol whose print-name is string is newly made, and is located in package.

list-all-packages **

returns the list of all packages ever made.

find-package name

find the package whose name or nickname is equal to the name string.

make-package name &key nicknames (use ’(lisp))

makes a new package by the name of name. Name can either be a string or a symbol. If the package already exists, error is reported.

in-package pkg &key nicknames (uses ’(lisp))

changes the current package (the value of package*) to pkg.

package-name pkg

returns the string name of the pkg package.

package-nicknames pkg

returns a list of nicknames of pkg.

rename-package pkg new-name &optional new-nicknames

changes the name of pkg to new-name and its nicknames to new-nicknames, which can either be a symbol, a string, or a list of symbols or strings.

package-use-list pkg

returns the list of packages which are used by pkg.

packagep pkg

T if pkg is a package.

use-package pkg &optional (curpkg *package*)

adds pkg to curpkg’s use-list. Once added, symbols in pkg become visible from curpkg without package prefix.

unuse-package pkg &optional (curpkg *package*)

removes pkg from curpkg’s use-list.

shadow sym &optional(pkg *package*)

makes a symbol interned in pkg, by hiding existing sym.

export sym &optional (pkg *package*)

is a symbol or a list of symbols. export makes sym accessible from other packages as external symbol(s). Actually, sym is registered as an external symbol in pkg. If a symbol is exported, it becomes accessible using a single colon “:” as package marker, whereas unexported symbols require double colons. In addition, exported symbols do not need colons when they are used by use-package or they are imported into the package. Whether a symbol is exported or not is attributed to packages where it is interned, not to each symbol. So, a symbol can be internal in a package and external in another. Export checks sym to have name conflict with symbols in other packages using pkg. If there is a symbol having the same print name with sym, “symbol conflict” error is reported.

unexport sym &optional pkg

If sym is an external symbol in pkg, it is unexported and becomes an internal symbol.

import sym &optional (pkg *package*)

is a symbol or a list of symbols. import makes symbols defined in other packages visible in pkg as an internal symbol without package prefix. If there is already a symbol that has the same print name as sym, then an “name conflict” error is reported.

do-symbols (var pkg &optional result) &rest forms

repeats evaluatiing forms for each binding of var to symbols (internal or external) in pkg.

do-external-symbols (var pkg &optional result) &rest forms

repeats evaluating forms for each binding of var to external symbols in pkg.

do-all-symbols (var &optional result) &rest forms

repeats evaluating forms for each binding of var to symbols in all packages. Note that forms may be evaluated more than once to a symbol if it appears more than one package.