Previous: Object reference predicates, Up: Objects [Contents][Index]
[#:optional vardef …] [#:key vardef …]) [#:restore procedure] [#:portrait thunk] [#:version version] [#:frozen] [#:upgrade migrator] [#:self name] body …
Defines a goblins object with object-name. The argument syntax
is that of define*
or lambda*
in that it takes
#:key
and #:optional
, however it does not support
#:rest
, nor #:allow-other-keys
. The object by default is
redefinable which aids in live hacking.
When #:restore
is given with a procedure, that procedure is
called to restore the actor upon rehydration from Goblins persistence
system. It’s called with the initial argument being the version of the
portrait data followed by the portrait data given by the portrait
data. When no restore function is provided the default behavior of
dropping the version and applying the other arguments to the
constructor is used.
When #:portrait
is given with a thunk, that is called to
produce the object’s self portrait in order to persist it. This thunk
is run within the body of the object so all arguments to the object
are available. When no portrait is given, the self portrait will match
the arguments provided to the constructor.
When #:version
is provided it will tag the portrait with that
version.
When #:frozen
it does not define the object as a redefinable
object (useful for live hacking) and prevents #:restore
being
used. Frozen objects have a slight performance improvement on spawning.
When #:upgrade
is provided, it uses this to migrate the portrait
data to the newest version. This is designed to work with the migrations
macro, however can be used on its own. This cannot be used in combination with
#:restore
.
When #:self
is provided with a identifier, that identifier is
bound to the refr of the actor itself.
Here is an example defining a simple cell object, portrait would be the val:
(define-actor (^cell bcom #:optional val) (case-lambda ;; Called with no arguments; return the current value [() val] ;; Called with one argument, we become a version of ourselves ;; with this new value [(new-val) (bcom (^cell bcom new-val))]))
Here’s an example of a thermostat which takes in the temperature as a
cell and a reference to a heater. It defines a portrait which removes
the value from the cell. It specifies a version of 1
, as it
needs to do version upgrade. Finally in the restore function it
matches on the version and converts from Celsius to Kelvin if it’s the
original version and spawns the ^thermostat with the cellified set
temperature:
(define-actor (^thermostat bcom set-temp-cell heater-refr) #:portrait (lambda () (list ($ set-temp-cell) heater-refr)) #:version 1 #:restore (lambda (version set-temp heater-refr) ;; Version 0 used C, convert to kelvin (define maybe-converted-temp (match version [0 (+ set-temp 273.15)] [1 set-temp])) (spawn ^thermostat (spawn ^cell maybe-converted-temp) heater-refr)) (methods [(set-temp new-temp) ($ set-temp-cell new-temp)] ;; Invoked with current room temp [(tick current-temp) (if (< current-temp ($ set-temp-cell)) (<-np heater-refr 'turn-on) (<-np heater-refr 'turn-off))]))
NOTE: this actor could have kept the temperature in the cell, there’s usually no reason to unpack values like this, it’s just for example purposes.
Previous: Object reference predicates, Up: Objects [Contents][Index]