Previous: , Up: Objects   [Contents][Index]

5.1.5 define-actor

Syntax: define-actor (object-name var …

[#:optional vardef …] [#:key vardef …]) [#:restore procedure] [#:portrait thunk] [#:version version] [#:frozen] 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 perfomance improvement on spawning.

Here is an example defining a simple cell object, portrait would be the val:

(define-actor (^cell bcom #:optional val)
    ;; Called with no arguments; return the current value
    [() val]
    ;; Called with one argument, we become a version of ourselves
    ;; with this new value
     (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 origional 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)
   [(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]