my-object
1 Forms and Functions
object
object-extend
object?
object-fields
send
send*
send+
dynamic-send
this
2 Examples
2.1 Posn example based on racket guide for structs
2.2 Fish example based on racket guide for objects
6.3.90.900

my-object

source code: https://github.com/AlexKnauth/my-object

 (require my-object) package: alexknauth-my-object
my version of objects, inspired by Things from heresy
Also, the objects here do not mean racket/class objects.

1 Forms and Functions

syntax

(object [field-id expr] ...)

creates and returns an object with the field-ids mapped to the exprs. Each expr can refer to this and all the other field-ids.

See also object-extend.

If an expr is a function, then that function can be used as a method for the object, but methods are not treated specially; they are just normal fields that happen to have functions stored in them.

Each field-id is public and immutable. Private mutable fields are also possible (see Fish example based on racket guide for objects).

syntax

(object-extend obj option ... [field-id expr] ...)

 
option = #:inherit (inherit-id ...)
  | #:super ([super-id1 super-id2] ...)
similar to both struct-copy and object inheritance.

If the #:inherit option is provided, the inherit-ids are available as bindings within the exprs.

If the #:super option is provided, the super-id1s are available within the exprs, and a super-id1 refers to the super-id2 field of the super object.

procedure

(object? v)  boolean?

  v : any/c
returns #t if v is an object, #f otherwise.

procedure

(object-fields obj)  (hash/c symbol? any/c #:immutable #t)

  obj : object?
returns a hash-table containing the fields of obj.

syntax

(send obj-expr method-id arg ...)

(send obj-expr (identity method-expr) arg ...)
(send obj-expr . field-id)
send
The first form is equivalent to ((obj-expr #'method-id)  arg ...), or to (dynamic-send obj-expr #'method-id  arg ...).

The second form allows the method to be determined at run time, and is equivalent to (dynamic-send obj-expr method-expr arg ...).

The third form is equivalent to (obj-expr #'field-id), and is mainly provided so that send+ can use field-id as a msg.

When send is used as an identifier by itself, it expands to dynamic-send.

syntax

(send* obj-expr msg ...)

 
msg = (method-id arg ...)
  | field-id
Equivalent to (let ([obj obj-expr]) (send obj . msg)  ...).

syntax

(send+ obj-expr msg ...)

 
msg = (method-id arg ...)
  | field-id
Equivalent to (let* ([obj obj-expr] [obj (send* obj msg)] ...) obj).

procedure

(dynamic-send obj method arg ...)  any

  obj : object?
  method : (or/c symbol? identifier?)
  arg : any/c
equivalent to ((obj method) arg ...).

syntax

this

within an object or object-extend form, refers to the current object.

2 Examples

2.1 Posn example based on racket guide for structs

This is based on the examples from Programmer-Defined Datatypes.

Examples:
> (require my-object)
> (define p (object [x 1] [y 2]))
> p

(object [x 1] [y 2])

> (object? p)

#t

> (p 'x) ; by the way, you can use #'x here instead of 'x

1

> (p 'y)

2

> (define p2 (p 'x #:-> 3))
> p2

(object [x 3] [y 2])

> (define (posn x0 y0)
    (object [x x0] [y y0]
            [add (λ (p) (posn (+ x (p 'x)) (+ y (p 'y))))]
            [->list (λ () (list x y))]))
> (define p3 (send (posn 1 2) add (posn 3 4)))
> (send p3 ->list)

'(4 6)

> (define p3 (posn 1 2))
> (define p4 (object-extend p3 [x 3])) ; or (p3 'x #:-> 3)
> (send p4 ->list)

'(3 2)

> (define (3d-posn x0 y0 z0)
    (object-extend (posn x0 y0)
                   #:inherit (x y)
                   [z z0]
                   [add (λ (p) (3d-posn (+ x (p 'x))  (+ y (p 'y)) (+ z (p 'z))))]
                   [->list (λ () (list x y z))]))
> (3d-posn 1 2 3)

(object [x 1] [y 2] [add #<procedure>] [->list #<procedure>] [z 3])

2.2 Fish example based on racket guide for objects

This is based on the examples from Classes and Objects.

Examples:
> (require my-object)
> (define (make-fish sz)
    (define size sz) ; private mutable field
    (object [get-size (λ () size)]
            [grow (λ (amt)
                    (set! size (+ amt size)))]
            [eat (λ (other-fish)
                   (grow (send other-fish get-size)))]))
> (define charlie (make-fish 10))
> (send charlie get-size)

10

> (send charlie grow 6)
> (send charlie get-size)

16

> (define (make-hungry-fish sz)
    (object-extend (make-fish sz)
                   #:inherit (eat)
                   [eat-more (λ (fish1 fish2)
                               (eat fish1)
                               (eat fish2))]))
> (send (make-hungry-fish 32) get-size)

32

> (define (make-picky-fish sz)
    (object-extend (make-fish sz)
                   #:super ([super-grow grow])
                   [grow (λ (amt)
                           (super-grow (* 3/4 amt)))]))
> (define daisy (make-picky-fish 20))
> (send daisy eat charlie)
> (send daisy get-size)

32