If a function call has two pairs of keyword arguments with the same keyword, the leftmost argument pair is used. This can be helpful if a list of keyword arguments is received and you want to selectively override some value in that argument list in application. There’s no need to use mutation or produce a fresh variation of the list.
(defun write-escaped (object &rest args &key &allow-other-keys) (apply 'write object :escape t args)) * (write "hello" :escape nil) hello * (write-escaped "hello" :escape nil) "hello"
See 188.8.131.52 for details.
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))
(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, 184.108.40.206.5 [:section]
(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, 220.127.116.11.5 [:section]
(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, 18.104.22.168.5 [:section]
(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, 22.214.171.124.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.
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.
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.
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.
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
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
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.
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.
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.
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 126.96.36.199.1, Package Prefixes for Symbols.