用 Scheme 作为 TEX的扩展语言
用 \eval
就可以在TEX文件里插入一段 Scheme.
当运行第二次tex2page 的时候,代码的运行结果就会被插入TEX文件。你可以用这些代码来改变 tex2page 的行为。
比如下面的代码将会打印 的值:1.4142135623730951
\eval{ (display (sqrt 2)) }
你可以想象一下,你能用 Scheme 在TEX里做什么吗?你几乎无所 不能!
看看第 16 章,里面有一些我自己定义的函数,可以随 意操纵文档的排版方式。我看了一会儿 tex2page 的代码就想出了几 乎所有我用的着的中文解决方案。
现在我把一个 coroutine 的测试代码放在这里,看看是什么结 果:
(require (lib "defmacro.ss")) (define-macro coroutine (lambda (x . body) `(letrec ((+local-control-state (lambda (,x) ,@body)) (resume (lambda (c v) (call/cc (lambda (k) (set! +local-control-state k) (c v)))))) (lambda (v) (+local-control-state v))))) (define make-matcher-coroutine (lambda (tree-cor-1 tree-cor-2) (coroutine dont-need-an-init-arg (let loop () (let ((leaf1 (resume tree-cor-1 'get-a-leaf)) (leaf2 (resume tree-cor-2 'get-a-leaf))) (if (eqv? leaf1 leaf2) (if (null? leaf1) #t (loop)) #f)))))) (define make-leaf-gen-coroutine (lambda (tree matcher-cor) (coroutine dont-need-an-init-arg (let loop ((tree tree)) (cond ((null? tree) 'skip) ((pair? tree) (loop (car tree)) (loop (cdr tree))) (else (resume matcher-cor tree)))) (resume matcher-cor '())))) (define tree-match? (lambda (tree1 tree2) (letrec ((tree-cor-1 (make-leaf-gen-coroutine tree1 (lambda (v) (matcher-cor v)))) (tree-cor-2 (make-leaf-gen-coroutine tree2 (lambda (v) (matcher-cor v)))) (matcher-cor (make-matcher-coroutine (lambda (v) (tree-cor-1 v)) (lambda (v) (tree-cor-2 v))))) (matcher-cor 'start-ball-rolling)))) (define tree1 '(((a b) (y z)) (3 4))) (define tree2 '(((a b) (t z)) (3 4))) (define tree3 '(((a (b y) z)) (3 4))) (define (display-line str . rest) (for-each display (cons str rest)) (newline)) (if (tree-match? tree1 tree2) (display-line "tree1 and tree2 match. ") (display-line "tree1 and tree2 don't match. ")) (if (tree-match? tree1 tree3) (display-line "tree1 and tree3 match. ") (display-line "tree1 and tree3 don't match. "))
结果是:tree1 and tree2 dont match. tree1 and tree3 match.
最后的结果就是 tex2page 交给 Scheme 解释器处理以后送回的结果。 这对与撰写 Scheme 文献非常有好处。