scheme-faq-programming


Scheme Frequently Asked Questions

The material on this page is licensed under the terms of the GNU Free Documentation License. See scheme-faq-license for more information about this.

general | language | macros | misc | programming | standards

Programming Concepts

Is there a module/unit/package/namespace system?

There is no standard module/unit/package/namespace system for Scheme. This is often considered a flaw of the language, but is in line with the rest of the language standard. The standard only defines features for which there is widespread consensus (in fact unanimous consensus by the authors) on the way they should work. There are simply too many different strategies for implementing module/unit/package/namespace systems - the very fact that we are using four different labels here for this feature is an indication of that.

Many Schemes provide their own modularisation facilities. Here is a list of the more "interesting" ones:

Dybvig and Waddell's portable macro system (see here), which is part of Chez Scheme, contains a module system that is implemented in terms of macros and can be retrofitted onto most Schemes.

What are "continuations"?

Continuations represent the "future" of computation at a particular point in program execution. Section 6.4 of R5RS gives a pretty good description of what exactly continuations are and how they can be "captured". It also outlines their ancestry in programming language theory.

Scheme is one of only a small number of languages that give the programmer access to continuations. Continuations have a multitude of uses but typically are only explictly dealt with in a few places in a program where their use greatly simplifies the structure of the code. Understanding and successfully using continuations is one of the key skills that distinguish a Scheme expert from a casual or novice user. Unfortunately, because continuations are such a comparatively unusual concept, good mainstream introductions to the concept and its application are hard to find. See The Scheme Programming Language, Fourth Edition by Kent Dybvig, which is also available online at http://www.scheme.com/tspl4 . Other good introductions can be found http://people.csail.mit.edu/people/jhbrown/scheme/continuationslides04.pdf and http://www.eleves.ens.fr/home/madore/computers/callcc.html .

How can I do object-oriented programming ?

