Lab 1 material: Introduction to Lisp
- More material for learning Lisp:
- Lisp Primer - A tutorial
- Practical Common Lisp - A freely available book on Lisp
To work through these exercises, refer to the above material for more information.
- Emacs and REPL:
Install LispBox on your computer and start it up. The lower window is the Lisp REPL (read-eval-print loop) where you can enter Lisp expressions and have them evaluated. - Hello World:
Type an expression prints “Hello World!” on the screen.
;; A typical print expression (print "Here is some text")
Note that in the REPL, you can recall your last command with Alt+P (for previous) and that tab completion works on most lisp symbols.
- Lisp basics:
Go through the sections Evaluating simple expressions, Evaluating Lists as Functions and Control Structures and Variables in this tutorial. Some expressions will generate an error, in that case the top window will show a message and a list of options. The safe option is always[ABORT REQUEST]
. - Defining functions:
Go through the section Writing Functions in the tutorial. You can skip typing the examples in boxes 3, 5, 6, 7, 8 and 9 - but read the examples and try to understand them. Write a function that asks the user for their name and prints “Hello, <name>!” on the screen.
;; An example of getting input from a user and printing it (defun repeat-what-you-say () (let ((what-you-said)) (print "Please say something and type enter:") (setf what-you-said (read-line t)) (print (concatenate 'string "You said: " what-you-said))))
Note that in the REPL, you will see the printed output as well as the return value of the function. The return value is (as you should know by now) the result of the last expression of the function body. Since the
PRINT
function returns its argument, the function above also returns it, which is why it is printed twice in the REPL. - Lists as data:
So far we've only seen lists used to call functions. However they can also be used to store data. Go through the section Lists and Symbols as Data in the tutorial. Feel free to skip the exercises that you feel you understand well, but make sure you understand how quoting (e.g.'(1 2 3)
) works.
The tutorial does not talk about keyword lists, which we will use. Keyword lists are created with the following syntax:
'(:keyword "value" :numberfield 123)
You can access the fields of a keyword list with the
GETF
function:
CL-USER> (getf '(:a 1 :b 2 :c 3) :b) 2
You can read more about keyword lists in chapter 2 of Practical Common Lisp. For more information about quoting, see this page of the Lisp Primer, and remember that quoting simply prevents a list from being evaluated and instead treats it as data.
- Symbols as data:
Lisp allows us to use symbols (e.g. variable names) as data. They are created with the same quoting syntax as lists:
'symbol
Symbols are simply short strings, except they are case-insensitive (the REPL always prints them in uppercase) and cannot be changed or manipulated. Like with lists, quoting a symbol simply stops it from being evaluated (i.e. treated as a variable) and instead treats the symbol itself as data.
Write a function that takes a keyword list, looks up the number called:test
and returns the symbolYES
if it is less than 10, andNO
otherwise.
;; Example REPL session showing the concepts you need to use CL-USER> (setf x '(:x 10 :y 33 :test 9)) (:X 10 :Y 33 :TEST 9) CL-USER> (getf x :test) 9 CL-USER> (> (getf x :test) 10) NIL CL-USER> (> 10 (getf x :test)) T CL-USER> (if (> 10 (getf x :test)) 'SMALLER 'BIGGER) SMALLER
- Loading files:
Typing things into the REPL every time is of course not the way we usually use Lisp. Instead we load a file with definitions of functions and variables, and then use the REPL to invoke them.- Start by downloading this file (right click “raw” and choose save as) and name the file
agents.lisp
. Save it in a folder for this lab session. - In the REPL, type
,
(comma); this invokes the command mode of the REPL, type the commandcd
and press enter. Emacs will prompt you for a file path, enter the file path to the folder where you saved the file. - Now type (in the REPL) the expression
(load “agents.lisp”)
. - Now the definitions of the file have been loaded in the REPL. To see what definitions are available, open the file in the upper half of Emacs. To do this, you can click in the upper half and then press (in sequence) Ctrl+X and Ctrl+F and type the path to the file. Alternatively just select “File → Open” If Emacs asks you to allow it to apply local variables from the file, then answer with Yes.
- Have a look at the file and see if you can understand the code. Don't worry too much if you don't. At the bottom of the file there are three example expressions. Try typing (in order) them in the REPL and see what happens
- Writing an agent program:
The functionEXAMPLE-AGENT-PROGRAM
gives an example of how to create a program to control an agent in the vacuum-cleaner world. The program is a function that takes a keyword list representing the percept value, and it should return one of the symbolsLEFT, RIGHT, UP, DOWN, SUCK
orIDLE
. A percept keyword list looks like this:'(:x 3 :y 8 :dirty T)
Here,
:x
and:y
give the location of the agent and:dirty
tells us if the current square has dirt or not. The given example program is an implementation of the code in figure 2.8 on page 46 in the textbook.
Write a new agent program, that walks about the environment randomly, sucking up dirt where it finds it. You can either write your function in the REPL or add it to the file. If you add it to the file, you have to save the file (keyboard shortcut is Ctrl+X, Ctrl+S) and then reload the file in the REPL (recommended option). Instead of typing the load command again, you can reload the file by hitting Ctrl+C, Ctrl+L while the file window is active.
Use theSIMULATE
andSIMULATE-QUIET
functions from last step to test your new agent program. Does it give better performance evaluation than the old one?
- Writing a performance evaluation function:
The functionEXAMPLE-MEASURE
shows how performance evaluation functions look. This function takes an environment and an agent as parameters, and returns a number indicating the performance of the agent so far.
Both the agent and the environment are so called structures. Their fields are defined in the fileagents.lisp
with calls to theDEFSTRUCT
macro. This macro defines a function for constructing an instance of the structure, e.g. for theENV
structure, this function is calledMAKE-ENV
.
The macro also defines functions for accessing the fields of a structure, e.g. the width field of anENV
structure in variable env can be accessed with(env-width env)
.
Write a performance evaluation function that awards 10 points for every clean square but deducts one point for every move the agent makes. The number of moves is stored in the moves-so-far field. Now run the simulations again. How does this change the evaluation score? Can you think of ways to change the agent program so that it scores better with this new evaluation function?