Text

The four causes of symbol conflicts

A symbol conflict arises when a package operation would result in two distinct symbols with the same name being accessible in a single package. There are exactly four ways this can happen.

Inheriting: When you use (via use-package or the defpackage :use clause) a package that exports a distinct symbol sharing the same name with a symbol already accessible in the using package. The conflict can arise between two inherited symbols, or between an inherited symbol and a present symbol.

Importing: When you import a symbol and a distinct symbol with the same name is already accessible in the target package.

Exporting: When you export a symbol from a package and a distinct symbol with the same name is already accessible in any package that uses that package.

Uninterning: When you unintern a shadowing symbol and the absence of its shadowing results in two distinct symbols with the same name being accessible via inheritance.

Here are short examples of each case. They all assume an environment in which this package definition is in effect:

(defpackage #:auto
  (:documentation "An automotive package.")
  (:use)
  (:intern #:tan)
  (:export #:car))

Inheritance conflict:

(defpackage #:inheritance-conflict
  (:use #:cl #:auto))

=> USE-PACKAGE #[PACKAGE "COMMON-LISP"] causes name-conflicts in
#[PACKAGE "INHERITANCE-CONFLICT"] between the following symbols:
  AUTO:CAR, COMMON-LISP:CAR
   [Condition of type NAME-CONFLICT]
See also:
  Common Lisp Hyperspec, 11.1.1.2.5 [:section]

Import conflict:

(defpackage #:import-conflict
  (:use #:cl))

(import '(auto:car) '#:import-conflict)

=> IMPORT AUTO:CAR causes name-conflicts in
#[PACKAGE "IMPORT-CONFLICT"] between the following symbols:
  AUTO:CAR, COMMON-LISP:CAR
   [Condition of type NAME-CONFLICT]
See also:
  Common Lisp Hyperspec, 11.1.1.2.5 [:section]

Export conflict:

(defpackage #:export-conflict
  (:use #:cl #:auto)
  ;; Avoid inheritance conflict with shadowing
  (:shadow #:car))

(export 'auto::tan '#:auto)

=> EXPORT AUTO::TAN causes name-conflicts in
#[PACKAGE "EXPORT-CONFLICT"] between the following symbols:
  AUTO::TAN, COMMON-LISP:TAN
   [Condition of type NAME-CONFLICT]
See also:
  Common Lisp Hyperspec, 11.1.1.2.5 [:section]

Unintern conflict:

(defpackage #:unintern-conflict
  (:use #:cl #:auto)
  ;; Avoid inheritance conflict with shadowing
  (:shadow #:car))

(unintern 'unintern-conflict::car '#:unintern-conflict)

=> UNINTERN UNINTERN-CONFLICT::CAR causes name-conflicts in
#<PACKAGE "UNINTERN-CONFLICT"> between the following symbols:
  AUTO:CAR, COMMON-LISP:CAR
   [Condition of type NAME-CONFLICT]
See also:
  Common Lisp Hyperspec, 11.1.1.2.5 [:section]

If you use Common Lisp, you have to interact with the package system. I think the best way to get along with the package system is not to keep it at arm’s length while holding your nose, but to learn how it works, inside and out.

Text

A little bit of file-position

When used with one argument, file-position returns an integer representing the stream’s file position:

* (defvar *s* (open "data.bin" :element-type '(unsigned-byte 8))
=> *S*

* (read-byte *s*)
=> 42

* (read-byte *s*)
=> 107

* (file-position *s*)
=> 2

When used with two arguments, file-position sets the stream position:

* (file-position *s* 1)
=> T

* (read-byte *s*)
=> 107

When used this way, the position is often given as an integer, but the function actually accepts a designator. An integer position value represents itself, the keyword :start represents 0 (the first position in the stream), and the keyword :end represents the last position in the stream.

What would life be like without :start and :end? For :start, not too difficult; you could just use 0. But without :end you would need to use some other function, such as file-length, to correctly position the stream at the end.

Text

A brief history of Lisp

For a 1500-word history of Lisp up to the point of Common Lisp standardization, see section 1.1.2 of the spec. It covers the institutions, projects, people, and influential ideas involved in the creation and evolution of Lisp over the course of several decades, from McCarthy at Dartmouth in the 1950s to the many active branches of Lisp in the 1980s.

Text

Putting the R in REPL

Try this in your REPL:

* (let (#'42) (+ . #'5))
=> 47

If you find it perplexing, and you use SBCL, evaluating + next in the REPL might help clear things up.

Text

Using an adjustable displaced array as a cursor on another array.

Scanning a string can be done using input functions withwith-input-from-string:

(with-input-from-string (stream "Hello World!  How do you do? ")
  (let ((c (make-string 4)))
    (loop
      :for pos = (read-sequence c stream)
      :while (= pos (length c))
      :do (print c)
      :finally (terpri))))

"Hell" 
"o Wo" 
"rld!" 
"  Ho" 
"w do" 
" you" 
" do?" 
nil

This can also be done using a displaced adjustable array, without copying the data that is read:

(defun make-vector-cursor (vector &key (size 0) (offset 0))
  (make-array size
              :element-type (array-element-type vector)
              :adjustable t
              :displaced-to vector
              :displaced-index-offset offset))

(defun advance-cursor (cursor &key (size (length cursor)))
  (multiple-value-bind (vector offset) (array-displacement cursor)
    (adjust-array cursor size
                  :element-type (array-element-type vector)
                  :displaced-to vector
                  :displaced-index-offset (+ offset (length cursor)))))
(let ((c (make-vector-cursor "Hello World!  How do you do? " :size 4)))
  (loop
    :do (print c)
    :while (ignore-errors (advance-cursor c))
    :finally (terpri)))

"Hell" 
"o Wo" 
"rld!" 
"  Ho" 
"w do" 
" you" 
" do?" 
NIL
(let ((c (make-vector-cursor "Hello World!  How do you do? " :size 1)))
  (loop
    :for size :from 1
    :do (print c)
    :while (ignore-errors (advance-cursor c :size size))
    :finally (terpri)))

"H" 
"e" 
"ll" 
"o W" 
"orld" 
"!  Ho" 
"w do y" 
"ou do? " 
nil

This post courtesy of Pascal J. Bourguignon

Text

Binding keyword arguments

By default, keyword argument variable bindings match the name of the keyword used to pass the value. For example:

(defun keytest (&key foo)
  (list foo))

* (keytest :foo 42)
=> (42)

However, the variable doesn’t have to match the keyword provided. The following syntax will accept a keyword of :foo in the function call but bind a variable named bar:

(defun keytest (&key ((:foo bar)))
  (list bar))

* (keytest :foo 42)
=> (42)

Binding keywords this way can be helpful when binding a plist via destructuring-bind when you don’t want the plist keys to name the variables you actually want to use in the scope of the destructuring bind. For example, the plist may contain (:customer-id 42 ...), but in your context it makes more sense to bind a variable named old-customer-id.

The “keyword” also need not be a keyword:

(defun keytest (&key ((foo bar)))
  (list bar))

* (keytest 'foo 42)
=> (42)

Using internal symbols as function keyword arguments is one way to indicate that they are not part of a function’s public API.

Text

Multiple export clauses in defpackage

The syntax for defpackage allows multiple export clauses. I like to use this feature to visually group related symbols.

(defpackage #:myproject
  (:use #:cl)
  ;; Web stuff
  (:export #:fetch
           #:parse-url
           #:status)
  ;; File utilities
  (:export #:lines
           #:first-line
           #:touch)
  ...)

Although it has no effect on the semantics, I find it helpful for reading.

Text

A simple REPL

Here’s a very simple REPL that includes the *, **, and *** variables:

(defun repl ()
  (princ "> ")
  (loop 
    (shiftf *** ** * (eval (read))) 
    (format t "~a~&> " *)))
  

Provided by Stas Boukarev.

Text

Printing package-qualified symbols

When *print-escape* is true, symbols are normally printed with package prefixes only if the current package *package* is not the symbol’s home package. It’s easy to make sure that a symbol is always printed with a package prefix, e.g. for debugging.

When the current package is the keyword package, non-keyword symbols are printed with package prefixes, and keywords are printed with their normal colon prefix. For example, in SBCL:

(in-package #:cl-user)
(let ((*package* (find-package "KEYWORD")))
  (prin1-to-string '(car stream :car quit)))

=> "(COMMON-LISP:CAR COMMON-LISP:STREAM :CAR SB-EXT:QUIT)"

For full details, see 22.1.3.3.1, Package Prefixes for Symbols.

Text

Evaluating the last expression

In the REPL, +, ++, and +++ have as values the three most recently evaluated expressions. A quick way to evaluate the previous expression, especially handy in a REPL without input history, is

#.+

It’s equivalent to (eval +).

(Thanks to Anton Kovalenko.)