Guile Reference Manual


Next: , Previous: (dir), Up: (dir)

The Guile Reference Manual

This reference manual documents Guile, GNU's Ubiquitous Intelligent Language for Extensions. This is edition 1.1 corresponding to Guile 1.8.5.

Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with the no Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Text “You are free to copy and modify this GNU Manual.”. A copy of the license is included in the section entitled “GNU Free Documentation License”.


Appendices

Indices

Table of Contents


Next: , Previous: Top, Up: Top

1 Preface

This reference manual documents Guile, GNU's Ubiquitous Intelligent Language for Extensions. It describes how to use Guile in many useful and interesting ways.

This is edition 1.1 of the reference manual, and corresponds to Guile version 1.8.5.


Next: , Up: Preface

1.1 Layout of this Manual

The manual is divided into five chapters.

Chapter 1: Introduction to Guile
This part provides an overview of what Guile is and how you can use it. A whirlwind tour shows how Guile can be used interactively and as a script interpreter, how to link Guile into your own applications, and how to write modules of interpreted and compiled code for use with Guile. Everything introduced here is documented again and in full by the later parts of the manual. This part also explains how to obtain and install new versions of Guile, and how to report bugs effectively.
Chapter 2: Programming in Scheme
This part provides an overview over programming in Scheme with Guile. It covers how to invoke the guile program from the command-line and how to write scripts in Scheme. It also gives an introduction into the basic ideas of Scheme itself and to the various extensions that Guile offers beyond standard Scheme.
Chapter 3: Programming in C
This part provides an overview of how to use Guile in a C program. It discusses the fundamental concepts that you need to understand to access the features of Guile, such as dynamic types and the garbage collector. It explains in a tutorial like manner how to define new data types and functions for the use by Scheme programs.
Chapter 4: Guile API Reference
This part of the manual documents the Guile API in functionality-based groups with the Scheme and C interfaces presented side by side.
Chapter 5: Guile Modules
Describes some important modules, distributed as part of the Guile distribution, that extend the functionality provided by the Guile Scheme core.


Next: , Previous: Manual Layout, Up: Preface

1.2 Conventions used in this Manual

We use some conventions in this manual.


Next: , Previous: Manual Conventions, Up: Preface

1.3 Contributors to this Manual

The Guile reference and tutorial manuals were written and edited largely by Mark Galassi and Jim Blandy. In particular, Jim wrote the original tutorial on Guile's data representation and the C API for accessing Guile objects.

Significant portions were contributed by Gary Houston (contributions to POSIX system calls and networking, expect, I/O internals and extensions, slib installation, error handling) and Tim Pierce (sections on script interpreter triggers, alists, function tracing).

Tom Lord contributed a great deal of material with early Guile snapshots; although most of this text has been rewritten, all of it was important, and some of the structure remains.

Aubrey Jaffer wrote the SCM Scheme implementation and manual upon which the Guile program and manual are based. Some portions of the SCM and SLIB manuals have been included here verbatim.

Since Guile 1.4, Neil Jerram has been maintaining and improving the reference manual. Among other contributions, he wrote the Basic Ideas chapter, developed the tools for keeping the manual in sync with snarfed libguile docstrings, and reorganized the structure so as to accommodate docstrings for all Guile's primitives.

Martin Grabmueller has made substantial contributions throughout the reference manual in preparation for the Guile 1.6 release, including filling out a lot of the documentation of Scheme data types, control mechanisms and procedures. In addition, he wrote the documentation for Guile's SRFI modules and modules associated with the Guile REPL.


Previous: Contributors, Up: Preface

1.4 The Guile License

Guile is Free Software. Guile is copyrighted, not public domain, and there are restrictions on its distribution or redistribution, but these restrictions are designed to permit everything a cooperating person would want to do.

C code linking to the Guile library is subject to terms of that library. Basically such code may be published on any terms, provided users can re-link against a new or modified version of Guile.

C code linking to the Guile readline module is subject to the terms of that module. Basically such code must be published on Free terms.

Scheme level code written to be run by Guile (but not derived from Guile itself) is not resticted in any way, and may be published on any terms. We encourage authors to publish on Free terms.

You must be aware there is no warranty whatsoever for Guile. This is described in full in the licenses.


Next: , Previous: Preface, Up: Top

2 Introduction to Guile


Next: , Up: Introduction to Guile

2.1 What is Guile?

Guile is an interpreter for the Scheme programming language, packaged for use in a wide variety of environments. Guile implements Scheme as described in the Revised^5 Report on the Algorithmic Language Scheme (usually known as R5RS), providing clean and general data and control structures. Guile goes beyond the rather austere language presented in R5RS, extending it with a module system, full access to POSIX system calls, networking support, multiple threads, dynamic linking, a foreign function call interface, powerful string processing, and many other features needed for programming in the real world.

Like a shell, Guile can run interactively, reading expressions from the user, evaluating them, and displaying the results, or as a script interpreter, reading and executing Scheme code from a file. However, Guile is also packaged as an object library, allowing other applications to easily incorporate a complete Scheme interpreter. An application can then use Guile as an extension language, a clean and powerful configuration language, or as multi-purpose “glue”, connecting primitives provided by the application. It is easy to call Scheme code from C code and vice versa, giving the application designer full control of how and when to invoke the interpreter. Applications can add new functions, data types, control structures, and even syntax to Guile, creating a domain-specific language tailored to the task at hand, but based on a robust language design.

Guile's module system allows one to break up a large program into manageable sections with well-defined interfaces between them. Modules may contain a mixture of interpreted and compiled code; Guile can use either static or dynamic linking to incorporate compiled code. Modules also encourage developers to package up useful collections of routines for general distribution; as of this writing, one can find Emacs interfaces, database access routines, compilers, GUI toolkit interfaces, and HTTP client functions, among others.

In the future, we hope to expand Guile to support other languages like Tcl and Perl by translating them to Scheme code. This means that users can program applications which use Guile in the language of their choice, rather than having the tastes of the application's author imposed on them.


Next: , Previous: What is Guile?, Up: Introduction to Guile

2.2 Obtaining and Installing Guile

Guile can be obtained from the main GNU archive site ftp://ftp.gnu.org or any of its mirrors. The file will be named guile-version.tar.gz. The current version is 1.8.5, so the file you should grab is:

ftp://ftp.gnu.org/pub/gnu/guile-1.8.5.tar.gz

To unbundle Guile use the instruction

     zcat guile-1.8.5.tar.gz | tar xvf -

which will create a directory called guile-1.8.5 with all the sources. You can look at the file INSTALL for detailed instructions on how to build and install Guile, but you should be able to just do

     cd guile-1.8.5
     ./configure
     make
     make install

This will install the Guile executable guile, the Guile library -lguile and various associated header files and support libraries. It will also install the Guile tutorial and reference manual.

Since this manual frequently refers to the Scheme “standard”, also known as R5RS, or the “Revised^5 Report on the Algorithmic Language Scheme”, we have included the report in the Guile distribution; See Introduction. This will also be installed in your info directory.


Next: , Previous: Obtaining and Installing Guile, Up: Introduction to Guile

2.3 A Whirlwind Tour

This chapter presents a quick tour of all the ways that Guile can be used. There are additional examples in the examples/ directory in the Guile source distribution.

The following examples assume that Guile has been installed in /usr/local/.


Next: , Up: Whirlwind Tour

2.3.1 Running Guile Interactively

In its simplest form, Guile acts as an interactive interpreter for the Scheme programming language, reading and evaluating Scheme expressions the user enters from the terminal. Here is a sample interaction between Guile and a user; the user's input appears after the $ and guile> prompts:

     $ guile
     guile> (+ 1 2 3)                ; add some numbers
     6
     guile> (define (factorial n)    ; define a function
              (if (zero? n) 1 (* n (factorial (- n 1)))))
     guile> (factorial 20)
     2432902008176640000
     guile> (getpwnam "jimb")        ; find my entry in /etc/passwd
     #("jimb" ".0krIpK2VqNbU" 4008 10 "Jim Blandy" "/u/jimb"
       "/usr/local/bin/bash")
     guile> C-d
     $


Next: , Previous: Running Guile Interactively, Up: Whirlwind Tour

2.3.2 Running Guile Scripts

Like AWK, Perl, or any shell, Guile can interpret script files. A Guile script is simply a file of Scheme code with some extra information at the beginning which tells the operating system how to invoke Guile, and then tells Guile how to handle the Scheme code.

Here is a trivial Guile script, for more details See Guile Scripting.

     #!/usr/local/bin/guile -s
     !#
     (display "Hello, world!")
     (newline)


Next: , Previous: Running Guile Scripts, Up: Whirlwind Tour

2.3.3 Linking Guile into Programs

The Guile interpreter is available as an object library, to be linked into applications using Scheme as a configuration or extension language.

Here is simple-guile.c, source code for a program that will produce a complete Guile interpreter. In addition to all usual functions provided by Guile, it will also offer the function my-hostname.

     #include <stdlib.h>
     #include <libguile.h>
     
     static SCM
     my_hostname (void)
     {
       char *s = getenv ("HOSTNAME");
       if (s == NULL)
         return SCM_BOOL_F;
       else
         return scm_from_locale_string (s);
     }
     
     static void
     inner_main (void *data, int argc, char **argv)
     {
       scm_c_define_gsubr ("my-hostname", 0, 0, 0, my_hostname);
       scm_shell (argc, argv);
     }
     
     int
     main (int argc, char **argv)
     {
       scm_boot_guile (argc, argv, inner_main, 0);
       return 0; /* never reached */
     }

When Guile is correctly installed on your system, the above program can be compiled and linked like this:

     $ gcc -o simple-guile simple-guile.c -lguile

When it is run, it behaves just like the guile program except that you can also call the new my-hostname function.

     $ ./simple-guile
     guile> (+ 1 2 3)
     6
     guile> (my-hostname)
     "burns"


Next: , Previous: Linking Guile into Programs, Up: Whirlwind Tour

