【问题标题】:Simulate a first-class library in R7RS Scheme在 R7RS Scheme 中模拟一个一流的库
【发布时间】:2014-01-31 08:28:44
【问题描述】:

我正在考虑为 Scheme 实现类似 Dylan 的对象系统。 (最好是完全可移植的 R7RS 方案。)在 Dylan 中有一个密封类的概念:不能从定义类的模块之外的密封类继承。

将 R7RS 库视为模块似乎很自然。但是,R7RS Scheme 中的库是静态的:在运行时不会保留任何关于它们的内容。从库中导入绑定后,它似乎与所有其他绑定无法区分。

嗯,这是sealed 实现的问题。假设一个类是由某个define-class 形式创建的。这种形式有效地扩展为类似

(define <new-class> (make <class> ...))

然后&lt;new-class&gt; 绑定可以从创建它的库中导出,然后导入到其他库(可能使用不同的名称)。假设我们在库 A 中创建了一个密封的 &lt;new-class&gt; 并将其导入到库 B。从 B 调用的 make 如何判断它是否可以创建 &lt;new-class&gt; 的后代?又如何允许从 A 调用的make 无条件地创建&lt;new-class&gt; 的子类?

(让我们忽略这种方法的一个缺点:R7RS 允许多次加载&lt;new-class&gt; 库,这有效地创建了几个不同的&lt;new-class&gt; 类对象。我真的不知道如何解决这个问题。)


一个想法是将所有类定义包含在一个表单中:

(define-library (A)
  (import (dylan))
  (export <new-class>)
  (begin
    (dylan-module
      (define-class <new-class> <object>
        ...  ) ) ) )

dylan-module 中定义的密封类可以继承自,但一旦表单结束,它们就真的是密封的。但是,我只想出了一种方法来实现这一点:

(define-syntax dylan-module
  (syntax-rules ()
    ((dylan-module %define-class body1 body2 ...)
     (begin
       ;; We will gather here all classes that are defined
       ;; inside the dylan-module form.
       (define to-be-sealed (list))

       ;; Locally redefine define-class to define a class
       ;; and add it to the list.
       ;;
       ;; It is necessary to pass %define-class explicitly
       ;; due to hygienic renaming: we want to allow %define-class
       ;; to be used inside of the body of the dylan-module form,
       ;; so we need to use a name from the environment where the
       ;; body is actually written.
       (let-syntax ((%define-class
                      (syntax-rules ()
                        ((%define-class name other (... ...))
                         (begin
                           (define-class name other (... ...))
                           (set! to-be-sealed
                                 (cons name to-be-sealed) ) ) ) ) ))
         body1 body2 ... )

       ;; The `seal` function is defined elsewhere.
       ;; `make` is allowed to subclass the sealed classes
       ;; until they are actually sealed by `seal`.
       (for-each seal to-be-sealed) ) ) ) )

它是这样使用的:

(define-library (A)
  (import (scheme base)
          (dylan) )
  (export <new-class>)
  (begin
    (dylan-module define-class
      (define-class <new-class> <object>
        ...  ) ) ) )

关于它的愚蠢之处在于:

  • 用户需要拼出define-class才能正确地重新定义它(在Dylan中,泛型函数也可以被密封,所以define-generic会紧随其后);

  • 通用make 无法以安全的方式创建密封类,应始终使用define-class 宏(或其他一些特殊情况)。

【问题讨论】:

    标签: scheme r7rs


    【解决方案1】:

    在我看来,您不应该尝试将 R6RS/R7RS 库重新用作类,而是直接在 Scheme 中构建自己的类。库旨在在编译时提供命名空间控制,而不是在运行时执行任何操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 2020-12-26
      • 2021-10-17
      • 2019-07-30
      • 2022-01-20
      • 1970-01-01
      相关资源
      最近更新 更多