Getting started with Chez Scheme and Emacs on macOS and Windows

I recently decided to switch my attention from learning Racket to Chez Scheme. One of the reasons that I chose Racket was because of how easy it is to get up and running. Setting up a development environment for Chez requires jumping through a few more hoops. In this post, I document those hoops. Disclaimer: The suggestions in this post may not represent best practice. I will update the post as I become more experienced with Chez and Emacs.

Chez Scheme


On macOS, I installed Chez with Homebrew.

$ brew install chezscheme

On Windows, I used the Windows installer.

So far, so good. Nothing tricky about installing Chez Scheme.


To launch the Chez REPL on macOS, open a Terminal and type chez.1 On Windows, 3 Chez programs were installed (64-bit threaded and 32-bit threaded and unthreaded). Open any of those programs to get a Chez REPL.

Test the REPL with simple expression.

> (+ 100 10 1)

The REPL has several nice features including:

  • Navigate through previous expressions with the up and down arrow keys.
  • Autocomplete functions and paths with TAB.
  • Write and edit multi-line expressions.
> (define (example x y z)
    (if (> x 0)
        (+ y z)
        (- y z)))
> (example 1 2 3)

When navigating through previous expressions, only the first line of a multi-line expression is shown. To see (and edit) all lines, type CTRL+L. In the middle of an expression, RET creates a new line; to enter an expression from the middle of an expression, use CTRL+J.

Library Directory

Chez does not come with a package manager, but there are 3rd-party options. I have not thoroughly explored the options, but I have a spent some time with Raven on macOS. Mostly, though, I want to describe how Chez finds libraries.

> (library-directories)
(("." . "."))

The "." indicates that Chez looks for libraries in the default directory. You can find the default directory by running current-directory in a freshly launched Chez REPL.

On macOS…

> (current-directory)

On Windows…

> (current-directory)
"C:\\Program Files\\Chez Scheme 9.5"

You probably don’t want to put libraries in these default locations. When installing packages globally with Raven on macOS, libraries are placed in /usr/local/lib/raven. On Windows, where I’m not using Raven, I created a library directory at C:\scheme\lib.

Before we go over where to stash that directory information, let’s cover library extensions.

> (library-extensions)
((".chezscheme.sls" . "") (".ss" . ".so")
  (".sls" . ".so") (".scm" . ".so") (".sch" . ".so"))

These are the file extensions that Chez uses when searching the library directories. The authors of Raven recommend the use of .sc so we need to stash that information, too.

On macOS, I edited .bash_profile to add information on library directories and extensions. From a Terminal window, open .bash_profile with the Nano text editor.

$ nano .bash_profile

I added the following lines to my .bash_profile.

export CHEZSCHEMELIBDIRS="/usr/local/lib/raven:"

The : at the end is used to indicate that the new entries should be appended to the existing entries. Remove the : to replace the default values with the new entries. After saving .bash_profile, enter the following command in the Terminal (and maybe restart the Terminal).

$ source .bash_profile

Now, from a Chez REPL, we can see the effect of our changes.

> (library-directories)
(("/usr/local/lib/raven" . "/usr/local/lib/raven")
  ("." . "."))
> (library-extensions)
((".sc" . ".so") (".chezscheme.sls" . "") (".ss" . ".so")
  (".sls" . ".so") (".scm" . ".so") (".sch" . ".so"))

If we have a library at /usr/local/lib/raven/srfi/s1/lists.sls, then we import the library with (import (srfi s1 lists)), i.e., you pass the components of the path to import.

> (xcons 1 2)
Exception: variable xcons is not bound
Type (debug) to enter the debugger.
> (import (srfi s1 lists))
> (xcons 1 2)
(2 . 1)

