Skip to content
TurtleKitty edited this page May 11, 2019 · 2 revisions

object

Everything is an object in Vaquero.

A programmer can go far with just the core data types, but some may wish to create their own. For that, there is the object procedure.

Simple objects are similar to tuples, but are immutable unless the programmer provides that ability via messages.

(def obj (object 'x 1 'y 2))

obj.x    ; 1
obj.y    ; 2
obj.z    ; (runtime-error (message-not-understood (send #(object x y) z) "Message not understood."))

Objects can contain procedures.

(proc foo (x) (+ x x)) 
(proc bar (x y) (* x y)) 
(def obj (object 'x 1 'y 2 'foo-thing foo 'barista bar))

obj.x             ; 1
(obj.foo-thing 4) ; 8
(obj.barista 2 3) ; 6

Thunks (procedures of one argument) can be designated as auto-executing with the auto: option. This is useful for informational properties and side effects.

(def foo (cell 5))
(proc bar () (+ 10 foo.get))
(proc baz () foo.inc! null)

(def obj
   (object
      'plus-10 bar
      'incr baz
      auto: '(plus-10 incr)))

obj.plus-10    ; 15
obj.incr       ; null
foo            ; #(cell 6)
obj.plus-10    ; 16

Objects can be commanded to forward certain messages to other objects with the forward: option. Since the objects and messages to resend are explicit, and delegators have access only to the delegatees' interfaces, this gives Vaquero the power of multiple "inheritance" without tears.

(proc robot ()
   (object 'fire-laser "Pew! Pew!" 
           'blazing-sword "WRECKED!"
           'use-radio "Contacting base!"))

(proc car ()
   (object 'accelerate "Zoom"
           'brake      "Screech!"
           'turn       "Whee!"
           'use-radio  "Listening to tunes..."))

(def robot-car
   (let (my-car (car) my-robot (robot))
      (object forward: %(($my-car accelerate brake turn)
                         ($my-robot fire-laser blazing-sword use-radio)))))

robot-car.fire-laser    ; "Pew! Pew!"
robot-car.accelerate    ; "Zoom"
robot-car.use-radio     ; "Contacting base!"

An object can be given a default procedure to execute when it receives a message it doesn't understand using the default: option. This can imitate classical single inheritance or prototype object systems.

(def monster
   (object
      'move "running..."
      'look-for-trouble "searching..."
      ; 40 other messages ...
))

(def goblin 
   (object
      'name 'Goblin
      'hp 5
      default: (proc (msg) (send monster msg))))

(def brat
   (object
      'name 'Princess
      'hp 7
      default: (proc (msg) "No!!!")))

goblin.hp   ; 5
goblin.move ; "running..."
brat.hp     ; 7
brat.move   ; "No!!!"

Objects have a number of default messages, if not overridden.

(def foo (object 'x 2 'y 3))

foo.type             ; '(object)     ; this method can be overridden, but must be a list of symbols
foo.view             ; #(object x y) ; this method can be overridden to pretty-print user-defined objects, but must be a thunk
foo.messages         ; (x y)         ; returns a list of non-default messages the object responds to
foo.to-bool          ; true          ; true unless the object responds to no messages

(foo.answers? 'x)    ; true
(foo.answers? 'y)    ; true
(foo.answers? 'z)    ; false

Objects that respond to the apply message can be used as the head of a code list.

(def no-way
   (object 'x 1 'y 2))

(def yes-way
   (object
      'apply (proc (args)
                (send no-way args.head))))

(yes-way 'x)   ; 1
(no-way 'x)    ; (runtime-error (message-not-understood ...))
Clone this wiki locally