Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid loading cycle in Racket?

Tags:

scheme

racket

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)?

like image 777
Bohdan Ivanov Avatar asked Sep 02 '18 12:09

Bohdan Ivanov


1 Answers

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))))
    ...))
like image 172
Greg Hendershott Avatar answered Sep 28 '22 11:09

Greg Hendershott