record-vector

  1. record-vector
    1. Description
    2. Example. Basic usage
    3. Example. Compound record-vector
    4. Requirements
    5. API
      1. record-vector
      2. record-vector?
      3. record-vector-clone
      4. record-vector-like?
      5. record-vector-attr?
      6. record-vector-ref
      7. record-vector-set!
      8. record-vector-update!
    6. Example
    7. Source code
    8. Authors
    9. Licence
    10. Version History

Description

Record-vector is a module for CHICKEN5|6 Scheme, and R7RS library for #:Guile :Gauche Gambit: Schemes, designed to work with key-value data structures, aka records. Record-vector does not declare a new record type, it is not a hash-table, nor a tree. Record-vector itself is just a pair of alist of attribute indexes in the second part of pair - value's vector.

'(((#:KW1 . INDEX1) ... (#:KWN . INDEXN)) . #(VALUE1 ... VALUEN))

KW - name of attribute, also Scheme keyword #:NAME or NAME: depend of Scheme variant. VALUE - any Scheme value.

Cons

Pros

Example. Basic usage

 
> (record-vector #:x 0.0 #:speed 0.1) => (((#:x . 0) (#:speed . 1)) . #(0.0 0.1))

;; make-rv  an alias of [procedure]record-vector
> (define boat (make-rv #:posn (make-rv #:x 1.0 #:y 2.0) #:id 10001 #:passengers 4))

;; record-vector-ref/rv-ref is accessor procedure/macro (last one supports inner rv chain access)
> (rv-ref boat #:posn #:y) => 2.0
;; same reference by attribute indexes
> (rv-ref boat 0 1) => 2.0 ;; Zero - #:posn, 1 - #:y in position.

;; the record-vector extends in this way
> (rv-attr? boat #:model) => #f
> (rv-update! boat #:model "Azimut 50")
> (rv-attr? boat #:model) => (#:model . 3)

;; get attribute by index
> (rv-ref boat 3) => "Azimut 50"

Example. Compound record-vector

 
(define objects (record-vector
                 #:table (make-rv
                          #:posn (make-rv #:x 100 #:y 20)
                          #:height 80
                          #:items (make-rv
                                   #:cup (make-rv  #:posn (make-rv #:x 10 #:y 0))
                                   #:pot (make-rv  #:posn (make-rv #:x 20 #:y 10))))))

> (cdr (rv-ref objects #:table #:items #:pot #:posn)) => #(20 10)

Requirements

Non standard predicate keyword? and utility (R7RS) procedure vector-append are used (in CHICKEN5 it's used from vector-lib package). Also in CHICKEN SRFI-17 setter adapter used for record-vector-ref.

API

All record-vector-* forms has rv-* shortcomings, some in form of macros with extended abilities.

record-vector

[procedure] (record-vector [#:NAME-1 VALUE-1 ... #:NAME-N VALUE-N])
[procedure] (make-rv [#:NAME-1 VALUE-1 ... #:NAME-N VALUE-N])

Record-vector construction procedures. make-rv is an alias of record-vector

record-vector may be empty.

 
> (record-vector #:code "defs.scm" #:lang 'Scheme #:loc 117)) => (((#:code . 0) (#:lang . 1) (#:loc . 2)) . #("defs.scm" Scheme 117))
> (define empty-obj (make-rv))
> empty-obj => (() . #())
> (record-vector? empty-obj) => #t

record-vector?

[procedure] (record-vector? VAR)

Unstrict predicate which test structure of argument VAR is like Scheme pair of list and vector.

record-vector-clone

[procedure] (record-vector-clone R-V-SRC [#:NAME-k #:NEW-VALUE-k ...])
[procedure] (rv-clone R-V-SRC [#:NAME-k #:NEW-VALUE-k ...])

Create the new record-vector by consing attributes alist of R-V-SRC and copy of R-V-SRC value vector. If every n-th value also record-vector? than recursive clone it inplace of new n-th value. Also apply new values to existing attributes with name #:NAME-k or extends new record-vector with them.

 
> (define r (record-vector #:x 1.0 #:y 3.0))
> (define r2 (record-vector-clone r #:y 2.0 #:z 3.0))
> r2 => (((#:x . 0) (#:y . 1) (#:z . 2)) . #(1.0 2.0 3.0))

record-vector-like?

[procedure] (record-vector-like? r1 r2)
[procedure] (rv-like? r1 r2)

Procedure record-vector-like? returns true if all of attribute names in r1.alist also in r2.alist or vice versa.

 

> (define r1 (make-rv x: 1 y: 2 z: 3))
> (define r2 (make-rv x: 4 y: 2))
> (rv-like? r1 r2) => #t  ;; bc all attributes from r2 are present in r1.
> (rv-like? r2 r1) => #t  ;; still True, record-vector-like? symmetrical

record-vector-attr?

[procedure] (record-vector-attr? R-V #:NAME)
[procedure] (rv-attr? R-V #:NAME)

This proc's for check presence of the attribute #:NAME in alist dictionary of R-V. Returns (assq #:NAME r-v.alist).

record-vector-ref

[procedure] (record-vector-ref R-V #:NAME-k #!optional DEFAULT)
[syntax] (rv-ref R-V #:NAME-k [#:SUB-NAME-j ...])

This is accesor of the attribute of the record-vector R-V. In CHICKEN record-vector-ref (not the rv-ref) SRFI-17 compatible. Optional DEFAULT value is used if there is no attribute named #:NAME-k.

The rv-ref macro works like record-vector-ref, but if the value with #:NAME-k is a record-vector?, it looks for the value of the #:SUB-NAME-j attribute in it, recursively. The macro does not have a default return value, unlike record-vector-ref.

 
> (record-vector-ref (record-vector #:x 124 #:y 0) #:x) => 124
> (record-vector-ref (make-rv #:x 1) #:t 1900) => 1900
> ;; but no default value in rv-ref macro
> (rv-ref (make-rv #:x 1) #:t 1990) => Error: (cdr) bad argument type: #f
> (rv-ref (make-rv #:person (make-rv #:name "Joe" #:age 50)) #:person #:name ) => "Joe"
;; if attribute is not present it returns False (use rv-attr? predicate before)
> (rv-ref (make-rv #:posn (make-rv #:x 0.0 #:y 0.0)) #:posn #:z) => #f ....

record-vector-set!

[procedure] (record-vector-set! R-V #:NAME-k NEW-VALUE)
[syntax] (rv-set! R-V #:NAME-k [#:SUB-R-V-NAME-j ...] NEW-VALUE)

record-vector-set! is a mutator of the record-vector attribute NAME rv-set! - recursive macro which able set value not only R-V but attributes compatible with record-vector structure

 
> (define r (record-vector #:pos 0.0 #:line (make-rv #:color 'red #:a 1.0 #:b 2)))
> r => (((#:pos . 0) (#:line . 1)) . #(0.0 (((#:color . 0) (#:a . 1) (#:b . 2)) . #(red 1.0 2))))

> (set! (record-vector-ref r #:pos) 1000.0) ;; SRFI-17
> r => (((#:pos . 0) (#:line . 1)) . #(1000.0 (((#:color . 0) (#:a . 1) (#:b . 2)) . #(red 1.0 2))))

> (rv-set! r #:line #:color 'blue)
> r => (((#:pos . 0) (#:line . 1)) . #(1000.0 (((#:color . 0) (#:a . 1) (#:b . 2)) . #(blue 1.0 2))))

record-vector-update!

[procedure] (record-vector-update! R-V #:NAME VALUE)
[syntax] (rv-update! R-V #:NAME [#:SUB-NAME ...] VALUE)

These procedure and macro (which recursive variant) for update existing attribute values ​​and add new attribute in record-vector R-V.

 
> (define p (make-rv posn: (make-rv x: 1 y: 2)))
> (rv-update! p posn: x: 10)
> p => (((#:posn . 0)) . #((((#:x . 0) (#:y . 1)) . #(10 2))))
> (rv-update! p posn: z: 30)
> p => (((#:posn . 0)) . #((((#:x . 0) (#:y . 1) (#:z . 2)) . #(10 2 30))))
;; rv-update! is stable
> (rv-update! p posn: z: 30)
> p => (((#:posn . 0)) . #((((#:x . 0) (#:y . 1) (#:z . 2)) . #(10 2 30))))

Example

 
(import (rename (record-vector) (record-vector rv)))

(let ((r (rv x: 1 y: 2))
      (nr (rv x: 2 y: 3)))
  (define (distance p t)
    (let ((dx (- (rv-ref t #:x) (rv-ref p #:x)))
          (dy (- (rv-ref t #:y) (rv-ref p #:y))))
      (sqrt (+ (* dx dx) (* dy dy)))))
  (= (distance r nr) (distance nr r)))

Source code

record-vector at Codeberg

Authors

Anton Idukov

Licence

BSD-2-Clause licence.

Version History