If you go to this branch:
https://codeberg.org/kakafarm-lisp-game-jam/shmendric-melabane/src/branch/why-cant-i-import-srfi-1-unfold
(here the repository worktree directory is named 2025-05-09-lisp-game-jam)
and run the commands as follows, you get this weird error:
yuval@computor:~/foo/2025-05-09-lisp-game-jam$ ./shell
yuval@computor ~/foo/2025-05-09-lisp-game-jam [env]$ make
rm -vf target/reflect.js target/reflect.wasm target/wtf8.wasm
guild compile-wasm -L modules --bundle -o target/game.wasm game.scm
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /gnu/store/w2grdcjmwg3likhg9as0k870z0w1lf60-profile/bin/guild
;;; WARNING: compilation of /gnu/store/w2grdcjmwg3likhg9as0k870z0w1lf60-profile/bin/guild failed:
;;; failed to create path for auto-compiled file "/gnu/store/w2grdcjmwg3likhg9as0k870z0w1lf60-profile/bin/guild"
Backtrace:
In hoot/library-group.scm:
1035:17 19 (foldts #<tree-il (seq (define input-values-east (lambd?>)
1035:17 18 (foldts #<tree-il (seq (define set-input-values-pointer?>)
1035:17 17 (foldts #<tree-il (seq (define input-values-pointer-loc?>)
1035:17 16 (foldts #<tree-il (seq (define set-input-values-pointer?>)
1035:17 15 (foldts #<tree-il (seq (define input-values-pointer-pre?>)
1035:17 14 (foldts #<tree-il (seq (define make-input-values (let (?>)
1035:17 13 (foldts #<tree-il (seq (define *previous-input* (call (?>)
1035:17 12 (foldts #<tree-il (seq (define *current-input* (call (t?>)
1035:17 11 (foldts #<tree-il (seq (define *player* (const #f)) (se?>)
1035:17 10 (foldts #<tree-il (seq (define *enemies* (const ())) (s?>)
1035:17 9 (foldts #<tree-il (seq (define make-new-game (lambda ((?>)
1035:17 8 (foldts #<tree-il (define make-new-game (lambda ((name ?>)
1035:17 7 (foldts #<tree-il (lambda ((name . make-new-game)) (lam?>)
1035:17 6 (foldts #<tree-il (lambda-case ((() #f #f #f () ()) (se?>)
1035:17 5 (foldts #<tree-il (seq (set! (toplevel *player*) (call ?>)
1035:17 4 (foldts #<tree-il (set! (toplevel *enemies*) (call (top?>)
1035:17 3 (foldts #<tree-il (call (toplevel length) (call (toplev?>)
1035:17 2 (fold-values #<procedure foldts (tree)> (#<tree-il (ca?>))
1035:17 1 (foldts #<tree-il (call (toplevel unfold) (lambda () (l?>)
1097:27 0 (_ _)
hoot/library-group.scm:1097:27: unbound top-level #("game.scm" 135 27) unfold
make: *** [Makefile:12: target/game.wasm] Error 1
I cannot import unfold from (srfi srfi-1). I have to copy and paste its GNU Guile implementation manually, and that is not good, I think.
What should I do to fix it?
Guile’s SRFI-1 is not yet compatible with Hoot, so Hoot has a very reduced subset of SRFI-1 at the moment. Copying the procedures you need into your project is the best short term option.
I would also like to use srfi-1 on hoot, it seems to me like the guile version is incompatible because guile’s core includes a handful of functions that hoot does not include
It should be quite easy to either add those to hoot’s core, or to copy over guile’s srfi-1 and add those definitions in there - which would be preferable?
It’s been awhile, but last time I tried to use SRFI-1 from Guile there were issues. I’d like to remove our very incomplete shim and direct people to just use Guile’s when that becomes possible.
Thanks for the quick reply!
I’ve taken a look, and found the following issues:
- hoot’s
case-lambda seems to not support matching on ( . rest) arguments, which are used in srfi-1
- hoot’s
case-lambda is not loaded by default
- a handful of procedures which are in guile’s core aren’t in hoot’s core (most notably
reverse!, concatenate, and concatenate!), and would have to be implemented
- guile allows local definitions in function bodies (aka “expression context”), hoot does not
- hoot’s
define* apparently doesn’t like = being used as an optional argument
- hoot doesn’t seem to like it when
map and for-each are redefined to support iterating over several lists at once
1 Like
Good list of issues. Thanks for gathering the information. I welcome help in chipping away at these!
I’ll take a gander at hoot’s internals and will try to see which of these I can fix
1 Like
I think the issues with case-lambda / definition stuff was caused by the relevant macros not having been loaded during my testing, so now an updated list of issues:
For guile’s srfi-1 to be loadable in hoot, the following modules need to be loaded:
(scheme case-lambda)
(hoot lists)
Guile’s srfi-1 expects a handful of procedures to be available that are not implemented in hoot’s core, namely:
length+
reverse!
concatenate
concatenate!
Guile uses load-extension to load native implementations of a handful of srfi-1 procedures. load-extension is unbound in hoot, and the procedures in question need to be implemented elsewhere. In particular, guile’s srfi-1 loads:
append-reverse from libguile/srfi-1.c,
append-reverse! from libguile/srfi-1.c,
count from libguile/srfi-1.c,
partition from libguile/srfi-1.c,
partition! from libguile/srfi-1.c,
remove from libguile/srfi-1.c,
remove! from libguile/srfi-1.c,
delete from libguile/srfi-1.c,
delete! from libguile/srfi-1.c,
delete-duplicates from libguile/srfi-1.c,
delete-duplicates! from libguile/srfi-1.c,
lset-difference! from libguile/srfi-1.c, and
filter! from libguile/list.c.
So now I’ve got a couple of questions:
Would the right course of action be to add these missing procedures to (hoot lists)? or somewhere else?
And how could/should we stub out load-extension?
Is it even possible to “inject” the dependencies on (scheme case-lambda) and (hoot lists) into (srfi srfi-1)?
That information seems a bit out of date. SRFI-1 used to rely on C extensions but it was rewritten in pure Scheme awhile back. Check out the version in Guile’s main branch and see what issues you run into.
oh yes, turns out my local guile checkout is 2 years old 
Thanks for the heads up!
with a current version of guile’s srfi-1 along with (define filter! filter) and (define reverse! reverse) added wherever appropriate it seems to just work!
I’ve just done some manual testing, as I couldn’t find a test suite for srfi-1
1 Like
Oh that’s better than the last time I checked. Okay, so those filter! and reverse! definitions can go in lib/guile.scm, if you’re interested in making a pull request. 