On 04-01-2023 16:11, yarl baudig wrote: > Hello guile. > > I don't know if that's a bug. Anyway, I am confused about this so I ask. I came across this problem playing with guix source code. I will share different "tests" each test is a directory with nothing but the files I share. > each time the command to try the test (inside it's directory) is `guile --no-auto-compile -L . main.scm` > [...] My (untested) hypothesis (*: things I'm unsure about) If there is no #:export (...), then when (define-operation (valid-path?)) is expanded, the identifier 'valid-path?' is free (*). Hence, the following ... > (syntax-rules (name ...) > ((_ name) id) ...))))) refers to the free identifier 'valid-path?'. Conversely, if there is #:export, then the (syntax-rules (name ...) ...) looks for the bound identifier 'valid-path?' (*). Important: bound identifiers != free-identifier, even if they have the same symbol! For (simple-format #t "~S\n" (operation-id valid-path?)) to work, the 'valid-path?' of that expression must be bound if the syntax-rules looks for a bound identifier, and free if it looks for a free identifier. By adding a (export valid-path?) between the simple-format and the (define-operation ...), the 'valid-path?' in (simple-format ...) becomes a bound identifier (*). Proposed solutions: (a) Move the (export ...) after the (simple-format ...) instead of in-between the define-operation and simple-format (b) Or put the uses of define-operation and define-enumeration-type in the same file. (c) Or use (eq? (syntax->datum ...) ...) instead of the 'syntax-rules (...)', to ignore the lexical environment and hence the bound/free distinction. (This has consequences for users of 'main' that rename their import of 'valid-path?' -- by this change, operation-id will expect the unrenamed name, whereas in the original code (IIUC) it would expect the renamed name.) Greetings, Maxime.