On Sat, 2009-04-25 at 17:12 +0200, Michele Simionato wrote:
> On Sat, Apr 25, 2009 at 4:50 PM, Abdulaziz Ghuloum <[email protected]> wrote:
> > There might be some subtle differences in other aspects
> > of running the program, like the behavior of call/cc or even read.
>
> Yes, I am aware of those differences. Also, in the REPL you can
> import modules at any moment, in scripts the import forms are
> the beginning.
>
> > [PS. your definition of assert-distinct should use bound-identifier=?
> > instead of free-identifier=?, unless I misunderstood what it's used
> > for. It is for checking duplicates in binding forms, like lambda, let
> > and letrec, right?]
> >
>
> I will free admit that I do not understand the details of free-identifier=?
> vs bound-identifier=? and that the R6RS document looks Greek to
> me when it tries to explain the differences. What I have grossly
> understood is that I should use bound-identifier=? when I want
> to check for names that to be bound (like names in a let form)
> and free-identifier=? if I want to compare a name with an unbound
> name, like a literal identifier. But this is foggy to me, for instance
> I do not understand the difference between free-identifier=?
> and a simple function like
>
> (define (identifier=? n1 n2)
> (eq? (syntax->datum n1) (syntax->datum n2)))
The R6RS does do a decent job of explaining succinctly, you just need to
understand the issues. Hopefully this helps:
(library (thing)
(export a)
(import (rnrs))
(define a 1))
(import (rnrs)
(thing)
(rename (thing) (a r:a)))
(define-syntax show
(syntax-rules ()
((_ expr)
(begin (write 'expr) (display " => ") (write expr) (newline)))))
(define-syntax fi
(lambda (stx)
(syntax-case stx ()
((_ x)
#`'#,(cond
;; If the value of the pattern variable refers to the same binding
;; as does the lexical scope of the `a' in the template.
((free-identifier=? #'x #'a) #'a)
;; If the value of the pattern variable is spelled the same as the
;; unbound `unbound' in the template.
((free-identifier=? #'x #'unbound) #'unbound)
(else #'unknown))))))
(show (fi a))
(show (fi r:a)) ;; `r:a' refers to the same binding as `a' in the macro does
(show (fi unbound)) ;; unbound, so the spelling is what's compared
(show (fi foo))
(show (let ((r:a 'shadow)) (fi r:a)))
(show (let-syntax ((a (lambda (_) 'shadow))) (fi a)))
(show (let ((unbound 'now-bound)) (fi unbound)))
(define-syntax bi
(lambda (stx)
(syntax-case stx ()
((_ x)
#'(bi x a)) ;; a is introduced here
((_ x y)
#`'(#,(bound-identifier=? #'x #'y)
#,(free-identifier=? #'x #'y))))))
(show (bi a)) ;; same scope, different introduction
(show (bi foo foo)) ;; same introduction, same spelling
(show (bi foo bar)) ;; same introduction, different spelling
(show (bi r:a a)) ;; same scope, same introduction
(define t 'mine)
(define-syntax introduce
(syntax-rules ()
((_ x)
(let ((t 'macro-introduced))
(list x t)))))
(show (introduce t))
$ ikarus --r6rs-script program.sps
(fi a) => a
(fi r:a) => a
(fi unbound) => unbound
(fi foo) => unknown
(let ((r:a 'shadow)) (fi r:a)) => unknown
(let-syntax ((a (lambda (_) 'shadow))) (fi a)) => unknown
(let ((unbound 'now-bound)) (fi unbound)) => unknown
(bi a) => (#f #t)
(bi foo foo) => (#t #t)
(bi foo bar) => (#f #f)
(bi r:a a) => (#f #t)
(introduce t) => (mine macro-introduced)
$
--
: Derick
----------------------------------------------------------------