【问题标题】:How to avoid loading cycle in Racket?如何避免球拍中的加载循环?
【发布时间】:2018-09-02 12:32:49
【问题描述】:

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

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

【问题讨论】:

  • 循环依赖通常是一种代码异味,表明您的程序结构不正确。您能否提供有关您的模块的更多详细信息,以帮助我们了解您的要求的必要性
  • 当然,例如,我有一些 Engine 和一些 Item,并且 Item 有 lambdas 作为字段,这些 lambdas 将 Engine 对象作为第一个参数;后来引擎正在处理项目列表。所以Engine需要Item,Item需要Engine

标签: scheme racket


【解决方案1】:

你可以使用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-require 加上set! 来实现的。

如果您查看source for xrepl,您会看到它定义了一个defautoload 宏,它(以一些不适用的细节为模)很简单:

(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))))
    ...))

【讨论】:

  • 好的,谢谢!你知道lazy-requiretyped/racket使用有什么问题吗?
  • 哦。从你的问题中我不清楚。是的,有麻烦。如果您使用的是 Typed Racket,我建议您使用单位(或者在这里提出一个关于编写您自己的类型化惰性要求的新问题)——如果您确定您确实需要相互 require-ing 模块。但首先:检查您是否可以将 Engine 和/或 Item 的递归定义与define-type 一起使用?和/或使用“defs.rkt”或“types.rkt”其他文件require
  • 非常感谢,格雷格。现在我明白了,在不同的语言中,我会尝试使用接口或特征。但这是完全不同的话题。
猜你喜欢
  • 1970-01-01
  • 2015-01-06
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
相关资源
最近更新 更多