What is a form in lisp ?

 

A form is anything which is to be evaluated .

Lisp is formed of two things : atoms and cons .

An atom is anything which is not a cons , a cons holds two references.

A list is formed of zero or more cons , where the second element of each cons , is a reference to the next cons , and the last element of the last cons is either a reference to the nil element , which represents the empty list () , or nothing , or the last element of the last cons is a reference to an atom . In the latter case , this list is called a dotted list . The elements of a list , are enclosed between a left parenthesis ( , and a right one )

This being said , a form or what can be evaluated in lisp , is either an atom or a cons, or more generally , instead or saying a cons , a list .

Evaluating atom forms

An atom form can be either , a self evaluating atom , or it can be a symbol .

Self evaluating atoms

If the form is an atom , an atom can be an atom which evaluates to itself , hence the value of evaluating the atom form , is the atom itself .

As an example , when evaluating a number such as 1 , it evaluates to 1 , or when evaluating a string such as "Hello world " , it evaluates to "Hello world " .

> 1
;;;evaluating 1 , yields 
;;;1 .
1

> "Hello world"
;;;evaluating "Hello world" , 
;;;yields "Hello world" .
"Hello world"

Symbols

If the form is an atom , an atom can also be a symbol . A symbol has , among other things , a name , a function property , and a value property .

If the form , is just a symbol , then what is evaluated is its value property . Some symbols evaluate to themselves , for example nil which is the empty list () , are both symbols , that evaluates to themselves .

>(symbolp nil )
;;;symbolp checks if the passed
;;;argument is a symbol , it 
;;;returns true , since nil 
;;;is a symbol .
T

> nil
;;;nil evaluates to itself 
nil

