Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the various differences in package systems between CL implementations?

Upon using (make-package 'test) (in-package test) in SBCL and CCL implementations, I've noticed that SBCL requires (cl:defun foo () (...)) or (cl:describe <symbol name here>) while CCL does not require any colons or double colons to use built-in symbols. It is my understanding that external symbols must be accessed with one colon, even if they are built-in. However CCL seems to work differently in this respect.

This confuses me somewhat regarding the use of external symbols. Are external symbols supposed to be available without any colons or is CCL just using/importing/inheriting automatically for convenience-sake?

Also, are there any more of these small but significant differences between the implementations regarding symbols and packages?

like image 727
Byte Avatar asked Dec 24 '22 12:12

Byte


1 Answers

The ANSI CL standard does not define which packages are used when you create a package

At some point in time, SBCL deviated from common practice, but still follows ANSI CL standards.

Using packages

Using packages in some other package means making their symbols available in that package.

You can get a package's use list by calling the function package-use-list.

It is undefined in the ANSI Common Lisp standard which packages a new package uses by default and also if it uses any at all.

Different common practice in implementations

There are now two common practices in implementations:

  • use COMMON-LISP and some implementation specific packages. CCL does that.

Example in CCL:

? (package-use-list (make-package "FOOBAR"))
(#<Package "CCL"> #<Package "COMMON-LISP">)

LispWorks:

CL-USER 17 > (package-use-list (make-package "FOOBAR"))
(#<The COMMON-LISP package, 0/4 internal, 978/1024 external>
 #<The HARLEQUIN-COMMON-LISP package, 0/4 internal, 365/512 external>
 #<The LISPWORKS package, 0/4 internal, 226/256 external>)
  • use no package. SBCL does that. If you want a new package to use the package COMMON-LISP, then you have to explicitly request that.

Example in SBCL:

* (package-use-list (make-package "FOOBAR"))

NIL

ABCL:

CL-USER(1): (package-use-list (make-package "FOOBAR"))
NIL

Writing portable code

Thus in SBCL and thus in portable Common Lisp you need to tell Lisp which packages should be used. To get the COMMON-LISP package used and only that package, you need to write:

(make-package "FOO" :use '("COMMON-LISP"))

Background

The original idea in the first Common Lisp was that one could write (in-package "FOO") at the REPL and the package was created with sensible defaults and one was directly in that package. The defaults were usually the package for the language (at that time called "LISP") and packages for common extensions (for example with CLOS+MOP, threads, ...).

Later Common Lisp was changed so that IN-PACKAGE did not create a package and it is defined that upon package creation it is undefined which packages are used and it is not required to use any package upon package creation. The SBCL maintainers then thought: instead of supporting common practice (which is not mentioned in the standard), provide a more neutral and predictable behaviour of using no package upon package creation.

Other differences

Most other differences in package systems in Common Lisp are around extensions to the standard. Examples:

  • hierarchical/nested packages

  • package prefixes to whole forms (not just symbols)

A bigger and incompatible change provided by some implementations as an option:

  • lowercase of all existing symbols and lowercasing reader. The standard defines symbols to be internally uppercase by default.

Undefined:

  • garbage collection of otherwise unreferenced, but interned, symbols
like image 149
Rainer Joswig Avatar answered Apr 26 '23 03:04

Rainer Joswig