The Building Blocks of Lisp Syntax

From the crazy line of C++ code in the previous section, you can get the idea that C++ has a lot of weird syntax—for indicating namespaces, dereferencing pointers, performing casts, referencing member functions, performing Boolean operations, and so on.

If you were to write a C++ compiler, you would need to do a lot of hard work so that the compiler could read this code and obey the many C++ syntax rules, before you could make any sense of the code.

Writing a Lisp compiler or interpreter is much easier. The part of a Lisp compiler or interpreter that reads in the code (which Lispers actually call the reader) is simpler than in C++ or any other major programming language. Take a random piece of Lisp code:

(defun square (n)
     (* n n))

This function declaration, which creates a function that simply squares a number, consists of nothing more than parentheses and symbols. In fact, you can view it as just a bunch of nested lists, delimited by parentheses.

Lisp only has one way of organizing bits of code: It uses parentheses to organize the code into lists.

All basic Lisp code uses this simple list-like syntax:

image with no caption

But what sorts of things can we put into these lists? Well, besides other lists, we can also put symbols, numbers, and strings into our code. Here, we’ll look at these basic building blocks, or datatypes, you’ll use in Lisp. (We’ll discuss many other Common Lisp datatypes in later chapters.)

Symbols

Symbols are a fundamental type of data in Lisp and are used extensively. A symbol in Lisp is a stand-alone word. Common Lisp symbols are typically made up of letters, numbers, and characters like + - / * = < > ? ! _. Some examples of valid Lisp symbols are foo, ice9, my-killer-app27, and even —<<==>>—.

Symbols in Common Lisp are case-insensitive (although most Lispers avoid using uppercase). To illustrate this, we’ll use a function called eq, which lets us see if two symbols are identical:

> (eq 'fooo 'FoOo)
T

As you can see, this function returned T, which tells us that Lisp considers these two symbols to be identical. (For now, ignore the quotation mark in front of the symbols. This will be explained shortly, when we discuss data mode.)

Numbers

Lisp supports both floating-point numbers and integers. When you write a number, the presence of a decimal point determines whether your number is seen as a floating-point number or an integer. The numbers 1 and 1.0 are two different entities in Common Lisp.

For instance, if you use most math functions with both an integer and a floating-point number, the integer will become “poisoned,” and a floating-point number will be returned. Here’s a case in point:

> (+ 1 1.0)
2.0

Note that the decimal point in the returned number, 2.0, indicates that it is a floating-point number.

Lisp can perform some amazing feats with numbers, especially when compared with most other languages. For instance, here we’re using the function expt to calculate the fifty-third power of 53:

> (expt 53 53)
2435684816502271213247760652010472551853345312868564084450513087957
6720609150223301256150373

Isn’t that cool? Most languages would choke on a calculation involving such a large number.

Finally, you should know that something weird could happen if you divide two integers:

> (/ 4 6)
2/3

The division function is dividing the 4 by 6. But instead of returning a fraction (0.66666...) as you might expect, it returns a rational number, represented as two integers with a division symbol between them. So the 2/3 result represents a single rational number, which is the mathematically ideal way to encode a fraction such as this.

Note that we get a different answer if there is a floating-point number in our calculation:

> (/ 4.0 6)
0.6666667

As in the previous example, the number with the decimal point (4.0) has poisoned our numbers to give us a fraction as a result.

If you’re not a math geek, this might not be of much use to you, but at least you now know what’s happening if you see this sort of thing while you’re coding. You can also rest assured that Lisp will do the right thing with this number when you use it later on in another calculation. Lisp is smart.

Strings

The last basic building block in Lisp is the string. Although strings aren’t really that fundamental to Lisp from a theoretical standpoint, any program that communicates with a human will usually need strings, because humans like to communicate with text.

To indicate a string in Lisp, surround characters with double quotes. For example, "Tutti Frutti" is a valid string.

We can display a string using a function called princ:

> (princ "Tutti Frutti")
 Tutti Frutti
 "Tutti Frutti"

Notice that printing our text at the REPL[1] will cause the text to appear twice. First, we see the actual printing caused by the princ command . However, since the REPL will always show the result of evaluating the entered expression, we see our string parroted back to us . This is because the princ function also returns a value, which happens to be the source string.

A string can also contain so-called escaped characters. If you want a string to include double quotes or a backslash, you’ll need to prefix these characters with a backslash. For example, this string has two escaped quotes:

> (princ "He yelled "Stop that thief!" from the busy street.")
He yelled "Stop that thief!" from the busy street.

As you can see, the backslashes in front of the two quotes tell Lisp that these are literal quotation marks in the string, shown in the displayed string just like any other character.



[1] As discussed in Chapter 2, in a read-eval-print loop (or REPL), the functions we enter will be read, then evaluated, and finally printed.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.187.108