2.3.4 Writing Guile Extensions

You can link Guile into your program and make Scheme available to the users of your program. You can also link your library into Guile and make its functionality available to all users of Guile.

A library that is linked into Guile is called an extensions, but it really just is an ordinary object library.

The following example shows how to write a simple extension for Guile that makes the j0 function available to Scheme code.

     #include <math.h>
     #include <libguile.h>
     
     SCM
     j0_wrapper (SCM x)
     {
       return scm_make_real (j0 (scm_num2dbl (x, "j0")));
     }
     
     void
     init_bessel ()
     {
       scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper);
     }

This C source file needs to be compiled into a shared library. Here is how to do it on GNU/Linux:

     gcc -shared -o libguile-bessel.so -fPIC bessel.c

For creating shared libraries portably, we recommend the use of GNU Libtool (see Introduction).

A shared library can be loaded into a running Guile process with the function load-extension. The j0 is then immediately available:

     $ guile
     guile> (load-extension "./libguile-bessel" "init_bessel")
     guile> (j0 2)
     0.223890779141236


Previous: Writing Guile Extensions, Up: Whirlwind Tour

2.3.5 Using the Guile Module System

Guile has support for dividing a program into modules. By using modules, you can group related code together and manage the composition of complete programs from largely independent parts.

(Although the module system implementation is in flux, feel free to use it anyway. Guile will provide reasonable backwards compatibility.)

Details on the module system beyond this introductory material can be found in See Modules.


Next: , Up: Using the Guile Module System
2.3.5.1 Using Modules

Guile comes with a lot of useful modules, for example for string processing or command line parsing. Additionally, there exist many Guile modules written by other Guile hackers, but which have to be installed manually.

Here is a sample interactive session that shows how to use the (ice-9 popen) module which provides the means for communicating with other processes over pipes together with the (ice-9 rdelim) module that provides the function read-line.

     $ guile
     guile> (use-modules (ice-9 popen))
     guile> (use-modules (ice-9 rdelim))
     guile> (define p (open-input-pipe "ls -l"))
     guile> (read-line p)
     "total 30"
     guile> (read-line p)
     "drwxr-sr-x    2 mgrabmue mgrabmue     1024 Mar 29 19:57 CVS"


Next: , Previous: Using Modules, Up: Using the Guile Module System
2.3.5.2 Writing new Modules

You can create new modules using the syntactic form define-module. All definitions following this form until the next define-module are placed into the new module.

One module is usually placed into one file, and that file is installed in a location where Guile can automatically find it. The following session shows a simple example.

     $ cat /usr/local/share/guile/foo/bar.scm
     
     (define-module (foo bar))
     (export frob)
     
     (define (frob x) (* 2 x))
     
     $ guile
     guile> (use-modules (foo bar))
     guile> (frob 12)
     24


Previous: Writing new Modules, Up: Using the Guile Module System
2.3.5.3 Putting Extensions into Modules

In addition to Scheme code you can also put things that are defined in C into a module.

You do this by writing a small Scheme file that defines the module and call load-extension directly in the body of the module.

     $ cat /usr/local/share/guile/math/bessel.scm
     
     (define-module (math bessel))
     (export j0)
     
     (load-extension "libguile-bessel" "init_bessel")
     
     $ file /usr/local/lib/libguile-bessel.so
     ... ELF 32-bit LSB shared object ...
     $ guile
     guile> (use-modules (math bessel))
     guile> (j0 2)
     0.223890779141236

There is also a way to manipulate the module system from C but only Scheme files can be autoloaded. Thus, we recommend that you define your modules in Scheme.


Next: , Previous: Whirlwind Tour, Up: Introduction to Guile

2.4 Discouraged and Deprecated

From time to time functions and other features of Guile become obsolete. Guile has some mechanisms in place that can help you cope with this.

Guile has two levels of obsoleteness: things can be deprecated, meaning that their use is considered harmful and should be avoided, even in old code; or they can be merely discouraged, meaning that they are fine in and of themselves, but that there are better alternatives that should be used in new code.

When you use a feature that is deprecated, you will likely get a warning message at run-time. Also, deprecated features are not ready for production use: they might be very slow. When something is merely discouraged, it performs normally and you wont get any messages at run-time.

The primary source for information about just what things are discouraged or deprecated in a given release is the file NEWS. That file also documents what you should use instead of the obsoleted things.

The file README contains instructions on how to control the inclusion or removal of the deprecated and/or discouraged features from the public API of Guile, and how to control the warning messages for deprecated features.

The idea behind those mechanisms is that normally all deprecated and discouraged features are available, but that you can omit them on purpose to check whether your code still relies on them.


Previous: Discouraged and Deprecated, Up: Introduction to Guile

2.5 Reporting Bugs

Any problems with the installation should be reported to bug-guile@gnu.org.

Whenever you have found a bug in Guile you are encouraged to report it to the Guile developers, so they can fix it. They may also be able to suggest workarounds when it is not possible for you to apply the bug-fix or install a new version of Guile yourself.

