Thank you both for the detailed and informative replies. I've been able to get away with writing my-record-equal? and my-record-printer and using them wherever required. I could say it's a pity I have to rewrite standard functions like member (although at least I can use memp), but I guess it's not really that hard, and your point about using Scheme as a base platform is well taken.
On Thu, Apr 23, 2009 at 5:28 PM, Derick Eddington <[email protected]> wrote: > 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 > ---------------------------------------------------------------- > >
