Skip to main content

+, ++, +++

+, ++, +++ Variable

Value Type:

an object.

Initial Value:

implementation-dependent.

Description:

The variables +, ++, and +++ are maintained by the Lisp read-eval-print loop to save forms that were recently evaluated.

The value of + is the last form that was evaluated, the value of ++ is the previous value of +, and the value of +++ is the previous value of ++.

Examples:

 
(+ 0 1)1
(- 4 2)2
(/ 9 3)3
(list + ++ +++)((/ 9 3) (- 4 2) (+ 0 1))
(setq a 1 b 2 c 3 d (list a b c))(1 2 3)
(setq a 4 b 5 c 6 d (list a b c))(4 5 6)
(list a b c)(4 5 6)
(eval +++)(1 2 3)
#.‘(,@++ d)(1 2 3 (1 2 3))


Affected By:

Lisp read-eval-print loop.

See Also:

- (variable), * (variable), / (variable), Section 25.1.1 (Top level loop)

, ∗∗, ∗∗∗ Variable

Value Type:

an object.

Initial Value:

implementation-dependent.

Description:

The variables *, **, and *** are maintained by the Lisp read-eval-print loop to save the values of results that are printed each time through the loop.

The value of * is the most recent primary value that was printed, the value of ** is the previous value of *, and the value of *** is the previous value of **.

If several values are produced, * contains the first value only; * contains nil if zero values are produced.

The values of *, **, and *** are updated immediately prior to printing the return value of a top-level form by the Lisp read-eval-print loop. If the evaluation of such a form is aborted prior to its normal return, the values of *, **, and *** are not updated.

Examples:

(values ’a1 ’a2) → A1, A2 
’b → B
(values ’c1 ’c2 ’c3) → C1, C2, C3
(list \* \*\* \*\*\*)(C1 B A1)
(defun cube-root (x) (expt x 1/3)) → CUBE-ROOT
(compile \*) → CUBE-ROOT
(setq a (cube-root 27.0))3.0
(\* \* 9.0)27.0

Affected By:

Lisp read-eval-print loop.

See Also:

- (variable), + (variable), / (variable), Section 25.1.1 (Top level loop)

Notes:

* (car /)

** (car //)

*** (car ///)

Expanded Reference: +, ++, +++

Basic Usage

The variables +, ++, and +++ hold the last three forms evaluated by the REPL's read-eval-print loop. + contains the most recently evaluated form, ++ the one before that, and +++ the one before ++.

(+ 1 2)
=> 3

;; In an interactive REPL:
;; + => (+ 1 2)
;; ++ => the form before that

How the History Shifts

Each time the REPL reads and evaluates a form, the history shifts: the old + becomes ++, the old ++ becomes +++, and + is set to the newly read form.

(list 'a)
=> (A)

(list 'b)
=> (B)

(list 'c)
=> (C)

;; In an interactive REPL after the above:
;; + => (LIST 'C) ; the most recently read form
;; ++ => the form that read +
;; +++ => (LIST 'B)

Re-evaluating Previous Forms

Since +, ++, and +++ hold the actual forms, you can re-evaluate a previous expression using eval.

(defvar *counter* 0)
=> *COUNTER*

(incf *counter*)
=> 1

;; In an interactive REPL, (eval +) would re-evaluate (incf *counter*)
;; (eval +) => 2
;; (eval +) => 3

Distinction from /, //, ///

The + family tracks the forms (unevaluated expressions) that were read, while the / family tracks the values that were produced. They are complementary.

(values 1 2 3)
=> 1
=> 2
=> 3

;; In an interactive REPL after the above:
;; + => (VALUES 1 2 3) ; the form that was read
;; / => (1 2 3) ; the list of values produced

Important Notes

These variables are maintained by the top-level REPL loop. They are not updated inside calls to eval or within code loaded from files -- only by the interactive read-eval-print loop itself.