Blog post: Guile Hoot v0.3.0 released!


We are excited to announce the release of Guile Hoot v0.3.0! Hoot is a Scheme to WebAssembly compiler backend for Guile, as well as a general purpose WebAssembly toolchain. In other words, Scheme in the browser!


  • Partial implementation of the Scheme module system! In past releases, programs were compiled by combining user code with a large Scheme prelude that contained the entire standard library. In this release, we’ve extracted all of the R7RS interface to their appropriate (scheme ...) modules and some Hoot-specific interfaces to (hoot ...) modules. Users can now use the import syntax to import these modules at the beginning of their programs. If no import form appears, a default set of modules is imported. User-defined modules are not yet supported. We plan to address this in the next release.Supporting the Scheme module system in a whole-program compiler like Hoot is no easy task due to procedural macros (syntax-case). If you’re interested in the details, check out Hoot lead engineer Andy Wingo’s blog post on the subject.
  • More of R7RS-small has been implemented and Hoot can now run over half of the Scheme benchmarks.
  • The toolchain can now emit and parse binaries with a name custom section. This optional feature makes binaries larger and is intended for debugging. By default, name sections are not emitted.
  • New hash table and weak key hashtable interfaces. Hoot’s hashtable interface is inspired by, but does not conform to, R6RS. Hash keys are currently limited to identity (eq) based hashing. eqv and equal hashing will come in a future release.
  • The (hoot reflect) module now automatically loads reflect.wasm. In past releases, users would have to locate and load this binary on their own. It quickly became the most common source of confusion for new users. We hope it is easier than ever to get started with Hoot!

Read on for the full change log.


  • Added import syntax.
  • Added truncate and exact-integer-sqrt procedures.
  • Added guard exception handling syntax.
  • Added call-with-port procedure.
  • Added complex number procedures make-polar, make-rectangular, magnitude, and angle.
  • Added string-map and substring procedures.
  • Added support for two list arguments in map and for-each (3+ lists still not implemented.)
  • Enhanced string->number to parse all types of numbers.
  • Fixed names of string comparison procedures. string-=? is now string=?, etc.
  • Fixed eta expansion of - and /.

Non-standard interfaces

  • Added hash tables and weak key hash tables.
  • Added external-non-null? procedure.
  • Added support for (ref extern) params/results to define-foreign.
  • Added support for (ref eq) results to define-foreign.
  • Fixed port seeking.


  • Added library-group form which encapsulates the entire compilation unit based on Enabling cross-library optimization and compile-time error checking in the presence of procedural macros.
  • Added #:emit-names? and #:imports compiler flags.
  • Removed #:env compiler flag.
  • read-and-compile now looks for an import form and includes only those modules in the compilation unit when specified.
  • Added support for f64 named temporaries to %inline-wasm.
  • Fixed fast path check for quo primcall.
  • Fixed fast path code for rsh/immediate primcall.


  • Uncaught exception details are now printed. True Scheme backtraces are not yet possible, however.
  • Fixed $argv table initialization to fit the maximum number of procedure arguments that can be known at compile time.
  • Fixed $apply to dynamically grow the $argv table when the number of arguments exceeds the current size.
  • Fixed $add-fracnum-fracnum when GCD is a bignum.
  • Fixed $quo when most negative fixnum is divided by -1.
  • Fixed stack pointer arithmetic in $fluid-ref*.


  • Added support for generating name custom section to resolve-wasm in (wasm-resolve).
  • Added support for name custom section to assemble-wasm in (wasm assemble).
  • Added support for name custom section to parse-wasm in (wasm parse).
  • Added id field to <wasm> type along with wasm-id accessor.
  • Added <names> type for name custom section.
  • Changed hoot-instantiate in (hoot reflect) to automaticall load reflect.wasm from Hoot’s installation directory or $HOOT_DATADIR.
  • reflect.js is now partially documented, though we hope to automatically generate all necessary JavaScript in the future so users need not concern themselves with this.

Browser compatibility

  • At last, Firefox 121, released in December, enables Wasm tail calls by default! This is the minimum Firefox version needed to run Hoot binaries without messing around in about:config.
  • Compatible with Google Chrome 119 or later.
  • Safari/WebKit is still unsupported.

Get Hoot 0.3.0!

Hoot is already available in GNU Guix:

$ guix pull
$ guix install guile-next guile-hoot

(Hoot currently requires a bleeding-edge version of Guile, hence guile-next above.)

Otherwise, Hoot can be built from source via our release tarball. See the Hoot homepage for a download link and GPG signature.

Documentation for Hoot 0.3.0, including build instructions, can be found here.


Several of us at Spritely will be attending both FOSDEM and the Guix days which precede them. Robin Templeton will be presenting Scheme in the Browser with Guile Hoot and WebAssembly in the Declarative and Minimalistic Computing devroom on Sunday, February 4th.

If you’re planning to attend, please come say hi!

Get in touch!

For bug reports, pull requests, or just to follow along with development, check out the Hoot project on GitLab.

If you build something cool with Hoot, let us know on our community forum!

The code in this release was brought to you by Andy Wingo, Robin Templeton, David Thompson. The lovely Hoot art is by tessa. Special thanks to the MetaMask folks for funding this work!

Until next time, happy hooting! :owl:


If anyone is interested in how easy Hoot is to use and extend, I was able to add some foreign function interfaces to a canvas contexts and create a Mandelbrot viewer with some limited controls for X, Y centering and Zoom. This is my first time using canvas btw!


Thank you for sharing this, @nanomonkey. So cool! And relatively little code, too!