Common Lisp Structures

A structure is an advanced datatype available in Common Lisp. Structures and their properties can be a useful way to represent data in your code.

Working with Structures

Structures can be used to represent objects with properties, as you might find in a typical object-oriented programming (OOP) language using the defstruct command, like so:

> (defstruct person
             name
             age
             waist-size
             favorite-color)
PERSON

According to the definition in this structure, a person has four properties (also called slots by Lispers): name, age, waist-size, and favorite-color.

Having defined this structure, we can create instances of a person using the make-person command, a special function that defstruct has automatically created for us:

> (defparameter *bob* (make-person :name "Bob"
                                   :age 35
                                   :waist-size 32
                                   :favorite-color "blue"))
*BOB*

Now when we enter *bob* into the REPL, we see our new person marked as a structure with the #S prefix. We also see that the structure is of type person, and the values of each of its properties (name, age, waist size, and favorite-color):

> *bob*
#S(PERSON :NAME "Bob" :AGE 35 :WAIST-SIZE 32 :FAVORITE-COLOR "blue")

We can determine Bob’s age by calling another automatically created function, person-age:

> (person-age *bob*)
35

We can also use setf with these commands to change Bob’s age. (Happy birthday, Bob!)

> (setf (person-age *bob*) 36)
36

The Lisp reader can also create a person directly from the printed representation of the person, another great example of the print/read symmetry in Lisp:

 > (defparameter *that-guy* #S(person :name
 "Bob" :age 35 :waist-size 32 :favorite-color "blue"))
 > (person-age *that-guy*)
  35

Here, we’re creating a new variable called *that-guy*, and we set its value using only the printed representation of the person . This variable now has a real person structure in it, just as if we had used the make-person function .

As you can see, defstruct is quite a powerful command that can be used to build special functions that make it easy to create instances of a new object and access its properties.

When to Use Structures

These days, many mainstream programmers believe that object orientation is a necessity when developing large and robust applications. Many Lispers, on the other hand, believe that it’s possible to build high-quality software without taking a purely OOP approach.

Beginning with Chapter 14, we’ll examine some of these alternate approaches, including higher-order functional programming and domain-specific language programming. The design of the Lisp language makes it much easier to take advantage of these alternate approaches than is possible with other, more object-oriented languages.

Regardless, even if you’re not writing purely OOP-style software, structures and their properties can still prove to be a useful way to represent data in your code. For instance, instead of creating a person class with defstruct, we could do the same thing with a standard list and our own make-person function. After all, why bother with structures if we can just roll our own person using lists, like so:

> (defun make-person (name age waist-size favorite-color)
        (list name age waist-size favorite-color))
  MAKE-PERSON
  > (defun person-age (person)
        (cadr person))
  PERSON-AGE
  > (defparameter *bob* (make-person "bob" 35 32 "blue"))
  *BOB*
  > *bob*
 ("bob" 35 32 "blue")
  > (person-age *bob*)
  35

Although this approach will work, it has several downsides. First, in order to check a person’s age or other properties, we would need to write a lot of error-prone functions that pull properties out of the list from the correct locations. Also, the printed version of our ad hoc object is very hard to understand. How do we know BOB is a person? Is Bob’s age 35 or 32? Regular lists just don’t lend themselves well to encoding objects with multiple properties.

Another problem with using lists to represent an object in the real world is that the properties of an object (like a person object) may change over time. Lists in Lisp work best when you are dealing with information that never changes once the list is created. When Bob turns 36, however, we need to change his age property.

Having part of a data structure change over time is called a mutation by computer scientists. It’s easy to change the value of a specific property (mutate the property) in a structure created with defstruct, so these structures are very suitable for handling data that needs to be mutable. Therefore, it makes sense to store a person (or any other object that changes over time) in a structure. We will be discussing the issue of mutation in greater detail in Chapter 14.

Note

The defstruct facility is not the only tool that can be used to create objects in Common Lisp. For example, in the epilogue of the book, you’ll see that Common Lisp’s Common Lisp Object System (CLOS) allows you to build very sophisticated object-based systems. If you care to code with a strongly object-oriented mindset, you will probably find all the OOP language functionality you need in Common Lisp. Indeed, CLOS has many advanced object-oriented features that you won’t find in many other places. Because of this, CLOS has often been used as a research tool for studying OOP ideas.

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

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