Gauche Devlog

< Extended formals | Import options: part one >

2010/05/01

Records and util.match

This is not a new feature for 0.9.1; it's been there for long time. But I rediscover it today with a pleasant surprise, so it may be worth to note about it, for I expect to use records more, as srfi-99 is supported in 0.9.1 (cf. ERR5RS Records and beyond).

The pattern matcher util.match can be used to match records. The feature already existed in the original Andrew Wright's match, and I believe it's available for many other Scheme implementations.

(use gauche.record)
(use util.match)
(use math.const)  ; for pi

(define-record-type circle #t #t radius)

(define-record-type rectangle #t #t width height)

(define (area shape)
  (match shape
    [($ circle r) (* pi r r)]
    [($ rectangle w h) (* w h)]))

gosh> (area (make-circle 5))
78.53981633974483
gosh> (area (make-rectangle 4 8))
32

($ class var ...) matches the instance of class, with binding slot values to var ... in order.

This pattern can be used for any instances, nevertheless I haven't used it much before. I care less about the order of slots when I think in terms of classes. Slots are always accessed by thier name, and I freely change the order of slots in class definitions, so it's a bit cumbersome to have patterns that depend on the order of slots.

However, records' slots feel more positional---maybe because their default constructor takes positional arguments to initialize slots. Also their emphasis of immutability reminds me the style of other functional languages.

If I find myself using this pattern more and more, it'll be worth to optimize it. Currently it looks up n-th slot name in the list of slots of the matching object, then uses slot-ref to obtain a value. For general objects we need to do that, since associations of the position and the slot can be changed by class redefinition. But for records we don't need to worry about class redefinition, and internally it's much faster to access records' slot via its position instead of its name.

Tags: gauche.record, srfi-99, util.match

Post a comment

Name: