The Concurrent Schemer

The Erlang VM supports the Scheme programming language.


"The Concurrent Schemer" (CSCM) is an implementation of the Scheme programming language built on top of the Erlang Virtual Machine. CSCM combines the sequential programming model of Scheme with the concurrent, distributed, and fault-tolerant programming model of Erlang. Simply put, the goals of CSCM are concurrent Scheme, distributed Scheme, and fault-tolerant Scheme.

Scheme is a statically scoped and properly tail recursive dialect of the Lisp programming language invented by Guy Lewis Steele Jr. and Gerald Jay Sussman at MIT. Scheme was designed to have exceptionally clear and simple semantics and few different ways to form expressions. A wide variety of programming paradigms, including imperative, functional, and object-oriented styles, find convenient expression in Scheme.

Erlang is a programming language used to build massively scalable, soft, real-time systems with requirements on high availability. Erlang’s run-time system has built-in support for concurrency, distribution and fault tolerance. Erlang is designed at the Ericsson Computer Science Laboratory and is maintained as an open-source project and community.

The default language is Scheme R7RS. The default virtual machine is Erlang/OTP 17 or higher. Scheme R5RS is available as a Scheme library.

Caution Please stay tuned for CSCM updates. The specification, documentation, and software are under construction.

There is nothing new (and plenty old) about CSCM. Scheme is Scheme. Erlang is Erlang. CSCM is Scheme and Erlang. Nothing is lost but a lot is to be gained.

If one knows Scheme, one needs only to learn Erlang. If one knows Erlang, one needs only to learn Scheme. If one knows Scheme and Erlang, one already knows CSCM.

CSCM is nothing more than a carefully constructed implementation of Scheme. By leveraging the Erlang language, CSCM can target a concise, precise specification of the Scheme language. By leveraging the Erlang VM, CSCM can target a performant, robust implementation of the Scheme language.

CSCM is aimed as an:

  • educational tool
  • well-established, high-quality implementation of concurrent Scheme
  • Erlang reference project
  • The following R7RS standard features are already supported or planned to be supported:
    • r7rs
    • exact-closed
    • exact-complex
    • ieee-float
    • full-unicode
    • ratios
    • posix when the Erlang os:type/0 function returns unix for Osfamily.
    • windows when the Erlang os:type/0 function returns win32 for Osfamily.
    • <Osfamily> as returned by the Erlang os:type/0 function
    • <Osname> as returned by the Erlang os:type/0 function
    • <Otprel> as returned by the Erlang erlang:system_info/1 function for otp_release
    • <Sysarch> as returned by the Erlang erlang:system_info/1 function for system_architecture
    • Subparts of <Sysarch> split by the "-" character token
    • <Wordsize> as returned by the Erlang erlang:system_info/1 function for {wordsize, external} multiplied by 8
    • big-endian
    • scm
    • scm-X.Y.Z where X is the major, Y is the minor, and Z is the patch release version of scm

This draft overview paper of the Scheme programming language download-able from the Scheme Report's website is a good place to start. The final Scheme R7RS small report specification and errata available from the same website are the best next steps.

