Lisp/Variables

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Variables

Lexical Variables

Two ways to bind variables: Function parameter definitions or LET.

(let ((x 1) (y 2))
  body)

(LET is almost equivalent to a function declaration.)

LET* behaves like a nested let, one for each variable. This allows later variables to reference earlier variables.

(let* ((x 1) (y (*x 2)))
  body)

The equivalent code is:

(let ((x 1))
  (let ((y (*x 2)))
    body)

These are lexically scoped. That is, x is different inside of the LET than it is outside.

Closures

Variables referenced by functions created within a LET (or DEFUN) will, if returned, still have access to those variables even though the scope has been left.

Dynamic (aka Special, aka Global) Variables

Two ways: DEFVAR or DEFPARAMETER.

Convention dictates that globals should start and end with *, eg *global-variable*

DEFVAR

(defvar *var* value
  "documentation")

If the variable is already declared, does nothing. Otherwise, creates and initializes it. If you rebuild the code but want to keep the state, use a DEFVAR.

DEFPARAMETER

(defparameter *var* value
  "documentation")

Always overrides whatever is there, unlike DEFVAR. These are parameters that should be reset when the code is recompiled.

DEFCONSTANT

You can define constants with DEFCONSTANT. Convention dictates that you surround the name with '+', eg, "+constant-variable+".

Constants can, and will, be overridden. Use them only for things that are really constant like π.

Using Lexical to Override Global Temporarily

(let ((*standard-output* *some-other-stream*))
  body)

Within body, *standard-output* is *some-other-stream*. Outside, it is what it would be otherwise.

Changing the Value

Use SETF to change the value.

(setf x 10)                   ; x = 10
(setf (aref a 0) 10)          ; a[0] = 10
(setf (gethash 'key hash) 10) ; hash[key] = 10
(setf (field o) 10)           ; o.field = 10

INCF and DECF are macros to make incrementing easier.

(incf x 10) ; x += 10
(decf x)    ; x -= 1

ROTATEF swaps two values, and returns NIL.

(rotatef a b)   ; a, b = b, a

SHIFTF slides the values to the left, and returns the left-most value.

(shiftf a b c 10)   ; a, b, c = b, c, 10