[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Internal defines/reference implementations



I want to bring up the internal definition issue.  The current
proposal disallows internal record-type definitions because such
definitions `would require a more complex implementation'.  I'm not
sure this is true in an interesting sense.

In any Scheme where letrec happens to bind left to right (allowed by
the `is an error' language of r5rs 4.2.2, perhaps discouraged by the
syntax-rules definition of r5rs 7.3), the implementation required for
internal record-type definition does not, in fact, require a more
complex implementation.  That's as maybe.

Certainly, a portable _reference implementation_ would, indeed,
require a more complex implementation... the various record-?
procedure constructors would have to be macros if we wanted to get the
same efficiency that the current reference implementation has (though
I would argue that this doesn't make the code much more difficult to
read; see below for the obvious lifting of these procedures to
macros).

I guess the real question is whether SRFI's primarily exist to define
features or libraries.  I've got to believe it's the former, otherwise
we would be talking about slib.  And if it's the former, the
restriction to top-level seems pretty arbitrary.

-erik

P.S. Just to toss in my two cents, I'd also like Olin's extra two
parentheses to group the field specs (though I didn't put them in the
following code).

(define-syntax define-record-type
  (syntax-rules ()
    ((define-record-type type
       (constructor constructor-tag ...)
       predicate
       (field-tag accessor . more) ...)
     (begin
       (define type
	 (make-record-type 'type '(field-tag ...)))
       (define constructor
	 (record-constructor type '(field-tag ...) '(constructor-tag ...)))
       (define predicate
	 (record-predicate type))
       (define-record-field type 'field-tag '(field-tag ...) accessor . more)
       ...
       ))))

(define-syntax define-record-field
  (syntax-rules ()
    ((define-record-field type all-tags field-tag accessor)
     (define accessor (record-accessor type all-tags field-tag)))
    ((define-record-field type all-tags field-tag accessor modifier)
     (begin
       (define accessor (record-accessor type all-tags field-tag))
       (define modifier (record-modifier type all-tags field-tag))))))

(define-syntax record-constructor
  (syntax-rules ()
    ((record-constructor type all-tags constructor-tags)
     (let ((size (length all-tags))
	   (arg-count (length constructor-tags))
	   (indexes (map (lambda (tag)
			   (list-index tag all-tags))
			 constructor-tags)))
       (lambda args
	 (if (= (length args) arg-count)
	     (let ((new (make-record (+ size 1))))
	       (record-set! new 0 type)
	       (for-each (lambda (arg i)
			   (record-set! new i arg))
			 args
			 indexes)
	       new)
	     (error "wrong number of arguments to constructor" type args)))))))

(define-syntax record-predicate
  (syntax-rules ()
    ((record-predicate type)
     (lambda (thing)
       (and (record? thing)
	    (eq? (record-type thing)
		 type))))))

(define-syntax record-accessor
  (syntax-rules ()
    ((record-accessor type all-tags tag)
     (let ((index (list-index tag all-tags)))
       (lambda (thing)
	 (if (and (record? thing)
		  (eq? (record-type thing)
		       type))
	     (record-ref thing index)
	     (error "accessor applied to bad value" type tag thing)))))))

(define-syntax record-modifier
  (syntax-rules ()
    ((record-modifier type all-tags tag)
     (let ((index (list-index tag all-tags)))
       (lambda (thing value)
	 (if (and (record? thing)
		  (eq? (record-type thing)
		       type))
	     (record-set! thing index value)
	     (error "modifier applied to bad value" type tag thing)))))))