Standard Scheme offers no direct support for object-oriented programming. However, implementing an OO framework on top of standard Scheme is not that difficult since closures provide a natural means of encapsulation. Portable OO systems that exploit this can be found in SLIB (see here), which contains two classless object systems, and in the OO section of the Scheme Repository at Indiana University (http://www.cs.indiana.edu/scheme-repository/code.oop.html).

Some Schemes have their own built-in OO system. Most of these are similiar to the Common Lisp Object System (CLOS), while others are conceptually closer to C++ and Java. Kawa is fully integrated with the Java object system, i.e. it allows Java classes to be defined and extended in Scheme.

How can I do logic programming and AI-related programming?

Prolog-style logic programming is facilitated by Cleary's Scheme Prolog - a Prolog interpreter in Scheme. See ftp://ftp.cs.indiana.edu/pub/scheme-repository/code/lang/prolog1.2.tar.gz. Dorai Sitaram's Prolog-in-Scheme (http://www.ccs.neu.edu/home/dorai/schelog/schelog.html, also known as Schelog, allows the mixing / interaction of declarative Prolog code with imperative "traditional" Scheme code. Kanren (http://kanren.sf.net/) is a declarative logic programming system with first-class relations, embedded in a pure functional subset of Scheme. If you want to write your own logic programming system in Scheme, the SICP (see here) chapter on Logic Programming provides plenty of inspiration and code.

FramerD (see http://framerd.sourceforge.net) is a portable distributed object-oriented database designed to support the maintenance and sharing of knowledge bases. Its scripting language is based on Scheme.

How can I do partial evaluation?

PGG (see http://s48.org/pgg/) is a partial evaluation system for Scheme built on top of Scheme48. It can take almost any R5RS-compliant Scheme program and perform a partial evaluation on it that produces a new Scheme program.

Similix (see http://www.diku.dk/OLD/forskning/topps/activities/similix.html) and Schism (see ftp://ftp.irisa.fr/local/lande/Schism) are partial evaluators for a large subset of Scheme. They should run in any R4RS-compliant Scheme.

How can I do exception handling?

Continuations (see here) can form the basis for implementing a simple throw/try/catch-style exception handling mechanism for Scheme in just a few lines. However, things get rather more complicated if the mechanism is to work in programs that themselves use continuations. Therefore, several Schemes come with built-in exception handling capabilities. SRFI-18 contains a general exception handling mechanism that also works in programs using the multi-threading extensions proposed by that SRFI. SRFI-34, which is complemented by SRFI-35 and SRFI-36, defines general exception rasing and handling constructs.

How can I write multi-threaded / concurrent programs?

Continuations (see here) can be used to implement coroutines and cooperative multi-threading. A few Schemes come with built-in preemptive multi-threading functionality. SRFI-18 and SRFI-19 define Scheme extensions for dealing with both "ordinary" and real-time multi-threading.

How can I do networking, e.g. TCP/IP / UDP?

Most Schemes come with built-in functions for accessing sockets. Some allow the definition of custom port types, thus enabling the use of standard Scheme port functions on sockets and many other objects.

How can I serve web pages?

Web applications can be built in any Scheme by using CGI, and complete web servers can be built in any Scheme with networking capabilities. Schemes with an FFI (see here) can access the many libraries available for supporting web programming (e.g. HTML generation, CGI processing).

OpenScheme and RScheme come with built-in support for CGI, incoming and outgoing HTTP, and HTML generation. For PLT Scheme there are several web programming packages available at http://www.cs.utah.edu/plt/develop/, including a complete web server, CGI, MIME, and cookie handling. Gauche also has cgi and html generation bits in its standard library.

Java-based Schemes can operate within the Java Servlet framework. JScheme features "Scheme Server Pages" that work in a similar way to Java Server Pages (JSPs). BRL (see here) , which is built on top of Java Servlets in Kawa, is a PHP-like web application framework.

Mod_lisp (http://www.fractalconcept.com/) is an Apache module to easily write web applications in Lisp/Scheme by implementing a TCP/IP-based protocol for communication between the Apache web server and Lisp/Scheme processes.

The Scheme FastCGI Proxy (http://zowie.metnet.navy.mil/~latendre/) allows Scheme code to be run as a fastCGI application under the mod_fcgi module available for the Apache web server. It is composed of a proxy written in C, basic input and output functions written in Scheme to communicate with that proxy, and a general code structure for the Scheme application. The Scheme application can be run locally or on remote computers.

LAML (http://www.cs.auc.dk/~normark/laml/) is a Scheme-based set of libraries for server side web programming as well programmatic authoring of complex WWW material.

How can I handle XML?

There is a striking similarity between XML and s-expressions (see here) - to such an extent that many people in the Lisp and Scheme community believe that XML is just a re-invention of s-expressions with an uglier syntax. For instance

<B>
  <A href="http://foo.bar">a link</A>
  <BR/>
  <P>some text</P>
</B>

can be represented as an s-expression as follows:

 (B (A (@ (href "http://foo.bar")) "a link") 
    (BR) 
    (P "some text")) 

This makes Scheme an ideal language for handling XML. Oleg Kiselyov has devised a complete framework for XML parsing, transformation, and generation, which is based on this model. The code and documentation are available from http://pobox.com/~oleg/ftp/Scheme/xml.html. Kirill Lisovsky has written several useful extensions to this package. See http://www.pair.com/lisovsky/sxml/index.html for details.

More "traditional" XML processing capabilities can be incorporated into Schemes that have an FFI (see here) by accessing native-language XML processing libraries.

WebIt! (http://celtic.benderweb.net/webit/) is an XML processing framework for PLT Scheme that, amongst other features, allows XSLT-like transformation to be performed by expansion-passing style Scheme macros.

The LAML software package supports XML via XML-in-LAML (http://www.cs.auc.dk/~normark/scheme/tutorial/xml-in-laml/xml-in-laml.html).

How can I do regular expression matching?

Most Schemes come with built-in support for regular expression matching using the same regular expression syntax found in languages such as Perl and Javascript. For Schemes that lack such facilities but have an FFI (see here), it is possible to access native-language regular expression libraries that are freely available for most languages. For a regular expression library that is implemented entirely in Scheme and works in any R4RS/R5RS-compliant implementation, check out Dorai Sitaram's pregexp package at http://www.ccs.neu.edu/home/dorai/pregexp/pregexp.html.

A different route, taken by some Schemes, is to represent regular expressions as s-expressions (see here), e.g.

  
 (: (or (in ("az")) (in ("AZ"))) 
    (* (uncase (in ("az09"))))) 
          

is a regular expression matching identifiers. The advantage of this representation over traditional regular expression syntax is the ease with which regular expressions can be constructed programmatically. It also gets around numerous idiosyncrasies of traditional regular expression notation. An in-depth explanation of "S-expression regular expressions" (SREs) can be found in http://www.ccs.neu.edu/home/shivers/papers/sre.txt, which details the rationale behind and implementation of SREs in the Scheme Shell (scsh, see http://www.scsh.net/).

How can I use Scheme for shell scripting?

Some Schemes all allow you to define Unix-style scripts containing Scheme code. SRFI-22 attempts to standardize the mechanism used for that.

Is there a way to execute Scheme programs in a "sandboxed" environment?

See http://community.livejournal.com/lisp/30281.html

What support is there for constructing parsers/compilers/interpreters for other languages?

Languages with a fully parenthesised syntax can be read and parsed by the standard Scheme reader/parser. Scheme macros in combination with ordinary Scheme code can be used to perform compilation/interpretation. See also here.

More general parser/compiler implementations are available from the Language Implementation section of the Scheme Repository at Indiana University (http://www.cs.indiana.edu/scheme-repository/code.lang.html) and in SLIB (see here).

Essence (http://www.informatik.uni-freiburg.de/proglang/software/essence/) is an LR parser generator for Scheme, writting in Scheme.

A fast LALR parser generator can be found at http://www.iro.umontreal.ca/~boucherd/Lalr/.

RegReg (http://www.iro.umontreal.ca/~latendre/scheme/regreg.html) is a parser generator based on tagged regular expressions.

Some Schemes come with their own libraries for implementing parsers. MIT/GNU Scheme comes with a parser and matching system that is Backaus-Naur Form -like.

Finally, Schemes with an FFI (see here) can use off-the-shelf parser/compiler libraries implemented in other languages.

How can I handle binary data?

See SRFI-56 which is an SRFI for handling binary data. Currently it is being drafted so the SRFI may change although currently the draft date has passed. Also SLIB provides a library for handling binary data called logicops.

Is there a way to check for the presence of a file or delete a file?

This is not in the standard, behaviors for open-like functions are unspecified in the case of non-existent files.

However, SLIB provides delete-file and file-exists?. You may be able to use SRFI-36, "I/O Conditions" to synthesize file-exists?. Particular implementations may provide functions, e.g. Guile provides a posix-style stat function.

Is there a way to access environment variables?

This is not in the standard.

However, SLIB provides getenv. Particular implementations may provide functions, e.g. Guile provides getenv. Additionally, SRFI-98, "An interface to access environment variables", defines a standardized method to access environment variables, but support is currently limited.

Is there a way to invoke scheme such that it evaluates expressions read from a file?

Almost all implementations provide such a mechanism. Please consult your documentation. Also see SRFI-22, "Running Scheme Scripts on Unix", for possible way to turn your Scheme file into an executable script.

On a *nix system, the convention is for programs to read from standard-input, and Scheme interpreters will typically do so. So, you would expect this to work:

somescheme < somefile.scm

Many interpreters provide command-options to load-and-execute a file. Guile, for example, uses -s somefile.scm.

How do I "pipe" the output of one scheme program to another?

This is completely dependant on your implementation and on your operating-system.

On *nix operating systems, programs are expected to play nice with "pipes" (specifically, "shell-pipes"). The only trick would then be executing your Scheme program.

As an example, in Guile you could guile -s prog1.scm | guile -s prog2.scm. Note that we told Guile to load and run the programs.

You could also manually construct the connection between the stdin and stdout of your Scheme programs, and use the posix exec family of commands. Assuming you had access to such affordances. This is what the *nix shell does for you.


category-scheme-faq