Как избежать цикла загрузки в Racket? - PullRequest
0 голосов
/ 02 сентября 2018

У меня довольно простой набор .rkt источников и, скажем, среди них "a.rkt" и "b.rkt". Я хотел бы иметь возможность написать (require "a.rkt") в "b.rkt" и наоборот. Теперь я сталкиваюсь с ошибкой о "цикле загрузки".

Могу ли я решить эту проблему с голыми модулями без добавления модулей? Есть ли в Racket что-то похожее на предварительное объявление, чтобы я мог просто добавить отсутствующую подпись вместо того, чтобы требовать? Если оба ответа «Нет», знает ли кто-нибудь хороший и понятный учебник о том, как реализовать юниты с typed/racket ( помимо официальных документов)?

1 Ответ

0 голосов
/ 06 сентября 2018

Вы можете использовать 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!.

Если вы посмотрите на источник для 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))))
    ...))
...