Skip to content

Instantly share code, notes, and snippets.

@orchid-hybrid
Last active April 10, 2018 16:45
Show Gist options
  • Save orchid-hybrid/0770f1b91ba27a1ac021 to your computer and use it in GitHub Desktop.
Save orchid-hybrid/0770f1b91ba27a1ac021 to your computer and use it in GitHub Desktop.
R7RS modules problem

This is a problem I have with my minikanren implementation, it's split into a lot of files and I want to swap out the implementation of substitutions. Here is a cut down explanation of the problem:

Libraries that share a structure, and code based on them

I have a module peano which I implement another module four using.

;; peano.sld
(define-library (peano)
  (import (scheme base))
  (export one add)
  (begin
(define one `(s z))

(define (add p q)
  (if (eq? 'z p)
      q
      `(s ,(add (cadr p) q))))
))
;; four.scm
(define four
  (let ((two (add one one)))
    (add two two)))

Someone comes along with a more efficient data structure or something called numeral and I want to try swapping peano out for it.

;; numeral.scm
(define-library (numeral)
  (import (scheme base))
  (export one add)
  (begin
(define one 1)

(define (add p q) (+ p q))
))

I can share the implementation of four using two different .sdl files which both include it:

;; four-peano.sld
(define-library (four-numeral)
  (import (scheme base)
          (numeral))
  (export four)
  (include "four.scm"))
;; four-numeral.sld
(define-library (four-numeral)
  (import (scheme base)
          (numeral))
  (export four)
  (include "four.scm"))

and this works nicely

sash> (import (four-peano))
#<unspecified>
sash> four
(s (s (s (s z))))

sash> (import (four-numeral))
#<unspecified>
sash> four
4

Problem in larger program

If my program has a dependency tree like this:

A <= B <= PEANO <= FOUR <= X <= Y <= Z

then I have to have .sld files for each of these:

A <= B <= PEANO <= FOUR-P <= X-P <= Y-P <= Z-P
       <= NUMERAL <= FOUR-N <= X-N <= Y-N <= Y-N

This is too much code duplication, if you had this happen to another module you'd be dealing with 4x as many SLDs.

Solution?

I found something that gets around the problem, I'm not sure if it's a solution or a workaround.

If you do not create four.sld then (import (four)) will fail (since it doesn't know where to look).

You can create two .sld like this:

;; four-peano.sld
(define-library (four)
  (import (scheme base)
          (peano))
  (export four add)
  (include "four-impl.scm"))
;; four-numeral.sld
(define-library (four)
  (import (scheme base)
          (numeral))
  (export four add)
  (include "four-impl.scm"))

and then just include the one that you want (import (four)) to use. This way we only need one implementation of (eight):

;; eight.sld
(define-library (eight)
  (import (scheme base)
          (four))
  (export eight)
  (begin

(define eight (add four four))

))

and we can select which implementation of numbers four should use:

$ rlwrap sagittarius -c -L. -S.sld
sash> (include "four-peano.sld") (import (four))
#<unspecified>
sash> #<unspecified>
sash> (import (eight))
#<unspecified>
sash> eight
(s (s (s (s (s (s (s (s z))))))))

$ rlwrap sagittarius -c -L. -S.sld
sash> (include "four-numeral.sld") (import (four))
#<unspecified>
sash> #<unspecified>
sash> (import (eight))
#<unspecified>
sash> eight
8

I'm not too keen on having to do an include like that - what do you think?

@SaitoAtsushi
Copy link

I suggest define add and one as modifiable (parameterizable) object.

;; add.sld
(define-library (add)
  (import (scheme base))
  (export add set-add! one set-one!)
  (begin
    (define add (lambda _ (error "procedure `add' is not selected")))
    (define one #f)

    (define (set-one! obj)
      (set! one obj))
    
    (define (set-add! proc)
      (set! add proc))
    ))
;; peano.sld
(define-library (peano)
  (import (scheme base)
          (add))
  (begin

    (set-one! `(s z))

    (set-add!
     (lambda(p q)
       (if (eq? 'z p)
           q
           `(s ,(add (cadr p) q)))))
    ))
;; numeral.sld
(define-library (numeral)
  (import (scheme base)
          (add))
  (begin
    (set-one! 1)
    (set-add! +)
    ))
;; four.sld
(define-library (four)
  (import (scheme base)
          (add))
  (export four)

  (begin
  (define four
    (let ((two (add one one)))
      (add two two)))
  ))
;; eight.sld
(define-library (eight)
  (import (scheme base)
          (add)
          (four))
  (export eight)
  (begin
    (define eight (add four four))
    ))

You can choose effect by what you import.

$ sash -c -L. -S.sld
sash> (import (peano) (eight))
#<unspecified>
sash> eight
(s (s (s (s (s (s (s (s z))))))))


$ sash.exe -c -L. -S.sld
sash> (import (numeral) (eight))
#<unspecified>
sash> eight
8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment