What do you expect to be printed?

I was testing how include on Sagittarius works and found out something interesting.

Firstly, I've prepared 4 files related to library. The contents are very simple. Like this;
;; foo.sld
(define-library (foo)
    (import (scheme base))
    (export bar)
  (include "impl/bar.scm"))

;; impl/bar.scm
(include "buzz.scm")

;; impl/buzz.scm
(define bar 'bar)

;; buzz.scm
(define bar 'buzz)
Now I put those files following directory structure;
./ + foo.sld
   + impl
       + bar.scm
       + buzz.scm
   + buzz.scm
Then, wrote following script;
(import (scheme base) (scheme write) (foo))
(display bar) (newline)
The question is, what would be the expected value to be printed 'bar or 'buzz? I first expected to be print 'bar with Sagittarius but it was 'buzz. Then checked with Chibi which also printed 'buzz. At this point I thought, oh R7RS de-facto would be 'buzz. Well it wasn't. I've also check with Gauche and Foment and these printed 'bar.

I know why this happens actually. When the first include was processed then the current loading path returned to the same directly as "foo.sld". Then second include "buzz.scm" is processed. I don't know how Gauche and Foment do this properly (well R7RS doesn't specify how to resolve the path so both are proper behaviour though).

Well, by now I've never seen this type of code in anywhere other than in my test. But I would like to go more intuitive behaviour.

13th August, 2014
I've modified compiler to be able to handle above case. What I've changed is that
  • include and include-ci returns read expression and filename
  • compiler sets current load path after include is done according to above filenam
It's a bit ugly way to fix so I need to think how we can clean it up now.


Shiro Kawai said...

At some point I hope srfi is made to set the standard. Gauche's behavior in this case follows cpp's #include "something"; it'ts relative to the file that immediately including the target. Rationale - suppose there's another file foo2.sld in a different directory, which (include "foo.sld"). You don't want yet another "buzz.scm" to be included.

kei said...

I totally agree with the rationale. Even like this would be a problem

(define-library (foo)
(import (scheme base))
(export bar)
(include "impl/bar.scm")
(include "buzz.scm"))

I would expect both buzz.scm to be included but currently only one buzz.scm is included :(

foof said...

Chibi does what you expect for the include library declaration (inside possibly nested include-library-declarations).

The include _macro_ I didn't want to support at all, because it's not needed in libraries, and it's dangerous in scripts. If you move a script that uses includes, it will break. So I deliberately made the Chibi implementation do the opposite of what other impls do.

kei said...

I haven't tried include-library-declaration so didn't notice that.

At some point include is convenient but I agree with that it's dangerous. It can easily break hygienic macros if it reads symbols as it is (which I believe required by R7RS).

Post a Comment