These exercises are about finishing the simple robot plan execution simulator. These exercises require just basic Lisp programming knowledge, except for the exercise on packages.

The Rules of the Queue still apply, both testing and critiquing.


Exercise name: pick-up

Test suite name: pick-up-test

Define test cases to test step-update with pick-up actions, then extend the code to implement pick-up. A robot can pick up an object only if the robot is in the same location as the object, and the robot is not already holding something. If these conditions are not met, the action should fail, i.e., the resulting state should be NIL, otherwise, the location of the object should be the robot.

For now, use a simple CASE or ECASE in step-update to select which code to execute for pick-up versus go. You will change this in a later exercise.

Refactor! Do not repeat code. If there are common Lisp tasks for the two robot actions, define well-named modular subfunctions to do those tasks.

Submit both your code and your test cases for pick-up. I will be evaluating the quality of both your code and your test cases. A good test suite covers all likely places where things might fail, but does not include redundant tests or tests that could never fail.

When defining test cases, you will almost certainly discover situations where it's not clear what the right answer should be. Post those questions to the newsgroup for discussion. Use the answer the newsgroup has converged on, if it's already been discussed. If agreement was not reached, pick the answer you prefer.


Exercise name: drop

Test suite name: drop-test

Define test cases to test step-update with drop actions, then implement drop. A robot can drop something only if the robot is holding something. If this condition is not met, the action should fail, otherwise the location of the object should be the room the robot is in. Note that drop takes no parameters.

Submit both your code and your test cases for drop.


Exercise name: plan-update

Test suite name: plan-update

Define test cases to test plan-update. The syntax is (plan-update state plan robot).

One or more tests should use the example plan in *plan* in the original simulator code file, but you should have other plans. Test for plans that work and ones that don't. The empty plan should always work.

Submit both your code and your test cases for plan-update. Only submit step-update if you had to change it.


Exercise name: Extensible simulator

Note: no new tests are needed for this exercise. You need to know how to create function closures to do this exercise.

Using a conditional or case statement to implement actions is fine when first starting, but it's not the best long-term approach. Every time we want to add a new action or modify an existing one, we have to edit the simulator source code.

A better approach is to make the simulator extensible, so that new actions can be added without touching the source code of the simulator. This means changing step-update so that it uses a table of some kind that maps action names to functions. All step-update should do is look up the name of the action for a step in the table. If it's there, it should run the function, which should return a new state, possibly NIL. If no entry is found, step-update should signal an error with error.

Decide what kind of data structure you want to use for the table. Change your code file so that it creates the table, and stores functions for go, pick-up, and drop. Change step-update appropriately.

Make sure all your tests still run.

Submit the new code only.


Exercise name: Simulator Packaging

Package names: robot-sim, robot-sim-tests

To do this exercise, you need to know about packages, as described in Graham (Chapter 8), the glossary (pp. 343-346), and my notes.

The robot simulator should be in its own package, to avoid conflicts with other libraries. The simulator test code should be in a different package, to guarantee that the test code is not accidentally depending on unexported internal simulator functions.

Define two files, robot-sim.lisp and robot-sim-tests.lisp. The first should contain the simulator code in the package robot-sim. The second should contain the test code in the package robot-sim-tests.

The three major issues in package design are to:

Export as little as possible. The more you export, the more name conflicts you might cause, and the less freedom you'll have to make future changes to your library. This same principle applies in module systems in other languages, such as Java and C++.

Depend on as little as possible. Your packages should only use those packages that are necessary. This reduces potential name conflicts, and insulates your library from changes in other libraries. Don't reinvent the wheel, but don't use a package if you don't need the code from that package.

In particular, do not use "user" packages, such as cs325-user, cl-user and Allegro's cg-user (in Allegro). User packages collect together other packages to provide convenient access to functions in an interactive Listener window. But because they include so many packages, they can cause name conflicts when defining library modules. Instead, library packages should use the underlying packages, such as common-lisp, that define the code needed by the library. You'll need to figure out what packages you need. You can use the function package-use-list to find out what packages cs325-user uses.

Ignore packages when matching symbols. The robot simulator determines what code to run based on symbols, such as go and pick-up. Symbols are symbols, and pick-up in the simulator package will not be the same as pick-up in a user package like cs325-user. The wrong answer is to export these symbols, because that can cause name conflicts. The better answer is to change your code so that it doesn't matter what package the input symbol is in. There are a number of ways to do this. I'll leave it to you to explore them.

To test, load both files into your CS325 Lisp. Do not call use-package. Instead, evaluate

(run-all-tests robot-sim-tests)

If you've done things correctly, all your robot tests should run.

Submit just your defpackage forms.

Comments? Send me mail.