Before sending in bug reports, please check with the following list that you really have found a bug.

When you write a bug report, please make sure to include as much of the information described below in the report. If you can't figure out some of the items, it is not a problem, but the more information we get, the more likely we can diagnose and fix the bug.


Next: , Previous: Introduction to Guile, Up: Top

3 Programming in Scheme

Guile's core language is Scheme, and an awful lot can be achieved simply by using Guile to write and run Scheme programs. In this part of the manual, we explain how to use Guile in this mode, and describe the tools that Guile provides to help you with script writing, debugging and packaging your programs for distribution.

For readers who are not yet familiar with the Scheme language, this part includes a chapter that presents the basic concepts of the language, and gives references to freely available Scheme tutorial material on the web.

For detailed reference information on the variables, functions etc. that make up Guile's application programming interface (API), See API Reference.


Next: , Up: Programming in Scheme

3.1 Basic Ideas in Scheme

In this chapter, we introduce the basic concepts that underpin the elegance and power of the Scheme language.

Readers who already possess a background knowledge of Scheme may happily skip this chapter. For the reader who is new to the language, however, the following discussions on data, procedures, expressions and closure are designed to provide a minimum level of Scheme understanding that is more or less assumed by the reference chapters that follow.

The style of this introductory material aims about halfway between the terse precision of R5RS and the discursive randomness of a Scheme tutorial.


Next: , Up: Basic Ideas

3.1.1 Data Types, Values and Variables

This section discusses the representation of data types and values, what it means for Scheme to be a latently typed language, and the role of variables. We conclude by introducing the Scheme syntaxes for defining a new variable, and for changing the value of an existing variable.


Next: , Up: About Data
3.1.1.1 Latent Typing

The term latent typing is used to describe a computer language, such as Scheme, for which you cannot, in general, simply look at a program's source code and determine what type of data will be associated with a particular variable, or with the result of a particular expression.

Sometimes, of course, you can tell from the code what the type of an expression will be. If you have a line in your program that sets the variable x to the numeric value 1, you can be certain that, immediately after that line has executed (and in the absence of multiple threads), x has the numeric value 1. Or if you write a procedure that is designed to concatenate two strings, it is likely that the rest of your application will always invoke this procedure with two string parameters, and quite probable that the procedure would go wrong in some way if it was ever invoked with parameters that were not both strings.

Nevertheless, the point is that there is nothing in Scheme which requires the procedure parameters always to be strings, or x always to hold a numeric value, and there is no way of declaring in your program that such constraints should always be obeyed. In the same vein, there is no way to declare the expected type of a procedure's return value.

Instead, the types of variables and expressions are only known – in general – at run time. If you need to check at some point that a value has the expected type, Scheme provides run time procedures that you can invoke to do so. But equally, it can be perfectly valid for two separate invocations of the same procedure to specify arguments with different types, and to return values with different types.

The next subsection explains what this means in practice, for the ways that Scheme programs use data types, values and variables.


Next: , Previous: Latent Typing, Up: About Data
3.1.1.2 Values and Variables

Scheme provides many data types that you can use to represent your data. Primitive types include characters, strings, numbers and procedures. Compound types, which allow a group of primitive and compound values to be stored together, include lists, pairs, vectors and multi-dimensional arrays. In addition, Guile allows applications to define their own data types, with the same status as the built-in standard Scheme types.

As a Scheme program runs, values of all types pop in and out of existence. Sometimes values are stored in variables, but more commonly they pass seamlessly from being the result of one computation to being one of the parameters for the next.

Consider an example. A string value is created because the interpreter reads in a literal string from your program's source code. Then a numeric value is created as the result of calculating the length of the string. A second numeric value is created by doubling the calculated length. Finally the program creates a list with two elements – the doubled length and the original string itself – and stores this list in a program variable.

All of the values involved here – in fact, all values in Scheme – carry their type with them. In other words, every value “knows,” at runtime, what kind of value it is. A number, a string, a list, whatever.

A variable, on the other hand, has no fixed type. A variable – x, say – is simply the name of a location – a box – in which you can store any kind of Scheme value. So the same variable in a program may hold a number at one moment, a list of procedures the next, and later a pair of strings. The “type” of a variable – insofar as the idea is meaningful at all – is simply the type of whatever value the variable happens to be storing at a particular moment.


Previous: Values and Variables, Up: About Data
3.1.1.3 Defining and Setting Variables

To define a new variable, you use Scheme's define syntax like this:

     (define variable-name value)

This makes a new variable called variable-name and stores value in it as the variable's initial value. For example:

     ;; Make a variable `x' with initial numeric value 1.
     (define x 1)
     
     ;; Make a variable `organization' with an initial string value.
     (define organization "Free Software Foundation")

(In Scheme, a semicolon marks the beginning of a comment that continues until the end of the line. So the lines beginning ;; are comments.)

Changing the value of an already existing variable is very similar, except that define is replaced by the Scheme syntax set!, like this:

     (set! variable-name new-value)

