gpt4 book ai didi

scheme - Chez 方案 : macro import at top level

转载 作者:行者123 更新时间:2023-12-04 20:27:53 25 4
gpt4 key购买 nike

我正在运行 Chez Scheme 9.5 并试图在
图书馆。下面是一个例子:

(library (forlib)
(export for)
(import (rnrs (6)))

(define-syntax for
(syntax-rules (in)
[(for x in lst body1 body2 ...)
(for-each (lambda (x) body1 body2 ...) lst)])))

我将其保存在一个文件中 forlib.ss并运行 chez来自同一个目录。
然后在 REPL 中,我得到了这个:
> (import (forlib))
> (for x in '(1 2 3) (display x))
Exception: invalid syntax (for x in (quote (1 2 3)) (display x))
Type (debug) to enter the debugger.

如果我将语法定义更改为
(define-syntax for
(syntax-rules ()
[(for x lst body1 body2 ...)
(for-each (lambda (x) body1 body2 ...) lst)])))

(没有 in 关键字),一切正常:
> (import (forlib))
> (for x '(1 2 3) (display x))
123
> _

回到旧定义 in关键词。
如果我将测试代码放入测试文件中:
;;; test-for.ss
(import (rnrs (6))
(forlib))

(for x in '(1 2 3) (display x))

并尝试执行此文件,结果取决于我如何执行该文件。
如果我使用 chez --program 运行这个程序,它按预期工作:
$ chez --program test-for.ss
123
$ _

如果我使用 chez --script 运行它,我得到与上面相同的错误:
$ chez --script test-for.ss
Exception: invalid syntax (for x in (quote (1 2 3)) (display x)) at line 6, char 1 of test-for.ss
$ _

这就提出了两个问题:
  • 为什么是 REPL 和 --script导入语法形式没有问题
    特殊关键字但拒绝接受具有特殊意义的语法形式
    其中的关键词?
  • --script之间究竟有什么区别?和 --program ?这
    用户手册说 --program意味着文件内容被解释
    作为一个 rnrs 顶级程序,但对于语义是什么保持沉默--script是。

  • 最后,为了让我的困惑完整,如果我输入上面的语法定义
    直接在 REPL 中,然后一切都按预期工作:
    > (define-syntax for
    (syntax-rules (in)
    [(for x in lst body1 body2 ...)
    (for-each (lambda (x) body1 body2 ...) lst)])))
    > (for x in '(1 2 3) (display x))
    123
    > _

    那么从导入的语法转换器之间的 REPL 有什么不同呢?
    直接在 REPL 中定义的库和语法转换器?

    最佳答案

    在 Chez Scheme 中,某些语义因操作模式而异。我将这些模式命名为 r6rs 和 repl。

    R6RS:

  • 程序(命令行上的 --program)

  • REPL:
  • 脚本(命令行上的 --script)
  • 文件(使用加载过程或作为 CLI 参数,没有 --program 或 --script)
  • 和 repl,当然是

  • 对于您的具体问题,如果您希望 repl 和脚本与库和程序的行为相匹配,则需要从 in 定义并导出一个名为 forlib 的标识符。这可以像空定义一样简单,或者您可以创建一个句法定义,在宏主体之外使用时会引发错误。
    简单的:
    (library (forlib)
    (export for in)
    (import (rnrs))

    (define in)

    (define-syntax for ...)
    )

    句法定义:
    (library (forlib)
    (export for in)
    (import (rnrs))

    (define-syntax in
    (identifier-syntax
    (error #f "Misplaced aux syntax in")))

    (define-syntax for ...)
    )

    两者都工作正常;使用您喜欢的任何一种。

    我知道的 repl 和 r6rs 模式之间的其他差异源于它们如何评估表达式。在 repl 模式下,每个表达式都是单独处理的。也就是说,Chez 读取一个表达式,计算该表达式,并可能打印出结果。在 r6rs 模式下,文件的全部内容都作为一个单元进行评估。明确地说,repl 模式的顶级延续是“读取、评估、也许打印和循环”,而 r6rs 模式的顶级延续是下一个表达式。
    例如,此代码在作为程序或脚本运行时的行为会有所不同:
    (import (chezscheme))

    (define println)

    (printf "~x\n"
    (call/cc (lambda (k)
    (set! println k)
    1)))

    (println 5)
    (println 6)

    另一个区别是,在 r6rs 模式下,您不能定义一个函数,然后在语法引用之外的语法案例宏扩展中使用它。
    (define ($two) 2)

    (define-syntax two
    (lambda (x)
    (syntax-case x ()
    [_ ($two)])))

    关于scheme - Chez 方案 : macro import at top level,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54173992/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com