I wrote a library foo/bar.rkt and I also allow to use it as a #lang. Roughly the structure is like this:
foo ├── bar │ ├── lang │ │ └── reader.rkt │ └── main.rkt ├── bar.rkt Most of the work happens in the library foo/bar.rkt, so naturally all of the tests reside there. I'd like to be able to test library proper, but also use the syntax of the language that I defined for it, so I try something like this and get a ... cycle? Sadly, I can't figure out why. Could you please help me reason through this. ;; foo/bar.rkt ;; ----------- (module+ test (module lang-test foo/bar (provide run-language-tests) (define (run-language-tests) 42)) (define run (dynamic-require 'lang-test 'run-language-tests)) (run)) ;; => error ; ; standard-module-name-resolver: cycle in loading ; at path: /Users/russki/Code/foo/bar.rkt ; paths: ; /Users/russki/Code/foo/bar.rkt Far as I can tell cycle isn't due to dynamic-require there, but due to that submodule declaration. This puzzles me, since the submod is declared with module, not module+ or module*. Other modules look as you'd probably expect: ;; foo/bar/lang/reader.rkt ;; ----------------------- #lang s-exp syntax/module-reader foo/bar/main ;; foo/bar/main.rkt ;; ---------------- #lang racket (require foo "../bar.rkt") (provide (except-out (all-from-out foo) #%app #%top) (rename-out [app #%app] [top #%top]) (except-out (all-from-out "../bar.rkt") app top)) Now, if we move the lang tests into a separate file, the dynamic-require above works out and no cycles are reported: ;; foo/lang-test.rkt ;; ----------------- #lang foo/bar (provide run-language-tests) (define (run-language-tests) 42) One hypothesis I have is that the (module lang-test foo/bar ...) doesn't resolve to the language but rather to the foo/bar.rkt. There must be a way to reflect how resolver works, but the closest I found was this: (require syntax/modresolve) (resolve-module-path 'foo/bar) And indeed it resolves to foo/bar.rkt, but then I don't know if I'm even using it correctly. I may actually be doing something stupid here e.g. introducing ambiguity as to how foo/bar is resolved (lang or lib) but this silliness brings about some things I'd like to clarify and learn: 1. How would you write your tests in the situation like this when most of the work happens in the library but you also allow using it as #lang? I'd like to keep both kinds of tests local to the library, so I can run them as I code. Or at least be able to run tests that only test the lib and corresponding language. 2. Why does the above report a cycle? How do I reason about it, better still how do I query the resolver, reflect and debug? Have I missed some important part in the docs about this? I wonder if the following convo is related and basically tells me I can'd test a language like this cause I'd need a submod trick or something: https://groups.google.com/forum/#!searchin/racket-users/cycle$20in$20loading%7Csort:date/racket-users/TXt6UtTBGBU/jVW8d94DBwAJ -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.