首页 > 解决方案 > 如何避免球拍中的加载循环?

问题描述

我有一组非常简单的.rkt来源,比如其中的“a.rkt”和“b.rkt”。我希望能够(require "a.rkt")在“b.rkt”中书写,反之亦然。现在我面临关于“加载周期”的错误。

我可以在不添加单元的情况下用裸模块解决这个问题吗?球拍是否有任何类似于前向声明的东西,所以我可以简单地添加缺少的签名而不是要求?typed/racket如果两个答案都是“否”,是否有人知道如何使用(除了官方文档)实现单元的良好且易于理解的教程?

标签: schemeracket

解决方案


您可以使用lazy-require

;; a.rkt
#lang racket
(require racket/lazy-require)
(lazy-require ["b.rkt" (b)])
(provide a)
(define (a) 'a)
(list (a) (b))

;; b.rkt
#lang racket
(require racket/lazy-require)
(lazy-require ["a.rkt" (a)])
(provide b)
(define (b) 'b)
(list (a) (b))

请注意,您必须告诉lazy-require您要导入的具体内容。那是因为它是根据dynamic-requireplus来实现的set!

如果您查看 的源代码xrepl,您会看到它定义了一个defautoload宏,它(模一些 N/A 细节)很简单:

(define-syntax-rule (defautoload libspec id ...)
  (begin
    (define id
      (make-keyword-procedure
       (λ (kws kw-args . args)
         (set! id (dynamic-require 'libspec 'id))
         (keyword-apply id kws kw-args args))))
    ...))

推荐阅读