On Windows 10, type env in the search box in the task bar and open the program to Edit the system environment variables. Then click the Environment Variables button. Click the button to create a new system variable. Type CHEZSCHEMELIBDIRS and C:\scheme\lib; in the name and value fields, respectively. Click OK. Repeat the process using CHEZSCHEMELIBEXTS and .sc;;.so; in the name and value fields. The ; in the values fields has the same meaning as the : on macOS.


I’m not aware of an IDE for Chez Scheme, but pairing a good text editor with the Chez REPL provides a decent development environment. I chose Emacs as a text editor. I’m slowly becoming more comfortable with Emacs, but I’m far from proficient.


On macOS, I installed Emacs with Homebrew.

$ brew cask install emacs

On Windows, I installed MSYS2 and then ran the following command from within MSYS2 to install Emacs.

$ pacman -S mingw-w64-x86_64-emacs

On macOS, I open Emacs via the icon in my applications folder. On Windows, I launch Emacs by typing emacs in the MSYS2 console.

Basic Usage

The power of Emacs is in the keyboard shortcuts and customization. I’m too early in my journey to have unlocked much of that potential. When you are browsing info on Emacs, you will see shorthand for referring to keyboard combinations, e.g., C-x C-f corresponds to CTRL+X followed by CTRL+F. The other important key is the meta key with M as the shorthand. On my MacBook, the meta key is option. On Windows, the default meta key is ALT. Similar to .bash_profile, Emacs can be customized through commands saved in the .emacs file.2


Geiser is a package that provides the ability to run several different Scheme implementations from within Emacs. We can install Geiser through MELPA.

Open Emacs, enter C-x C-f to find a file, and type .emacs at the prompt. On macOS, I added the following to .emacs.

(require 'package)

(add-to-list 'package-archives
             '("melpa" . "")

On Windows, I added the more extensive code provided on MELPA’s Getting Started page.

Save .emacs and restart Emacs. Then type M-x followed by package-refresh-contents. If that is successful, you will see the message Package refresh done in the minibuffer. To install Geiser, type M-x and then package-install. In response to the Install package: prompt, type geiser and hit return.

To customize Geiser, I used the menu options rather than directly editing the .emacs file. Choose Options/Customize Emacs/Specific Group... and type geiser at the prompt. Click on Geiser Chez and change the location of the binary.

On mac0S…


On Windows..

C:\Program Files\Chez Scheme 9.5\bin\ta6nt\scheme

Click Apply and Save. Click the Geiser link next to Parent groups: Click on Geiser Implementation and change the default implementation to chez. Optionally, you could also delete some (or all) of the non-Chez implementations listed under active implementations. Click Apply and Save. Restart Emacs.

The Chez REPL is launched through Emacs with M-x followed by run-chez. You can navigate through the previous expressions with ESC+P and ESC+N. Multi-line expressions, autocomplete, and syntax highlighting are also supported.

Library Directory

Apparently, the changes that we made to .bash_profile on macOS and the environment variables on Windows to point Chez to libraries and extensions are not picked up by the Chez REPL as used by Geiser. We need to add a couple of lines to .emacs.

On macOS…

(setenv "CHEZSCHEMELIBDIRS" "/usr/local/lib/raven")

On Windows…

(setenv "CHEZSCHEMELIBDIRS" "C:\\scheme\\lib;")
(setenv "CHEZSCHEMELIBEXTS" ".sc;;.so;")

UPDATE (2019-08-20): In Emacs, I eventually noticed that there is an option to highlight matching parantheses, which I find very helpful. Select Options/Highlight Matching Parantheses and then Options/Save Options. I’ve also started using company-mode for text completion. I was also pleased to discover that reindenting lines in Emacs is as simple as selecting the section to indent and pressing TAB.

  1. You can also type petite to launch Petite Chez Scheme. At this point, I don’t have a good understanding of why I would choose chez or petite. I have defaulted to using chez.↩︎

  2. More complicated file structures for customizing Emacs are possible, but my proficiency with Emacs is not at that level, yet.↩︎

Travis Hinkelman
Ecological Modeler