Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are variable and symbol different in Lisp?

Tags:

lisp

numberp is a predicate in Lisp, and (numberp 1) returns T as expected. But if I only type numberp in the console, it prompts that the variable name is undefined.

What's the difference between these 2?

like image 311
Thomson Avatar asked Nov 30 '22 07:11

Thomson


1 Answers

The question is slightly wrong already.

We are talking about different things in Common Lisp:

  • symbol : that's a data structure in Lisp. A symbol is a data object with a name, a value, a function, a package and possibly more.

In Common Lisp the symbol can have both a value and a function (or macro).

  • a variable is an identifier for a value in Lisp code

There are top-level variables defined by DEFVAR and DEFPARAMETER. There are also local variables defined by LAMBDA, DEFUN, LET, LET* and others.

(defun foo (i-am-a-variable) ...)

(defparameter *i-am-a-global-variable* ...)
  • a named function is an identifier for a function in Lisp code. Named functions are introduced on the top-level by DEFUN, DEFGENERIC and DEFMETHOD. There are also local named functions defined by FLET and LABELS.

Example:

(defun i-am-a-function (foo) ...)

(flet ((i-am-a-function (foo) ...)) ...)

To further complication function names and variable names are symbols in the source code.

Example:

(type-of (second '(defun foo () nil)))  -->  SYMBOL

Let's look at functions and variables:

(defun foo ()
  (let ((some-name 100))
    (flet ((some-name (bar) (+ bar 200)))
       (+ some-name (some-name some-name)))))

Above code uses a variable and a function with the same symbol in the source code. Since functions and variables have their own namespace, there is no collision.

(+ some-name (some-name some-name))

Above then means we add the variable to the result of the function call on the variable.

This has the practical effect that you can do something like this:

(defun parent (person) ...)

(defun do-something (parent)
   (parent parent))

You don't have to fear that your local variable names will shadow a global (or local) function. They simply are in different namespaces.

In Scheme there is only one namespace and we have to write

(define (foo lst) (list 'a lst 'n))

where in Common Lisp we can write:

(defun foo (list) (list 'a list 'n))

In Common Lisp there is no need to write lst instead of list - because there is no clash between the local variable list and the global function list.

Accessing the other namespace

To get a function object stored in a variable you can use FUNCTION.

(let ((my-function (function numberp)))
  (funcall my-function 10))

(function foo) can be written shorter as #'foo.

FUNCALL calls a function object.

OTOH, if you want to store a function object from a variable in the function namespace, there is only one way:

(setf (symbol-function 'foo) my-function)

It is also necessary that the object is really a function and not something else (a number, a string, ...). Otherwise you'll see an error.

The side effect of this is that a Common Lisp never has to check if in (foo bar) the FOO is really a function. There is no possibility that it can be other than a function or undefined.

like image 178
Rainer Joswig Avatar answered Dec 05 '22 00:12

Rainer Joswig