On Wed, 2009-04-22 at 05:42 -0700, Ramana wrote:
> Can the record printer in Ikarus be customized (e.g. only print a
> certain field, or print field names)?

IIRC, no.  There's an existing request for this:
https://bugs.launchpad.net/ikarus/+bug/301441

> Can we extend equal? to new records (like "deriving Eq" in Haskell)?

equal? cannot be extended in any way.  eqv?, which equal? is specified
to use for records, is specified to compare records according to their
location in the store.  I'm guessing you want equal? to treat records as
it does pairs and vectors.  I.e., compare records' structural equality
rather than eqv? equality.

> What about in R6RS (i.e. without any Ikarus-specific features) (for
> both questions)?

If you want R6RS portability, you have to make these things yourself and
use them where needed.  You can make your own printer which recognizes
records and prints them as you want.  You can make your own equivalence
predicate which treats records as you want.  Scheme is intended to be a
small base platform upon which you build your own systems.

If you use a generics or type classes framework with a printer and a
structural equivalence predicate and build your software on it, you
could extend those things as desired and they'd work with other software
components built on the framework (I imagine).  If you only need a more
limited solution, you could do something like this:

(define (printer port obj)
  (if (record? obj)
    (print-record-my-way port obj)
    (put-datum port obj)))

To get the record data to print, use the records introspection
facilities described throughout R6RS Libraries Chapter 6.  You may find
useful what my (xitomatl records) library does to help with record
inheritance.  You could define print-record-my-way as:

(import (xitomatl records)
        (only (xitomatl common) fprintf))

(define (print-record-my-way port r)
  (let ((rtd (record-rtd r)))
    (fprintf port "#[~s" (record-type-name rtd))
    (for-each (lambda (f a)
                (fprintf port " ~s: ~s" f (a r)))
              (record-type-fields rtd)
              (record-type-accessors rtd))
    (put-string port "]")))

For a predicate to test structural equality of records, you could do
something like:

(define (record-equal? x y)
  (let ((x-rtd (record-rtd x))
        (y-rtd (record-rtd y)))
    (and (eqv? x-rtd y-rtd)
         (andmap (lambda (a) (equal? (a x) (a y)))
                 (record-type-accessors x-rtd)))))

But this does not handle the case when records' fields transitively
contain records.  To handle that, you'd need something like equal? which
works that way.  If you need that, you could adapt an existing
implementation of equal?, such as the cycle-safe one in:
ikarus.dev/scheme/ikarus.equal.ss

And remember: other components which do not use your printer and
predicate do not use them.

-- 
: Derick
----------------------------------------------------------------

Reply via email to