![]() | ![]() | ![]() | Deleting Instances | ![]() |
GBBopen retains created unit and space instances until they are explicitly deleted. This behavior is important to blackboard applications, where shared information in the form of unit instances remains available until a decision is made to remove them.
In this exercise, we explore some implications of deleting unit and space instances.
If you ended the Common Lisp session used in the last exercise, begin a new session and evaluate the following forms:
cl-user> (load "<install-dir>/initiate.lisp") ... cl-user> :gbbopen-user ... gbbopen-user> (define-unit-class location () (x y)) #<standard-unit-class location> gbbopen-user> (defparameter ui (make-instance 'location :x 50 :y 60)) ui gbbopen-user> (defparameter si (make-space-instance '(known-world))) si gbbopen-user> (add-instance-to-space-instance (make-instance 'location :x 80 :y 90) si) #<location 2> gbbopen-user>
|
Just to review, we created two location
1
is no longer on the known-world
ui
:
gbbopen-user> ui #<location 1> gbbopen-user>The
location
2
is the only
location
known-world
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 2>) gbbopen-user>
Now, let's create five more location
gbbopen-user> (dotimes (i 5) (make-instance 'location)) nil gbbopen-user>Note that we did not specify
x
and y
slot values for these new
unit instances. We will explore the implications of this shortly.
We did not assign the new location
known-world
gbbopen-user> (find-instance-by-name 5 'location) #<location 5> gbbopen-user>
It is often useful to perform some action on all instances of a unit class. GBBopen provides a mapping function, or “iterator,” that repeatedly calls a function with each instance of a unit class as the argument to the function. For example:
gbbopen-user> (map-instances-of-class #'print 'location) #<location 6> #<location 3> #<location 7> #<location 1> #<location 2> #<location 4> #<location 5> nil gbbopen-user>displays each of our
location
location
print
function may differ from the above example in your Common Lisp
implementation.
Currently, there is only one location
known-world
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 2>) gbbopen-user>
Let's use location
known-world
gbbopen-user> (map-instances-of-class #'(lambda (instance) (add-instance-to-space-instance instance si)) 'location) Warning: In add-instance-to-space-instance: #<location 2> is already on space instance #<standard-space-instance (known-world)>. nil gbbopen-user>GBBopen warns us that the
location
2
unit instance is
already on the known-world
location
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 7> #<location 6> #<location 5> #<location 4> #<location 3> #<location 2> #<location 1>) gbbopen-user>
For those who prefer a more iterative programming style, GBBopen provides a
dolist-style macro, location
known-world
(do-instances-of-class (instance 'location) (add-instance-to-space-instance instance si))instead of the
Let's delete the first location
gbbopen-user> (delete-instance ui) #<deleted-unit-instance location 1> gbbopen-user>Note that the displayed representation indicates that the unit instance has been deleted.
We can no longer find the deleted unit instance by its name:
gbbopen-user> (find-instance-by-name 1 'location) nil gbbopen-user>and it is no longer included in a
gbbopen-user> (map-instances-of-class #'print 'location) #<location 6> #<location 3> #<location 7> #<location 2> #<location 4> #<location 5> nil gbbopen-user>and it is no longer on the
known-world
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 7> #<location 6> #<location 5> #<location 4> #<location 3> #<location 2>) gbbopen-user>
However, the deleted location
ui
global variable:
gbbopen-user> ui #<deleted-unit-class location 1> gbbopen-user>and that can lead to problems. Let's try to place the deleted
location
known-world
gbbopen-user> (add-instance-to-space-instance ui si) Error: No methods applicable for generic function #<standard-generic-function add-instance-to-space-instance> with args (#<deleted-unit-instance location 1> #<standard-space-instance (known-world)>) of classes (deleted-unit-instance standard-space-instance) gbbopen-user>> :a gbbopen-user>
Most of GBBopen's operations signal an error if they are given a deleted unit
instance. This is because deleted-unit-instance
standard-unit-instance
describe
function:
gbbopen-user> (describe ui) #<deleted-unit-instance location 1> is an instance of #<standard-class deleted-unit-instance>: The following slots have :instance allocation: instance-name 1 original-class #<standard-unit-class location> gbbopen-user>Note that the slots that we defined for
location
deleted-unit-instance
instance-name
original-class
deleted-unit-instance
Several GBBopen operations on a deleted unit instance do not signal errors. In particular:
gbbopen-user> (instance-name-of ui) 1 gbbopen-user>The value returned by
deleted-unit-instance
Typically, blackboard applications obtain unit instances from the blackboard
repository (or as we will see in
the Using a Control
Shell exercise,
as an event argument) rather than maintaining references to them in variables.
This limits the possibility of retaining a deleted unit instance and
performing GBBopen operations on it. The deletion status of a unit instance
can be determined using the
gbbopen-user> (instance-deleted-p ui) t gbbopen-user>
In the last exercise, we noted that space instances can be organized in hierarchical structures. To illustrate this, let's create a few more space instances:
gbbopen-user> (make-space-instance '(known-world my-town)) #<standard-space-instance (known-world my-town)> gbbopen-user> (make-space-instance '(known-world my-town east-side)) #<standard-space-instance (known-world my-town east-side)> gbbopen-user> (make-space-instance '(known-world my-town west-side)) #<standard-space-instance (known-world my-town west-side)> gbbopen-user>
Recall that the my-town
known-world
east-side
west-side
gbbopen-user> (describe-blackboard-repository) Space Instance Contents -------------- -------- known-world 6 instances (6 location) my-town Empty east-side Empty west-side Empty Unit Class Instances ---------- --------- location 6 standard-space-instance 4 --------- 10 instances gbbopen-user>
Observe from the above description that child space instances that we created
are not placed on their parent. Unlike the directories in a file system in
the analogy that we presented in the last exercise, in GBBopen a
space-instance hierarchy is orthogonal to containment. In fact, space
instances are actually unit instances (of the class
The functions
gbbopen-user> (children-of (find-space-instance-by-path '(known-world my-town))) (#<standard-space-instance (known-world my-town west-side)> #<standard-space-instance (known-world my-town east-side)>) gbbopen-user>
Now, let's add location
2
to the my-town
east-side
gbbopen-user> (let ((location-2 (find-instance-by-name 2 'location))) (add-instance-to-space-instance location-2 '(known-world my-town)) (add-instance-to-space-instance location-2 '(known-world my-town east-side))) #<location 2> gbbopen-user>As we expect,
location
2
is now on three space instances:
gbbopen-user> (describe-instance (find-instance-by-name 2 'location)) Location #<location 2> Instance name: 2 Space instances: ((known-world my-town east-side) (known-world my-town) (known-world)) Dimensional values: None Non-link slots: x: 80 y: 90 Link slots: None gbbopen-user>and the description of the blackboard repository is:
gbbopen-user> (describe-blackboard-repository) Space Instance Contents -------------- -------- known-world 6 instances (6 location) my-town 1 instance (1 location) east-side 1 instance (1 location) west-side Empty Unit Class Instances ---------- --------- location 6 standard-space-instance 4 --------- 10 instances gbbopen-user>
Placing a unit instance on multiple space instances is useful when each space
instance represents a different view of unit instances. In this case,
location
2
is in the known-world
my-town
east-side
gbbopen-user> (find-instances 'location '(known-world my-town) :all) (#<location 2>) gbbopen-user> (find-instances 'location '(known-world my-town east-side) :all) (#<location 2>) gbbopen-user>
Now let's delete some of what we just created. Let's delete the
my-town
gbbopen-user> (delete-space-instance '(known-world my-town)) #<deleted-unit-instance standard-space-instance (known-world my-town)> gbbopen-user>and describe the blackboard repository:
gbbopen-user> (describe-blackboard-repository) Space Instance Contents -------------- -------- known-world 6 instances (6 location) Unit Class Instances ---------- --------- location 6 standard-space-instance 1 --------- 7 instances gbbopen-user>Notice that GBBopen has also deleted all the child space instances of
my-town
east-side
west-side
Also note that deleting space instances did not delete any of the unit instances that were stored on them. If we want to delete a space instance and all the unit instances that are stored on it, we must explicitly delete the unit instances before deleting the space instance. For example, we could do:
gbbopen-user> (map-instances-on-space-instances #'delete-instance 'location '(known-world my-town)) nil gbbopen-user>to delete the unit instances in
my-town
As is the case with
(do-instances-on-space-instances (instance 'location '(known-world my-town)) (delete-instance instance))to explicitly delete the
location
my-town
If we really want to get rid of all our unit and space instances, we can use
the
gbbopen-user> (delete-blackboard-repository) t gbbopen-user> (describe-blackboard-repository) There are no space instances in the blackboard repository. gbbopen-user> (map-instances-of-class #'print location) nil gbbopen-user>
Calling location
location
gbbopen-user> (make-instance 'location) #<location 1> gbbopen-user>Note that deleting the blackboard repository also reset the counter for
location
1
.
The GBBopen Project
![]() | ![]() | ![]() | Deleting Instances | ![]() |