![]() | ![]() | ![]() | 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 location1 is no longer on the known-worldui:
gbbopen-user> ui #<location 1> gbbopen-user>The
location2 is the only
locationknown-worldgbbopen-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 locationknown-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
locationlocationprint function may differ from the above example in your Common Lisp
implementation.
Currently, there is only one locationknown-world
gbbopen-user> (find-instances 'location '(known-world) :all) (#<location 2>) gbbopen-user>
Let's use locationknown-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 location2 unit instance is
already on the known-worldlocationgbbopen-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, locationknown-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-worldgbbopen-user> (find-instances 'location '(known-world) :all) (#<location 7> #<location 6> #<location 5> #<location 4> #<location 3> #<location 2>) gbbopen-user>
However, the deleted locationui 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
locationknown-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-instancestandard-unit-instancedescribe 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 locationdeleted-unit-instanceinstance-nameoriginal-classdeleted-unit-instanceSeveral 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-instanceTypically, 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-townknown-worldeast-sidewest-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 location2 to the my-towneast-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, location2 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,
location2 is in the known-worldmy-towneast-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-towneast-sidewest-sideAlso 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-townAs is the case with
(do-instances-on-space-instances (instance 'location '(known-world my-town))
(delete-instance instance))
to explicitly delete the locationmy-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 locationlocation
gbbopen-user> (make-instance 'location) #<location 1> gbbopen-user>Note that deleting the blackboard repository also reset the counter for
location1.
The GBBopen Project
![]() | ![]() | ![]() | Deleting Instances | ![]() |