R6RSのライブラリの「レベル」指定はなぜ必要か? その2 - Scheme VM を書く
レベルが (meta 2) とか (meta 3) の例が理解できなくていろいろ探した結果、実際のコード例が見つかったのだけど全く分からないλ...。
レベルに関する記述なんて1ページなのになぜ理解できないのだろう。
examples.scm - Google Code Search
;;====================================================== ;; ;; Further library tests: ;; ;;====================================================== ;; Test meta-level resolution for chained imports: (library (foo) (export u) (import (rnrs)) (define u 1)) (library (bar) (export u v) (import (rnrs) (foo)) (define-syntax v (lambda (e) (syntax u)))) (library (baz) (export) (import (for (rnrs) (meta 2) expand run) (for (bar) (meta 2))) (display (let-syntax ((m (lambda (e) (let-syntax ((n (lambda (e) (+ u (v))))) (n))))) (m)))) (import (baz)) ;==> 2 ;;====================================================== ;; ;; Check that export levels compose correctly: ;; ;;====================================================== (library (foo) (export x y) (import (rnrs)) (define x 2) (define y 4)) (library (baz) (export y) ;; exports y at level 1 (import (rnrs) (for (foo) expand))) (library (bab) (export f) (import (for (rnrs) expand run) ;; This also implicitly imports into (meta 2) (for (foo) expand) ;; imports x and y at level 1 (for (baz) expand)) ;; also imports y but at level expand + 1 = 2 (define (f) (let-syntax ((foo (lambda (_) (+ x ;; level 1 y ;; level 1 (let-syntax ((bar (lambda (_) y))) ;; level 2 (bar)))))) (foo)))) (import (bab)) (f) ;==> 10 ;;========================================================== ;; ;; Check that levels of reference are determined lexically: ;; ;;========================================================== (library (foo) (export f) (import (rnrs)) (define (f) 1)) (library (bar) (export g) (import (rnrs) (for (foo) expand)) ;; This is the wrong level ! (define-syntax g (syntax-rules () ((_) (f))))) ;; This *must* be an error: ;; The use of f in bar cannot be satisfied ;; by the import of foo into the client level 0 here. ;; That would violate lexical determination of ;; level of reference to f in bar. ;; (library (main) ;; (export) ;; (import (rnrs) (foo) (bar)) ;; (display (g))) ;; ==> Syntax violation: Attempt to use binding of f in library (bar) at invalid meta level 0. ;; Binding is only valid at meta levels: 1 ;; Example from http://www.r6rs.org/r6rs-editors/2006-August/001682.html (library (A) (export x) (import (rnrs)) (define x 37)) (library (B) (export) (import (A))) (library (C) (export foo) (import (rnrs) (for (A) expand)) (define-syntax foo (syntax-rules () ((_) x)))) (library (D) (export foo) (import (rnrs) (C))) ;; This has to raise syntax error to avoid problem described in ;; above message. (library (E) (export) (import (rnrs) (B) (D)) ;; (display (foo)) ; Attempt to use x in library (C) at invalid meta level 0. ;; ; Binding is only available at meta levels: 1 ) ;;============================================================== ;; ;; Importing into multiple and negative levels: ;; ;;============================================================== (library (foo) (export x) (import (rnrs)) (define x 42)) (library (bar) (export get-x) (import (rnrs) ;; Code in (syntax ...) expressions refer to bindings ;; at one lower level - for example, ordinary macros ;; are evaluated at level expand = 1, but manipulate ;; code that will run at level run = 0. ;; The occurrence of (syntax x) below is not in a macro ;; but rather at level 0. ;; The reference x in (syntax x) is therefore at level -1. ;; To make it refer to the x in foo, we need to import ;; the latter at level -1. (for (foo) (meta -1))) (define (get-x) (syntax x))) (library (baz) (export) (import (for (rnrs) (meta 3) (meta 2) expand run) (for (bar) (meta 3) expand)) (display (let-syntax ((m (lambda (ignore) (get-x)))) (m))) ;==> 42 (display (let-syntax ((m (lambda (ignore) (let-syntax ((n (lambda (ignore) (let-syntax ((o (lambda (ignore) (get-x)))) (o))))) (n))))) (m))) ;==> 42 ;; This should give a syntax error: ;; (display ;; (let-syntax ((m (lambda (ignore) ;; (let-syntax ((n (lambda (ignore) ;; (get-x)))) ;; (n))))) ;; (m))) ;==> Syntax-violation: Attempt to use binding of get-x in library (baz) at invalid level 2 ;; ; Binding is only valid at levels (1 3) ) ;; baz (import (baz)) ;==> 42 42