This roadmap is a DRAFT.

  • Programming
    • v0.1.0 Sequential "datum" PUBLISHED
      • datum model
      • datum tokenizer and parser
      • environment primitives
    • v0.2.0 Sequential "primitive expressions" PUBLISHED
      • primitive expressions - quote, lambda, if, set!, include, include-lib
      • programs - define
    • v0.2.5 Sequential "derived expressions" (part 1 of 2) PUBLISHED
      • derived expressions - cond, case, and, or, when, unless, cond-expand, let, let*, letrec, letrec*, begin, do, named let
      • temporary library procedures - eqv?, not
    • v0.2.8 Sequential "skeleton for libraries" PUBLISHED
      • libraries - skeleton implementation framework for all libraries
    • v0.3.0 Sequential "derived expressions" (part 2 of 2) PUBLISHED
      • derived expressions - let-values, let*-values, letrec-values, make-parameter, parameterize, guard
      • beta library procedures - apply, call-with-values, call-with-current-continuation (a.k.a. call/cc), values, call-with-values, dynamic-wind, with-exception-handler, raise, raise-continuable, error, error-object?, error-object-message, error-object-irritants, file-error?
      • programs - define-values
    • v0.4.0 Sequential "base library without number" PUBLISHED
      • base library - boolean (0 procedures)
      • base library - bytevector (16 procedures)
      • base library - char (8 procedures)
      • base library - control (7 procedures)
      • base library - equality (3 procedures)
      • base library - exception (0 procedures)
      • base library - io (56 procedures)
      • base library - list (0 procedures)
      • base library - string (20 procedures)
      • base library - symbol (4 procedures)
      • base library - system (0 procedures)
      • base library - vector (20 procedures)
    • v0.5.0 Sequential "syntax" (part 1 of 2, previously v0.7.0) PUBLISHED
      • beta syntax - lambda-syntax, set!-syntax, begin-syntax, let-syntax, let*-syntax, letrec-syntax, letrec*-syntax, syntax-rules, syntax-error
      • programs - define-syntax
    • v0.5.5 Sequential "syntax" (part 2 of 2, previously v0.7.0) IN PROGRESS
      • derived expressions - quasiquote, unquote, unquote-splicing
      • programs - define-record-type
    • v0.6.0 Sequential "libraries"
      • programs - import, define-library
      • libraries - case-lambda (1 procedure), char (22 procedures), cxr (25 procedures), eval (2 procedures), file (11 procedures), lazy (5 procedures), load (2 procedures), process-context (7 procedures), read (2 procedures), repl (1 procedure), time (3 procedures), write (8 procedures), r5rs (2 procedures)
      • tools - scm shell
    • v0.7.0 Sequential "base number library" (previously v0.5.0)
      • libraries - base number (52 procedures), complex (6 procedures), inexact (14 procedures)
    • v0.8.0 Sequential "features"
      • extensions - Erlang-style pattern matching, records, and binary support
      • integration - Erlang native functions, nif functions, and code loading
      • tools - scmc compiler
      • performance - lexical addressing for variable lookup
    • v0.9.0 Sequential "maintenance"
      • bug fixes
      • improvements
        • replace macro template expansion mechanism with a state-based approached that can detect invalid macro definitions and/or macro uses.
      • refactoring
      • performance tuning
      • documentation
      • compatibility testing (r7rs, r5rs, etc.)
      • Erlang/OTP enhancements
        • parsetools (leex.erl)
        • i/o protocol (file.erl, file_io_server.erl, group.erl, io.erl, io_lib.erl, user.erl)
    • v1.0.0 Concurrent "processes"
      • extensions - Erlang processes and error handling
      • libraries - erlang (demonitor, hibernate, is-process-alive, link, monitor, process-flag, process-info, processes, register, registered, resume-process, self, recv, send, send-after, send-nosuspend, spawn, spawn-link, spawn-monitor, spawn-opt, suspend-process, unlink, unregister, whereis, yield)
    • v1.1.0 Concurrent "distributed"
      • extensions - Erlang distribution and error handling
      • libraries - erlang (disconnect-node, is-alive, monitor-node, node, nodes)
      • libraries - net-adm (dns-hostname, host-file, localhost, names, ping, world, world-list)
      • libraries - net-kernel (allow, connect-node, monitor-nodes, get-net-ticktime, set-net-ticktime, start, stop)
      • tools - epmd
    • v1.2.0 Concurrent "ports and drivers"
      • extensions - Erlang ports, drivers, and error handling
    • v1.3.0 Concurrent "maintenance"
      • bug fixes
      • refactoring
      • performance tuning
      • documentation
  • Open Telecom Platform (OTP)
    • v1.5.0 OTP "applications"
      • behaviors - gen_server, gen_fsm, gen_event, supervisor
      • logging - system
      • applications
      • included applications
      • distributed applications
    • v1.6.0 OTP "releases"
      • releases
      • release handling
      • release distribution
      • release deployment
    • v1.7.0 OTP "maintenance"
      • bug fixes
      • refactoring
      • performance tuning
      • documentation
  • Tools
    • v2.0.0 Tools
  • Education and Training