Remember that variables do not have fixed types, so new-value may have a completely different type from whatever was previously stored in the location named by variable-name. Both of the following examples are therefore correct.

     ;; Change the value of `x' to 5.
     (set! x 5)
     
     ;; Change the value of `organization' to the FSF's street number.
     (set! organization 545)

In these examples, value and new-value are literal numeric or string values. In general, however, value and new-value can be any Scheme expression. Even though we have not yet covered the forms that Scheme expressions can take (see About Expressions), you can probably guess what the following set! example does...

     (set! x (+ x 1))

(Note: this is not a complete description of define and set!, because we need to introduce some other aspects of Scheme before the missing pieces can be filled in. If, however, you are already familiar with the structure of Scheme, you may like to read about those missing pieces immediately by jumping ahead to the following references.


Next: , Previous: About Data, Up: Basic Ideas

3.1.2 The Representation and Use of Procedures

This section introduces the basics of using and creating Scheme procedures. It discusses the representation of procedures as just another kind of Scheme value, and shows how procedure invocation expressions are constructed. We then explain how lambda is used to create new procedures, and conclude by presenting the various shorthand forms of define that can be used instead of writing an explicit lambda expression.


Next: , Up: About Procedures
3.1.2.1 Procedures as Values

One of the great simplifications of Scheme is that a procedure is just another type of value, and that procedure values can be passed around and stored in variables in exactly the same way as, for example, strings and lists. When we talk about a built-in standard Scheme procedure such as open-input-file, what we actually mean is that there is a pre-defined top level variable called open-input-file, whose value is a procedure that implements what R5RS says that open-input-file should do.

Note that this is quite different from many dialects of Lisp — including Emacs Lisp — in which a program can use the same name with two quite separate meanings: one meaning identifies a Lisp function, while the other meaning identifies a Lisp variable, whose value need have nothing to do with the function that is associated with the first meaning. In these dialects, functions and variables are said to live in different namespaces.

In Scheme, on the other hand, all names belong to a single unified namespace, and the variables that these names identify can hold any kind of Scheme value, including procedure values.

One consequence of the “procedures as values” idea is that, if you don't happen to like the standard name for a Scheme procedure, you can change it.

For example, call-with-current-continuation is a very important standard Scheme procedure, but it also has a very long name! So, many programmers use the following definition to assign the same procedure value to the more convenient name call/cc.

     (define call/cc call-with-current-continuation)

Let's understand exactly how this works. The definition creates a new variable call/cc, and then sets its value to the value of the variable call-with-current-continuation; the latter value is a procedure that implements the behaviour that R5RS specifies under the name “call-with-current-continuation”. So call/cc ends up holding this value as well.

Now that call/cc holds the required procedure value, you could choose to use call-with-current-continuation for a completely different purpose, or just change its value so that you will get an error if you accidentally use call-with-current-continuation as a procedure in your program rather than call/cc. For example:

     (set! call-with-current-continuation "Not a procedure any more!")

Or you could just leave call-with-current-continuation as it was. It's perfectly fine for more than one variable to hold the same procedure value.


Next: , Previous: Procedures as Values, Up: About Procedures
3.1.2.2 Simple Procedure Invocation

A procedure invocation in Scheme is written like this:

     (procedure [arg1 [arg2 ...]])

In this expression, procedure can be any Scheme expression whose value is a procedure. Most commonly, however, procedure is simply the name of a variable whose value is a procedure.

For example, string-append is a standard Scheme procedure whose behaviour is to concatenate together all the arguments, which are expected to be strings, that it is given. So the expression

     (string-append "/home" "/" "andrew")

is a procedure invocation whose result is the string value "/home/andrew".

Similarly, string-length is a standard Scheme procedure that returns the length of a single string argument, so

     (string-length "abc")

is a procedure invocation whose result is the numeric value 3.

Each of the parameters in a procedure invocation can itself be any Scheme expression. Since a procedure invocation is itself a type of expression, we can put these two examples together to get

     (string-length (string-append "/home" "/" "andrew"))

— a procedure invocation whose result is the numeric value 12.

(You may be wondering what happens if the two examples are combined the other way round. If we do this, we can make a procedure invocation expression that is syntactically correct:

     (string-append "/home" (string-length "abc"))

but when this expression is executed, it will cause an error, because the result of (string-length "abc") is a numeric value, and string-append is not designed to accept a numeric value as one of its arguments.)


Next: , Previous: Simple Invocation, Up: About Procedures
3.1.2.3 Creating and Using a New Procedure

Scheme has lots of standard procedures, and Guile provides all of these via predefined top level variables. All of these standard procedures are documented in the later chapters of this reference manual.

Before very long, though, you will want to create new procedures that encapsulate aspects of your own applications' functionality. To do this, you can use the famous lambda syntax.

For example, the value of the following Scheme expression

     (lambda (name address) expression ...)

is a newly created procedure that takes two arguments: name and address. The behaviour of the new procedure is determined by the sequence of expressions in the body of the procedure definition. (Typically, these expressions would use the arguments in some way, or else there wouldn't be any point in giving them to the procedure.) When invoked, the new procedure returns a value that is the value of the last expression in the procedure body.

To make things more concrete, let's suppose that the two arguments are both strings, and that the purpose of this procedure is to form a combined string that includes these arguments. Then the full lambda expression might look like this:

     (lambda (name address)
       (string-append "Name=" name ":Address=" address))

We noted in the previous subsection that the procedure part of a procedure invocation expression can be any Scheme expression whose value is a procedure. But that's exactly what a lambda expression is! So we can use a lambda expression directly in a procedure invocation, like this:

     ((lambda (name address)
        (string-append "Name=" name ":Address=" address))
      "FSF"
      "Cambridge")

This is a valid procedure invocation expression, and its result is the string "Name=FSF:Address=Cambridge".

It is more common, though, to store the procedure value in a variable —

     (define make-combined-string
       (lambda (name address)
         (string-append "Name=" name ":Address=" address)))

— and then to use the variable name in the procedure invocation:

     (make-combined-string "FSF" "Cambridge")

Which has exactly the same result.

It's important to note that procedures created using lambda have exactly the same status as the standard built in Scheme procedures, and can be invoked, passed around, and stored in variables in exactly the same ways.


Previous: Creating a Procedure, Up: About Procedures
3.1.2.4 Lambda Alternatives

Since it is so common in Scheme programs to want to create a procedure and then store it in a variable, there is an alternative form of the define syntax that allows you to do just that.

A define expression of the form

     (define (name [arg1 [arg2 ...]])
       expression ...)

is exactly equivalent to the longer form

     (define name
       (lambda ([arg1 [arg2 ...]])
         expression ...))

So, for example, the definition of make-combined-string in the previous subsection could equally be written:

     (define (make-combined-string name address)
       (string-append "Name=" name ":Address=" address))

This kind of procedure definition creates a procedure that requires exactly the expected number of arguments. There are two further forms of the lambda expression, which create a procedure that can accept a variable number of arguments:

     (lambda (arg1 ... . args) expression ...)
     
     (lambda args expression ...)

The corresponding forms of the alternative define syntax are:

     (define (name arg1 ... . args) expression ...)
     
     (define (name . args) expression ...)

For details on how these forms work, see See Lambda.

(It could be argued that the alternative define forms are rather confusing, especially for newcomers to the Scheme language, as they hide both the role of lambda and the fact that procedures are values that are stored in variables in the some way as any other kind of value. On the other hand, they are very convenient, and they are also a good example of another of Scheme's powerful features: the ability to specify arbitrary syntactic transformations at run time, which can be applied to subsequently read input.)


Next: , Previous: About Procedures, Up: Basic Ideas

3.1.3 Expressions and Evaluation

So far, we have met expressions that do things, such as the define expressions that create and initialize new variables, and we have also talked about expressions that have values, for example the value of the procedure invocation expression:

     (string-append "/home" "/" "andrew")

but we haven't yet been precise about what causes an expression like this procedure invocation to be reduced to its “value”, or how the processing of such expressions relates to the execution of a Scheme program as a whole.

This section clarifies what we mean by an expression's value, by introducing the idea of evaluation. It discusses the side effects that evaluation can have, explains how each of the various types of Scheme expression is evaluated, and describes the behaviour and use of the Guile REPL as a mechanism for exploring evaluation. The section concludes with a very brief summary of Scheme's common syntactic expressions.


Next: , Up: About Expressions
3.1.3.1 Evaluating Expressions and Executing Programs

In Scheme, the process of executing an expression is known as evaluation. Evaluation has two kinds of result:

Of the expressions that we have met so far, define and set! expressions have side effects — the creation or modification of a variable — but no value; lambda expressions have values — the newly constructed procedures — but no side effects; and procedure invocation expressions, in general, have either values, or side effects, or both.

It is tempting to try to define more intuitively what we mean by “value” and “side effects”, and what the difference between them is. In general, though, this is extremely difficult. It is also unnecessary; instead, we can quite happily define the behaviour of a Scheme program by specifying how Scheme executes a program as a whole, and then by describing the value and side effects of evaluation for each type of expression individually.

So, some1 definitions...

The following subsections describe how each of these types of expression is evaluated.

Evaluating Literal Data

When a literal data expression is evaluated, the value of the expression is simply the value that the expression describes. The evaluation of a literal data expression has no side effects.

So, for example,

For any data type which can be expressed literally like this, the syntax of the literal data expression for that data type — in other words, what you need to write in your code to indicate a literal value of that type — is known as the data type's read syntax. This manual specifies the read syntax for each such data type in the section that describes that data type.

Some data types do not have a read syntax. Procedures, for example, cannot be expressed as literal data; they must be created using a lambda expression (see Creating a Procedure) or implicitly using the shorthand form of define (see Lambda Alternatives).

Evaluating a Variable Reference

When an expression that consists simply of a variable name is evaluated, the value of the expression is the value of the named variable. The evaluation of a variable reference expression has no side effects.

So, after

     (define key "Paul Evans")

the value of the expression key is the string value "Paul Evans". If key is then modified by

     (set! key 3.74)

the value of the expression key is the numeric value 3.74.

If there is no variable with the specified name, evaluation of the variable reference expression signals an error.

Evaluating a Procedure Invocation Expression

This is where evaluation starts getting interesting! As already noted, a procedure invocation expression has the form

     (procedure [arg1 [arg2 ...]])

where procedure must be an expression whose value, when evaluated, is a procedure.

The evaluation of a procedure invocation expression like this proceeds by

For a procedure defined in Scheme, “calling the procedure with the list of values as its parameters” means binding the values to the procedure's formal parameters and then evaluating the sequence of expressions that make up the body of the procedure definition. The value of the procedure invocation expression is the value of the last evaluated expression in the procedure body. The side effects of calling the procedure are the combination of the side effects of the sequence of evaluations of expressions in the procedure body.

For a built-in procedure, the value and side-effects of calling the procedure are best described by that procedure's documentation.

Note that the complete side effects of evaluating a procedure invocation expression consist not only of the side effects of the procedure call, but also of any side effects of the preceding evaluation of the expressions procedure, arg1, arg2, and so on.

To illustrate this, let's look again at the procedure invocation expression:

     (string-length (string-append "/home" "/" "andrew"))

In the outermost expression, procedure is string-length and arg1 is (string-append "/home" "/" "andrew").

In the evaluation of the outermost expression, the interpreter can now invoke the procedure value obtained from procedure with the value obtained from arg1 as its arguments. The resulting value is a numeric value that is the length of the argument string, which is 12.

Evaluating Special Syntactic Expressions

When a procedure invocation expression is evaluated, the procedure and all the argument expressions must be evaluated before the procedure can be invoked. Special syntactic expressions are special because they are able to manipulate their arguments in an unevaluated form, and can choose whether to evaluate any or all of the argument expressions.

Why is this needed? Consider a program fragment that asks the user whether or not to delete a file, and then deletes the file if the user answers yes.

     (if (string=? (read-answer "Should I delete this file?")
                   "yes")
         (delete-file file))

If the outermost (if ...) expression here was a procedure invocation expression, the expression (delete-file file), whose side effect is to actually delete a file, would already have been evaluated before the if procedure even got invoked! Clearly this is no use — the whole point of an if expression is that the consequent expression is only evaluated if the condition of the if expression is “true”.

Therefore if must be special syntax, not a procedure. Other special syntaxes that we have already met are define, set! and lambda. define and set! are syntax because they need to know the variable name that is given as the first argument in a define or set! expression, not that variable's value. lambda is syntax because it does not immediately evaluate the expressions that define the procedure body; instead it creates a procedure object that incorporates these expressions so that they can be evaluated in the future, when that procedure is invoked.

The rules for evaluating each special syntactic expression are specified individually for each special syntax. For a summary of standard special syntax, see See Syntax Summary.


Next: , Previous: Evaluating, Up: About Expressions
3.1.3.2 Tail calls

Scheme is “properly tail recursive”, meaning that tail calls or recursions from certain contexts do not consume stack space or other resources and can therefore be used on arbitrarily large data or for an arbitrarily long calculation. Consider for example,

     (define (foo n)
       (display n)
       (newline)
       (foo (1+ n)))
     
     (foo 1)
     -|
     1
     2
     3
     ...

foo prints numbers infinitely, starting from the given n. It's implemented by printing n then recursing to itself to print n+1 and so on. This recursion is a tail call, it's the last thing done, and in Scheme such tail calls can be made without limit.

Or consider a case where a value is returned, a version of the SRFI-1 last function (see SRFI-1 Selectors) returning the last element of a list,

     (define (my-last lst)
       (if (null? (cdr lst))
           (car lst)
           (my-last (cdr lst))))
     
     (my-last '(1 2 3))  3

If the list has more than one element, my-last applies itself to the cdr. This recursion is a tail call, there's no code after it, and the return value is the return value from that call. In Scheme this can be used on an arbitrarily long list argument.


A proper tail call is only available from certain contexts, namely the following special form positions,

The following core functions make tail calls,


The above are just core functions and special forms. Tail calls in other modules are described with the relevant documentation, for example SRFI-1 any and every (see SRFI-1 Searching).

It will be noted there are a lot of places which could potentially be tail calls, for instance the last call in a for-each, but only those explicitly described are guaranteed.


Next: , Previous: Tail Calls, Up: About Expressions
3.1.3.3 Using the Guile REPL

If you start Guile without specifying a particular program for it to execute, Guile enters its standard Read Evaluate Print Loop — or REPL for short. In this mode, Guile repeatedly reads in the next Scheme expression that the user types, evaluates it, and prints the resulting value.

The REPL is a useful mechanism for exploring the evaluation behaviour described in the previous subsection. If you type string-append, for example, the REPL replies #<primitive-procedure string-append>, illustrating the relationship between the variable string-append and the procedure value stored in that variable.

In this manual, the notation is used to mean “evaluates to”. Wherever you see an example of the form

     expression
     
     result

feel free to try it out yourself by typing expression into the REPL and checking that it gives the expected result.


Previous: The REPL, Up: About Expressions
3.1.3.4 Summary of Common Syntax

This subsection lists the most commonly used Scheme syntactic expressions, simply so that you will recognize common special syntax when you see it. For a full description of each of these syntaxes, follow the appropriate reference.

lambda (see Lambda) is used to construct procedure objects.

define (see Top Level) is used to create a new variable and set its initial value.

set! (see Top Level) is used to modify an existing variable's value.

let, let* and letrec (see Local Bindings) create an inner lexical environment for the evaluation of a sequence of expressions, in which a specified set of local variables is bound to the values of a corresponding set of expressions. For an introduction to environments, see See About Closure.

begin (see begin) executes a sequence of expressions in order and returns the value of the last expression. Note that this is not the same as a procedure which returns its last argument, because the evaluation of a procedure invocation expression does not guarantee to evaluate the arguments in order.

if and cond (see if cond case) provide conditional evaluation of argument expressions depending on whether one or more conditions evaluate to “true” or “false”.

case (see if cond case) provides conditional evaluation of argument expressions depending on whether a variable has one of a specified group of values.

and (see and or) executes a sequence of expressions in order until either there are no expressions left, or one of them evaluates to “false”.

or (see and or) executes a sequence of expressions in order until either there are no expressions left, or one of them evaluates to “true”.


Previous: About Expressions, Up: Basic Ideas

3.1.4 The Concept of Closure

The concept of closure is the idea that a lambda expression “captures” the variable bindings that are in lexical scope at the point where the lambda expression occurs. The procedure created by the lambda expression can refer to and mutate the captured bindings, and the values of those bindings persist between procedure calls.

This section explains and explores the various parts of this idea in more detail.


Next: , Up: About Closure
3.1.4.1 Names, Locations, Values and Environments

We said earlier that a variable name in a Scheme program is associated with a location in which any kind of Scheme value may be stored. (Incidentally, the term “vcell” is often used in Lisp and Scheme circles as an alternative to “location”.) Thus part of what we mean when we talk about “creating a variable” is in fact establishing an association between a name, or identifier, that is used by the Scheme program code, and the variable location to which that name refers. Although the value that is stored in that location may change, the location to which a given name refers is always the same.

We can illustrate this by breaking down the operation of the define syntax into three parts: define

A collection of associations between names and locations is called an environment. When you create a top level variable in a program using define, the name-location association for that variable is added to the “top level” environment. The “top level” environment also includes name-location associations for all the procedures that are supplied by standard Scheme.

It is also possible to create environments other than the top level one, and to create variable bindings, or name-location associations, in those environments. This ability is a key ingredient in the concept of closure; the next subsection shows how it is done.


Next: , Previous: About Environments, Up: About Closure
3.1.4.2 Local Variables and Environments

We have seen how to create top level variables using the define syntax (see Definition). It is often useful to create variables that are more limited in their scope, typically as part of a procedure body. In Scheme, this is done using the let syntax, or one of its modified forms let* and letrec. These syntaxes are described in full later in the manual (see Local Bindings). Here our purpose is to illustrate their use just enough that we can see how local variables work.

For example, the following code uses a local variable s to simplify the computation of the area of a triangle given the lengths of its three sides.

     (define a 5.3)
     (define b 4.7)
     (define c 2.8)
     
     (define area
       (let ((s (/ (+ a b c) 2)))
         (sqrt (* s (- s a) (- s b) (- s c)))))

The effect of the let expression is to create a new environment and, within this environment, an association between the name s and a new location whose initial value is obtained by evaluating (/ (+ a b c) 2). The expressions in the body of the let, namely (sqrt (* s (- s a) (- s b) (- s c))), are then evaluated in the context of the new environment, and the value of the last expression evaluated becomes the value of the whole let expression, and therefore the value of the variable area.


Next: , Previous: Local Variables, Up: About Closure
3.1.4.3 Environment Chaining

In the example of the previous subsection, we glossed over an important point. The body of the let expression in that example refers not only to the local variable s, but also to the top level variables a, b, c and sqrt. (sqrt is the standard Scheme procedure for calculating a square root.) If the body of the let expression is evaluated in the context of the local let environment, how does the evaluation get at the values of these top level variables?

The answer is that the local environment created by a let expression automatically has a reference to its containing environment — in this case the top level environment — and that the Scheme interpreter automatically looks for a variable binding in the containing environment if it doesn't find one in the local environment. More generally, every environment except for the top level one has a reference to its containing environment, and the interpreter keeps searching back up the chain of environments — from most local to top level — until it either finds a variable binding for the required identifier or exhausts the chain.

This description also determines what happens when there is more than one variable binding with the same name. Suppose, continuing the example of the previous subsection, that there was also a pre-existing top level variable s created by the expression:

     (define s "Some beans, my lord!")

Then both the top level environment and the local let environment would contain bindings for the name s. When evaluating code within the let body, the interpreter looks first in the local let environment, and so finds the binding for s created by the let syntax. Even though this environment has