(use-modules (ice-9 match)) ;;; Different ways to represent coordinate vectors! ;;; Let's assume we have a 2d vector and a 3d vector ;;; First up: tagged alists (or tagged vectors work too) (define (tagged-alist-type? tagged-alist type-symbol) (define (tag-matches? tag) (eq? tag type-symbol)) (match tagged-alist (((? tag-matches? tag) body ...) #t) ;; anything else, no (_ #f))) (define (tagged-alist-ref tagged-alist key) (assoc-ref (cdr tagged-alist) key)) (define (make-vec2d x y) `(*vec2d* (x . ,x) (y . ,y))) ;; (make-vec2d 1 2) => (*vec2d* (x . 1) (y . 2)) (define (vec2d? obj) (tagged-alist-type? obj '*vec2d*)) ;; (vec2d? (make-vec2d 30 40)) => #t ;; (vec2d? 'donut) => #f (define (vec2d-x vec2d) (tagged-alist-ref vec2d 'x)) (define (vec2d-y vec2d) (tagged-alist-ref vec2d 'y)) ;; (vec2d-x (make-vec2d 30 40)) => 30 ;; (vec2d-y (make-vec2d 30 40)) => 40 (define (make-vec3d x y z) `(*vec3d* (x . ,x) (y . ,y) (z . ,z))) ;; (make-vec3d 1 2 3) => (*vec3d* (x . 1) (y . 2) (z . 3)) (define (vec3d? obj) (tagged-alist-type? obj '*vec3d*)) (define (vec3d-x vec3d) (tagged-alist-ref vec3d 'x)) (define (vec3d-y vec3d) (tagged-alist-ref vec3d 'y)) (define (vec3d-z vec3d) (tagged-alist-ref vec3d 'z)) ;;; Advantages: ;;; - easy to read ;;; - easy to serialize/deserialize... just use read/write to ;;; read/write from sexps! ;;; - easy to understand ;;; ;;; Disadvantages: ;;; - record types with lots of slots will be slow to access... ;;; traversing an alist is worse/average-case O(n)! ;;; - no generic method support out of the box ;;; - adding all those setters takes a lot of work ;;; (and we haven't even covered setters) ;;; ;;; see also property lists