> (set 'ip "192.168.0.1" )
;;;set the value property of 
;;;the symbol ip to the string
;;;192.168.0.1 . ip is quoted
;;;using ' as not to be evaluated . 

> ip
;;;ip is evaluated , this returns
;;;the attribute value , which is :
"192.168.0.1"

Evaluating list forms

If what is to be evaluated is a non empty list , hence a list which contains some elements , then this list is called a compound form . The empty list ( ) is a symbol , and it evaluates to itself .

A list , depending on the first element , that it has , is called either : a function form , a lambda form , a macro form or a special form .

What is a function form ?

A function performs a computation , such as an addition , or a regular expression matching .

A function form is just a non empty list , which has as a first element , a symbol , which has a function property , that defines a function .

How a function form is evaluated , is that first the remaining elements of the list , known as the cdr of the list , are evaluated one after another , from left to right in order . Once their evaluation is done , their evaluation is applied to the function .

The standard does not specify , if the symbol which contains the function definition , is evaluated before, or after , or in between , the evaluation of the arguments .

> (+ 1 pi )
;;;This is a function form , 
;;;+ is a symbol , which has
;;;its function property defining
;;;a function . 
;;;First the remainder elements of 
;;;the list are evaluated from left 
;;;to right , one after the other . 
;;;1 evaluates to 1 .
;;;pi is a symbol , its value property 
;;;is evaluated , this returns :
;;; 3.1415926535897932385L0 .
;;;The standard does not specify , 
;;;when symbol + is evaluated . 
;;;Evaluating the symbol + , returns
;;;its function definition . 
;;;Once arguments and function definition
;;;evaluation is done , the function 
;;;is called with the evaluated arguments .
;;;The addition of 1 and  
;;; 3.1415926535897932385L0 , is 
;;;equal to 4.1415926535897932383L0 . 
4.1415926535897932383L0

To check if the function property , of a symbol is of a function type , functionp can be used , this is not the same as checking , if a symbol has its function property bounded , in this case fboundp can be used .

>(functionp '+ )
;;;' is used to quote a 
;;;symbol , as not to be
;;;evaluated .
;;;The symbol + is not
;;;of type function , it
;;;is a symbol which has 
;;;some properties . 
NIL

>(functionp #'+ )
;;;#' returns the value
;;;of the property : function
;;; of a symbol .
;;;The function property of 
;;;+ is of a function type . 
T

>(fboundp '+ )
;;;Checks if the symbol +
;;;has its property : function 
;;;bounded .
T

What is a lambda form ?

A lambda form , is a non empty list , which has as a first element , a lambda expression .

A lambda expression is a function , which has no name , and is defined by using a list , which first element is the symbol lambda , followed by a list , that contains the function parameters , known as , a lambda list , a lambda list can be empty , as such the function receives no arguments . The lambda list is followed by zero or more optional forms , which constitutes the function body . If the lambda function , has no body , it just returns nil , otherwise it returns the value of the last evaluated form .

The evaluation of a lambda form , is equivalent to using funcall . What this means , is that since funcall is a function , all its arguments are first evaluated from left to right , hence the lambda expression is first evaluated , followed by the remainder elements of the list , finally funcall will apply the gotten function , from the lambda expression , to the evaluated arguments , and returns the result .

> ((lambda (x ) (* x x ) ) 2 )
;;;This is a lambda form , since 
;;;the first element of the list
;;;is a lambda expression . 
;;;The lambda expression is first 
;;;evaluated to get its function 
;;;definition .
;;;The second element of the form , 
;;;is 2 , it evaluates to itself , 
;;;which is 2 .
;;;The gotten function is applied 
;;;to the argument 2 , this
;;;returns 4 .
4

What is a macro form ?

A function performs a computation , such as an addition , or sorting some elements , whereas a macro function , returns another form to be evaluated , in other words , it returns a new program .

A macro form , is a non empty list , which has as a first element a symbol , which has its function property , defining a macro .

To check if the function property of a symbol , defines a macro , macro-function can be used . macro-function returns nil , if the property function of a symbol , does not define a macro .

> (defmacro sub(var )
   `(- ,var 1 ) )
;;;Define the symbol sub ,
;;;function property with
;;;a macro definition . 
SUB

>> (macro-function '+ )
;;;The property function of the
;;;symbol + , is not a macro
;;; definition , hence 
;;; macro-function returns NIL .
NIL

> (macro-function 'sub )
;;;The symbol sub function property 
;;;is a macro definition , hence
;;;macro-function does not return
;;;nil . 
#<FUNCTION SUB (SYSTEM::<MACRO-FORM> SYSTEM::<ENV-ARG>)
  (DECLARE (CONS SYSTEM::<MACRO-FORM>)) (DECLARE (IGNORE SYSTEM::<ENV-ARG>))
  (IF (NOT (SYSTEM::LIST-LENGTH-IN-BOUNDS-P SYSTEM::<MACRO-FORM> 2 2 NIL))
   (SYSTEM::MACRO-CALL-ERROR SYSTEM::<MACRO-FORM>)
   (LET* ((VAR (CADR SYSTEM::<MACRO-FORM>))) (BLOCK SUB `(- ,VAR 1))))>

A macro form is evaluated , by first evaluating the macro , and expanding it , replacing the macro form . The arguments are evaluated as part of the expanded form .

> (defmacro sub(var )
    `(- ,var 1 ) )
;;;Defines the function property
;;;of the symbol sub , as being 
;;;a macro defintion .

> (sub pi)
;;;sub function property , is a macro
;;;definition , hence what happens first,
;;;is that sub is expanded , and the form
;;;is replaced , by sub expansion .
;;;pi as a symbol , is not evaluated , 
;;;first , it is only evaluated ,
;;;when evaluating the replacement 
;;;form , which is now :
;;;(- pi 1 )
;;;This is a function form , 
;;;the cdr of the list , 
;;;which is its remainder , 
;;;is evaluated . 
;;; pi is evaluated to get 
;;;3.1415926535897932385L0
;;;1 is evaluated to 1 .
;;;The standard does not specify ,
;;;when the symbol - is evaluated , 
;;;to get its function definition .
;;;It can be , before , after , or
;;;in between evaluating the arguments.
;;;Once the elements of the list 
;;;are evaluated , the function 
;;;- is applied to the gotten 
;;;arguments , and the returned 
;;;value is 2.1415926535897932385L0 
2.1415926535897932385L0

What is a special form ?

A special form , is a form , which has as its first element , a special operator . The special operators are :

block                            
catch                         
eval-when                 
flet                             
function                  
go                     
if                           
labels                                      
let          
let*
load-time-value
locally
macrolet
multiple-value-call 
multiple-value-prog1 
progn
progv
quote
return-from 
setq
symbol-macrolet 
tagbody
the
throw
unwind-protect

A special form , might have a special syntax , or a special evaluation rule , for example it might not evaluate all of its arguments .

> (if t 1 pi )
;;;In this example , pi is 
;;;never evaluated , since 
;;;the condition is true , 
;;;hence what is evaluated 
;;;is 1 , which evaluates ,
;;;to itself .
1