问题
I have quite simple set of .rkt
sources and, say, "a.rkt" and "b.rkt" among them. I'd like to be able to write (require "a.rkt")
in "b.rkt" and vice versa. Now I'm facing error about "loading cycle".
Can I solve this issue with bare modules without adding units? Does Racket have anything similar to forward declaration so I could simple add missing signature instead of requiring? If both answers are "No", does someone know good and understandable tutorial on how to implement units with typed/racket
(aside of official docs)?
回答1:
You can use 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))
Notice that you must tell lazy-require
the specific things you want to import. That's because it is implemented in terms of dynamic-require
plus set!
.
If you peek at the source for xrepl, you'll see it define a defautoload
macro, which (modulo some N/A details) is simply:
(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))))
...))
来源:https://stackoverflow.com/questions/52137060/how-to-avoid-loading-cycle-in-racket