Table of Contents
LISP Syntax
Important feature of LabLisp, as of any other LISP, is that the LISP code is a data structure (list of lists, or tree, of atoms) and lists are fundamental LISP data structure. LabLisp expression consists of symbols, literals and parentheses that organize the list into sub-lists. Following is example of an expression:
(foo (bar 1.3 a) (boo "text" 14))
What we see is a list, containing symbol foo
and two sub-lists. First sub-list contains symbol bar
, literal floating-point number 1.3
, and symbol a
(possibly variable name). Second sub-list contains symbol boo
, string literal “text”
and integer literal 14
. Symbols foo
, bar
and boo
appear first in their lists, and should name functions. Actually, all LISP operators are applied in the functional syntax, appearing at the first position of the expression. So simple addition will be written as
(+ 3 5)
This expression can be directly entered to LISP and evaluates to 8
. LISP programs are written in a functional style. We can understand the first example expression as function foo
that takes two parameters, and we call the expression (foo x y)
a function-application form. Before the function is invoked (applied), the two sub-lists need to be evaluated to something the foo
function accepts as arguments. The form (bar 1.3 a)
is another function-application, where the arguments are evaluated first: literal 1.3
evaluates to itself and symbol a
should be defined variable that evaluates to its value (let’s say another number). Analogically for the (boo “text” 14)
form, which could be application of boo
function to literal arguments “text”
and 14
. All together, this means the arguments of the form bar
are evaluated first (left to right), then the function bar
is applied, then the arguments of boo
are evaluated and that function is applied, finally, the complete expression with function foo
is evaluated last.
The examples above consist of lists of atoms. In LabLisp, atoms can have one of following types: symbol, integer, float, string, function object or package. Symbol can be, for now, understood as a variable or a function name. The last two types (function and package) are not trivial, and we will discuss them later. Any white space (space, line break, tab) is considered as separator between the list items and has no other special role in the code. Line breaks or indents serve only esthetic purposes.
Escaping
In LISP syntax, as in the examples above, we encounter some special characters. Obviously, the parentheses ( )
hold a unique role as list delimiters. The quotation marks (double quotes) delimit string. Everything between a pair of quotation marks is considered a string. With that comes the need for single character escape symbol \
(backlash). For example, if we want to include quotations mark in our string we need to escape the “
character, otherwise our string would be broken apart:
"she said \"ouch\" suddenly"
Backlash symbol escapes single character. If we want to escape several characters in a block, we contain them in bars | |
.
"here come three |"""| quotation marks"
Commenting
Comments in LISP code are marked with one or more semicolons, which will cause the LISP interpreter (called reader) to ignore everything behind until the end of line
(+ 3 6) ; example of addition
It is conventional to highlight comments with multiple semicolons depending on importance. Single semicolon appears on the line with command. Two-semicolon comments are between commands. Three semicolons typically appear in comment describing a block of code (function definition etc.) and four-semicolon comment is reserved for header of whole source file.
When the programmer needs to comment-out whole block of code, there is also block-comment pair of symbols
#|this is out|#
Block-comments are counted and leveled, so it is possible to surround the part of block-commented code with new pair of block-comment symbols.
Special reader characters
In more developed LISP languages, the #
symbol serves as marker for several reader operations and macros, but in LabLisp there are only few and will be discussed in the following chapter.
LISP environments feature another syntactic curiosity: auto-upper-casing of symbol name strings (not string literals). It is conventional to write lisp source code in lower-case, but the reader converts all lower-case to upper case. So, symbols written in the code as aaa
, AAA
, aAa
etc. will all be converted to AAA
and refer to the same symbol. It is possible to force the symbol name to have lower-case with escaping: a\aa
, will be read as AaA
and will not be equivalent to AAA
. Therefore, while normally auto-upper-casing all symbol names, LISP still is case sensitive.
There are some other important special characters: ‘
(quote) `
(backquote) ,
(comma) ,@
(comma-at) and ,.
(comma-dot). These characters appear before an expression and serve as switch between code-mode and data mode. This topic will be discussed in more details later. Let’s just give one example for quote:
(f a b) ;is code, will be evaluated as function form f ‘(f a b) ;switched to list data structure with three symbols
Similarly looking .
(dot) #
' (sharp-quote) have different purpose, and we will discuss them in the next chapters.
Style
Apart from that, LISP is very benevolent with symbol names. Many different characters are allowed. For example, <_!*!_>
is perfectly fine as symbol name. But good habit is to write descriptive symbol (function, macro) names in lower-case with hyphens (same as minus sign) separating words:
my-first-function