These features are not specified in the [R7RS] specification.

  • include primitive expression. A filename may start with a path component $VAR, for some string VAR. If so, the value of the environment variable VAR as returned by (get-environment-variable VAR) is substituted for $VAR. If get-environment-variable returns false, $VAR is left as is. If the filename is absolute (possibly after variable substitution), the include file with that name is included. Otherwise, the specified file is searched for in the current working directory, in the same directory as the current including file, and in the directories given by the include option, in that order. The include option is available for the scm shell and scm compiler.
  • include-lib primitive expression. include-lib is similar to include but should not point out an absolute file. Instead, the first path component is assumed to be the name of an Erlang application. If the filename is absolute (possibly after variable substitution), an error is raised. Otherwise, the file is searched using the Erlang code:lib_dir/1 function.
  • letrec-values derived expression binding construct
  • let*-syntax and letrec*-syntax derived expression binding constructs for syntactic keywords

These features are also not specified in the [R7RS] specification but are under consideration and review as potential enhancements.

  • Proprietary procedures for bytevector-u8-set!, list-set!, string-set!, and vector-set! having the following properties:
    • different name
    • same number and meaning of arguments
    • same intended operation as original procedure but returns a modified copy of the object (as opposed to introducing side-effects)

These [R7RS] items are not supported.

  • Unsupported lexical conventions
    • datum labels
    • The !fold-case and !no-fold-case directives are treated as comments and have no effect on identifiers and character names read from the same port.
  • Unsupported primitive expressions
    • include-ci
    • include-lib-ci unsupported enhancement
  • Unsupported (scheme base) library exports
    • bytevector-copy!
    • bytevector-u8-set!
    • list-set!
    • read-bytevector!
    • set-car!
    • set-cdr!
    • string-copy!
    • string-fill!
    • string-set!
    • vector-copy!
    • vector-fill!
    • vector-set!
  • Unsupported (scheme r5rs) library exports
    • transcript-on
    • transcript-off
  • Miscellaneous
    • The maximum number of arguments that may be passed to a procedure is 255.
    • Inexact constants have double precision regardless of the specified exponent marker.

These [R7RS] items are not considered as limitations (but should be documented nevertheless).

  • Lexical conventions
    • Scheme symbols, characters, strings, and UTF-8 bytevectors must be composed of Unicode characters. Non-Unicode characters are rejected.
  • Binding constructs for syntatic keywords
    • Proprietary primitive expressions lambda-syntax, set!-syntax, and begin-syntax are used to implement binding constructs for syntatic keywords.
  • (scheme base) library exports
    • eqv? treats all pairs, vectors, bytevectors, records, and strings as having distinct locations.
    • eqv? and eq? share the same implementation.
    • char→integer returns only values equal to the Unicode scalar value of the given character. integer→char accepts only values that represent Unicode characters.
    • char-ready?, u8-ready?, peek-char, and peek-u8 are not supported for input ports that represent global resources (e.g. standard input) until the v0.9.0 release. The Erlang I/O-protocol and corresponding Erlang applications (i.e. kernel and stdlib) require changes to support such ready and peek operations.
    • flush-output-port is a no-op for output ports that represent global resources (e.g. standard output and standard error).
    • get-output-string and get-output-bytevector are unsupported for output ports that represent global resources (e.g. standard output and standard error).

Please report software issues and patches to the scm GitHub issue tracker if you have have trouble or simply found a bug. Similarly, please report documentation and specification issues to the scm-doc GitHub issue tracker.

Direct general questions and discussions to the The Concurrent Schemer Google group.

Support is provided on a timely, best-effort basis.

CSCM is looking for contributors to help with all parts of the Roadmap.

(define #Fun (+ #Scheme #Erlang))

If you are interested in Scheme, Erlang, Functional programming, or otherwise, please check the Contributor’s Guide for more information.

An incomplete list of CSCM, Scheme, Erlang, and Related resources.


  • website
  • faq
  • documentation
    • user’s guide
    • contributor’s guide
    • sample code and sample applications
  • community mailing list
    • announce
    • questions
    • bugs
    • patches
  • contributor site
    • source code repositories
    • issue tracker