fileschemer5rs

R5RS circular dependency (cycle in loading)


I have two r5rs files - scheme-interpreter.scm and scheme-interpreter-operations.scm. The first file contains two functions - interpret and evaluate. The second file contains auxilliary functions, which get called inside evaluate. However, these functions can call evaluate as well. Thus, recursion occurs. When I reference each file in the other one like this:

(#%require "scheme-interpreter-operations.scm")
(#%provide (all-defined))
#lang r5rs
(#%require "scheme-interpreter-operations.scm")
(#%provide (all-defined))

I get errors. Is it possible to load files in a circular manner?


Solution

  • Using the Racket R5RS language with the racket module system on top like in your sample code, it's possible to have circular dependencies using using lazy-require.

    Example:

    s1.scm:

    #lang r5rs
    
    (#%require "s2.scm")
    (#%provide (all-defined))
    
    (define (evaluate x)
      (cond
       ((and (pair? x) (eq? (car x) '+))
        (add (cdr x)))
       ((number? x) x)))
    
    (display (evaluate '(+ 1 2)))
    (newline)
    

    s2.scm:

    #lang r5rs
    
    (#%require racket/lazy-require)
    (lazy-require ("s1.scm" (evaluate))) ; Lazily import evaluate
    (#%provide (all-defined))
    
    (define (add x)
      (apply + (map evaluate x)))
    

    And demonstration:

    $ racket s1.scm
    3
    

    For a general R5RS approach, a (load "s2.scm") in s1.scm works with Chicken, Guile and plt-r5rs, at least (With the Racket specific stuff removed, of course). Adjust filenames appropriately.