On Sep 19, 2009, at 4:56 PM, David Van Horn wrote:
Suppose I define a cons-like structure and I want to provide a form
that is like quote, but produces my cons-like things when it quotes
syntactic pairs. In particular, I need the form to respect the eq?-
ness requirements on quoted pairs, so that:
(define (f) '(x))
(eq? (f) (f)) => #f
I wonder if someone could sketch how to do this in Ikarus?
I'll sketch two ways, each with its advantages/disadvantages.
First, suppose you have your cons-like structure defined in a separate
library:
(library (kons) (export kons pare? kar kdr) (import (rnrs))
(define-record-type (pare kons pare?)
(nongenerative)
(fields (immutable kar kar) (immutable kdr kdr))))
1. By evaluating the constant value at expansion time and producing a
quoted constant
This allows you to say:
> (import (konstant))
> (define (f) (konstant (kons 1 (kons 2 (kons 3 '())))))
> (eq? (f) (f))
#t
So, (konstant expr) evaluates expr at macro expansion time and stashes
the result
in a quoted constant. It may be implemented as:
(library (konstant)
(export konstant)
(import (rnrs))
(define-syntax konstant
(syntax-rules ()
[(_ expr)
(let-syntax ([quoteit
(lambda (x)
(with-syntax ([v (datum->syntax x expr)])
#'(quote v)))])
quoteit)])))
Advantages: this is the fastest access to the quote-like constant
since the value of expr is inlined in the code and the compiler sees
it as a constant and thus can copy-propagate it, etc.
Disadvantages: (1) expr has to be computable at expansion time (so, it
cannot reference lexical variables for example, hence the auxiliary
library), and (2) the value of expr has to be serializable.
Serializable things in R6RS are symbols, numbers, booleans, chars, the
empty list, pairs, vectors, bytevectors, and strings. Ikarus extends
the serializables to include structs, eq?- and eqv?-hashtables, and
records (though it does not make sense to use run-time generative
records, and that's why I used the nongenerative clause). Basically,
anything that contains a closure is not serializable.
2. Compute the expression once and remember it in a hash table at
subsequent references.
This is pretty straightforward.
(library (statik)
(export statik)
(import (rnrs) (konstant) (only (ikarus) gensym))
(define t (make-eq-hashtable))
(define-syntax statik
(syntax-rules ()
[(_ expr)
(let ([k (konstant (gensym))])
(or (hashtable-ref t k #f)
(let ([v expr])
(hashtable-set! t k v)
v)))])))
> (import (statik)
> (define (f) (statik (kons 1 (kons 2 (kons 3 '())))))
> (eq? (f) (f))
#t
Advantages: Fixes the limitations of the first approach by removing
all constraints to what expr may be.
Disadvantages: There's a hashtable lookup which may be expensive
compared to a quoted constant.
Converting (kquote (1 2 3)) into (konstant/statik (kons 1 (kons 2
(kons 3 '())))) should be straightforward, so, I'll leave it out.
Does any of these two approaches meet your requirement?
Aziz,,,