From 92905faf2c34bf86e3b45d72d7b16a16ec4948f5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Grabm=C3=BCller?= Date: Wed, 23 May 2001 17:24:50 +0000 Subject: [PATCH] * guile.texi: Commented out menu entry and inclusion of Tcl/Tk stuff. * indices.texi: Users are advised to look under C and Scheme names, xref to transformation rules added. * intro.texi, scheme-modules.texi, scheme-ideas.texi, scheme-evaluation.texi, scheme-data.texi, scheme-procedures.texi: Fixed most REFFIXMEs. * srfi-modules.texi (About SRFI Usage): New node. (SRFI-0): Extended. Fixed all REFFIXMEs. --- doc/ChangeLog | 16 + doc/guile.texi | 6 +- doc/indices.texi | 28 +- doc/intro.texi | 4 +- doc/scheme-data.texi | 18 +- doc/scheme-evaluation.texi | 12 +- doc/scheme-ideas.texi | 1458 ------------------------------------ doc/scheme-modules.texi | 20 +- doc/scheme-procedures.texi | 779 ------------------- doc/srfi-modules.texi | 98 ++- 10 files changed, 151 insertions(+), 2288 deletions(-) rewrite doc/scheme-ideas.texi (100%) rewrite doc/scheme-procedures.texi (100%) diff --git a/doc/ChangeLog b/doc/ChangeLog index cff21ad5c..32522fff9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,19 @@ +2001-05-23 Martin Grabmueller + + * guile.texi: Commented out menu entry and inclusion of Tcl/Tk + stuff. + + * indices.texi: Users are advised to look under C and Scheme + names, xref to transformation rules added. + + * intro.texi, scheme-modules.texi, scheme-ideas.texi, + scheme-evaluation.texi, scheme-data.texi, scheme-procedures.texi: + Fixed most REFFIXMEs. + + * srfi-modules.texi (About SRFI Usage): New node. + (SRFI-0): Extended. + Fixed all REFFIXMEs. + 2001-05-19 Neil Jerram * posix.texi (Networking): Split existing material into new nodes diff --git a/doc/guile.texi b/doc/guile.texi index 633b2b03a..29da7b221 100644 --- a/doc/guile.texi +++ b/doc/guile.texi @@ -80,7 +80,7 @@ by the Free Software Foundation. @sp 10 @comment The title is printed in a large font. @title Guile Reference Manual -@subtitle $Id: guile.texi,v 1.9 2001-05-14 21:37:51 mgrabmue Exp $ +@subtitle $Id: guile.texi,v 1.10 2001-05-23 17:24:49 mgrabmue Exp $ @subtitle For use with Guile @value{VERSION} @include AUTHORS @@ -177,7 +177,7 @@ Part III: Guile Modules add-on, so maybe it shouldn't be documented here (though it is nice to have a link from here to the Guile-scsh manual, if one exists). -* Tcl/Tk Interface:: +@c * Tcl/Tk Interface:: Part IV: Guile Scripting @@ -255,7 +255,7 @@ Indices @include repl-modules.texi @include expect.texi @include scsh.texi -@include tcltk.texi +@c @include tcltk.texi @c Guile as an scripting language @iftex diff --git a/doc/indices.texi b/doc/indices.texi index 69760b0bb..47b8d4cc2 100644 --- a/doc/indices.texi +++ b/doc/indices.texi @@ -1,22 +1,40 @@ @node Concept Index @unnumbered Concept Index + +This index contains concepts, keywords and non-Schemey names for several +features, to make it easier to locate the desired sections. + @printindex cp @node Procedure Index @unnumbered Procedure Index + +@c FIXME::martin: Review me! + This is an alphabetical list of all the procedures and macros in Guile. -[[Remind people to look for functions under their Scheme names as well -as their C names.]] + +When looking for a particular procedure, please look under its Scheme +name as well as under its C name. The C name can be constructed from +the Scheme names by a simple transformation described in the section +@xref{Transforming Scheme name to C name}. + @printindex fn @node Variable Index @unnumbered Variable Index + +@c FIXME::martin: Review me! + This is an alphabetical list of all the important variables and constants in Guile. -[[Remind people to look for variables under their Scheme names as well -as their C names.]] + +When looking for a particular variable or constant, please look under +its Scheme name as well as under its C name. The C name can be +constructed from the Scheme names by a simple transformation described +in the section @xref{Transforming Scheme name to C name}. + @printindex vr @@ -25,7 +43,9 @@ as their C names.]] @c spurious makeinfo errors. @node Type Index @unnumbered Type Index + This is an alphabetical list of all the important data types defined in the Guile Programmers Manual. + @printindex tp diff --git a/doc/intro.texi b/doc/intro.texi index 5c24c3aa3..f12c3c980 100644 --- a/doc/intro.texi +++ b/doc/intro.texi @@ -1,4 +1,4 @@ -@c $Id: intro.texi,v 1.9 2001-05-16 18:08:12 mgrabmue Exp $ +@c $Id: intro.texi,v 1.10 2001-05-23 17:24:49 mgrabmue Exp $ @page @node What is Guile? @@ -686,7 +686,7 @@ usual for your operating system, and it will additionally look into the directories listed in the @code{LTDL_LIBRRAY_PATH} environment variable. To see how these Guile extensions via shared libraries relate to the -module system, see below REFFIXME. +module system, see below @xref{Intro to Modules and Extensions}. @node Guile Modules @section Guile Modules diff --git a/doc/scheme-data.texi b/doc/scheme-data.texi index b5b3bb619..7f283f446 100755 --- a/doc/scheme-data.texi +++ b/doc/scheme-data.texi @@ -1614,9 +1614,10 @@ y @subsection String Comparison The procedures in this section are similar to the character ordering -predicates (REFFIXME), but are defined on character sequences. They all -return @code{#t} on success and @code{#f} on failure. The predicates -ending in @code{-ci} ignore the character case when comparing strings. +predicates (@pxref{Characters}), but are defined on character sequences. +They all return @code{#t} on success and @code{#f} on failure. The +predicates ending in @code{-ci} ignore the character case when comparing +strings. @rnindex string=? @@ -2536,7 +2537,7 @@ one of the constructor procedures @code{make-variable} or @code{make-undefined-variable} or retrieved by @code{builtin-variable}. First-class variables are especially useful for interacting with the -current module system (REFFIXME). +current module system (@pxref{The Guile module system}). @deffn primitive builtin-variable name Return the built-in variable with the name @var{name}. @@ -2967,7 +2968,7 @@ up a list. An example will clear that up: This example also shows that lists have to be quoted (REFFIXME) when written, because they would otherwise be mistakingly taken as procedure -applications (REFFIXME). +applications (@pxref{Simple Invocation}). @node List Predicates @@ -3028,7 +3029,7 @@ that modifying the elements of the new list also modyfies the elements of the old list. On the other hand, applying procedures like @code{set-cdr!} or @code{delv!} to the new list will not alter the old list. If you also need to copy the list elements (making a deep copy), -use the procedure @code{copy-tree} (REFFIXME). +use the procedure @code{copy-tree} (@pxref{Copying}). @node List Selection @subsection List Selection @@ -4896,8 +4897,9 @@ elements of @var{vector}. @subsection Vector Modification -A vector created by any of the vector constructor procedures (REFFIXME) -documented above can be modified using the following procedures. +A vector created by any of the vector constructor procedures +(@pxref{Vectors}) documented above can be modified using the +following procedures. According to R5RS, using any of these procedures on literally entered vectors is an error, because these vectors are considered to be diff --git a/doc/scheme-evaluation.texi b/doc/scheme-evaluation.texi index d3edc523f..d3b3f6eea 100644 --- a/doc/scheme-evaluation.texi +++ b/doc/scheme-evaluation.texi @@ -72,10 +72,10 @@ another comment type for multiline comments, called @dfn{block comments}. This type of comment begins with the character sequence @code{#!} and ends with the characters @code{!#}, which must appear on a line of their own. These comments are compatible with the block -comments in the Scheme Shell @file{scsh} (REFFIXME). The characters -@code{#!} were chosen because they are the magic characters used in -shell scripts for indicating that the name of the program for executing -the script follows on the same line. +comments in the Scheme Shell @file{scsh} (@pxref{The Scheme shell +(scsh)}). The characters @code{#!} were chosen because they are the +magic characters used in shell scripts for indicating that the name of +the program for executing the script follows on the same line. Thus a Guile script often starts like this. @@ -85,7 +85,7 @@ Thus a Guile script often starts like this. @end lisp More details on Guile scripting can be found in the scripting section -(REFFIXME). +(@pxref{Guile Scripting}). @node Case Sensitivity @@ -105,7 +105,7 @@ are the same in R5RS Scheme, but are different in Guile. It is possible to turn off case sensitivity in Guile by setting the reader option @code{case-insensitive}. More on reader options can be -found at (REFFIXME). +found at (@pxref{Reader options}). @lisp (read-enable 'case-insensitive) diff --git a/doc/scheme-ideas.texi b/doc/scheme-ideas.texi dissimilarity index 100% index 6db8ce219..e69de29bb 100644 --- a/doc/scheme-ideas.texi +++ b/doc/scheme-ideas.texi @@ -1,1458 +0,0 @@ -@page -@node Basic Ideas -@chapter 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. - -@menu -* About Data:: Latent typing, types, values and variables. -* About Procedures:: The representation and use of procedures. -* About Expressions:: All kinds of expressions and their meaning. -* About Closure:: Closure, scoping and environments. -@end menu - - -@node About Data -@section Data Types, Values and Variables - -This section discusses the representation of data types and values, what -it means for Scheme to be a @dfn{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. - -@menu -* Latent Typing:: Scheme as a "latently typed" language. -* Values and Variables:: About data types, values and variables. -* Definition:: Defining variables and setting their values. -@end menu - - -@node Latent Typing -@subsection Latent Typing - -The term @dfn{latent typing} is used to descibe a computer language, -such as Scheme, for which you cannot, @emph{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 @emph{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 @code{x} to the numeric value 1, you can be certain that, -immediately after that line has executed (and in the absence of multiple -threads), @code{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 @code{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 @emph{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. - - -@node Values and Variables -@subsection 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 -- -@code{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. - - -@node Definition -@subsection Defining and Setting Variables - -To define a new variable, you use Scheme's @code{define} syntax like -this: - -@lisp -(define @var{variable-name} @var{value}) -@end lisp - -This makes a new variable called @var{variable-name} and stores -@var{value} in it as the variable's initial value. For example: - -@lisp -;; 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") -@end lisp - -(In Scheme, a semicolon marks the beginning of a comment that continues -until the end of the line. So the lines beginning @code{;;} are -comments.) - -Changing the value of an already existing variable is very similar, -except that @code{define} is replaced by the Scheme syntax @code{set!}, -like this: - -@lisp -(set! @var{variable-name} @var{new-value}) -@end lisp - -Remember that variables do not have fixed types, so @var{new-value} may -have a completely different type from whatever was previously stored in -the location named by @var{variable-name}. Both of the following -examples are therefore correct. - -@lisp -;; Change the value of `x' to 5. -(set! x 5) - -;; Change the value of `organization' to the FSF's street number. -(set! organization 545) -@end lisp - -In these examples, @var{value} and @var{new-value} are literal numeric -or string values. In general, however, @var{value} and @var{new-value} -can be any Scheme expression. Even though we have not yet covered the -forms that Scheme expressions can take (@pxref{About Expressions}), you -can probably guess what the following @code{set!} example does@dots{} - -@lisp -(set! x (+ x 1)) -@end lisp - -(Note: this is not a complete description of @code{define} and -@code{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. - -@itemize @bullet -@item -REFFIXME, to read about using @code{define} other than at top level in a -Scheme program, including a discussion of when it works to use -@code{define} rather than @code{set!} to change the value of an existing -variable. - -@item -@ref{Lambda Alternatives}, to read about an alternative form of the -@code{define} syntax that can be used when defining new procedures. - -@item -REFFIXME, to read about an alternative form of the @code{set!} syntax -that helps with changing a single value in the depths of a compound data -structure.) -@end itemize - - -@node About Procedures -@section 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 @code{lambda} is used -to create new procedures, and conclude by presenting the various -shorthand forms of @code{define} that can be used instead of writing an -explicit @code{lambda} expression. - -@menu -* Procedures as Values:: Procedures are values like everything else. -* Simple Invocation:: How to write a simple procedure invocation. -* Creating a Procedure:: How to create your own procedures. -* Lambda Alternatives:: Other ways of writing procedure definitions. -@end menu - - -@node Procedures as Values -@subsection 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 @code{open-input-file}, what we actually mean is that there is a -pre-defined top level variable called @code{open-input-file}, whose -value is a procedure that implements what R5RS says that -@code{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 @dfn{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, @code{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 @code{call/cc}. - -@lisp -(define call/cc call-with-current-continuation) -@end lisp - -Let's understand exactly how this works. The definition creates a new -variable @code{call/cc}, and then sets its value to the value of the -variable @code{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 @code{call/cc} ends up -holding this value as well. - -Now that @code{call/cc} holds the required procedure value, you could -choose to use @code{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 @code{call-with-current-continuation} as a -procedure in your program rather than @code{call/cc}. For example: - -@lisp -(set! call-with-current-continuation "Not a procedure any more!") -@end lisp - -Or you could just leave @code{call-with-current-continuation} as it was. -It's perfectly fine for more than one variable to hold the same -procedure value. - - -@node Simple Invocation -@subsection Simple Procedure Invocation - -A procedure invocation in Scheme is written like this: - -@lisp -(@var{procedure} [@var{arg1} [@var{arg2} @dots{}]]) -@end lisp - -In this expression, @var{procedure} can be any Scheme expression whose -value is a procedure. Most commonly, however, @var{procedure} is simply -the name of a variable whose value is a procedure. - -For example, @code{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 - -@lisp -(string-append "/home" "/" "andrew") -@end lisp - -@noindent -is a procedure invocation whose result is the string value -@code{"/home/andrew"}. - -Similarly, @code{string-length} is a standard Scheme procedure that -returns the length of a single string argument, so - -@lisp -(string-length "abc") -@end lisp - -@noindent -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 - -@lisp -(string-length (string-append "/home" "/" "andrew")) -@end lisp - -@noindent ---- 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 @emph{syntactically} correct: - -@lisp -(string-append "/home" (string-length "abc")) -@end lisp - -@noindent -but when this expression is executed, it will cause an error, because -the result of @code{(string-length "abc")} is a numeric value, and -@code{string-append} is not designed to accept a numeric value as one of -its arguments.) - - -@node Creating a Procedure -@subsection 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 @code{lambda} syntax. - -For example, the value of the following Scheme expression - -@lisp -(lambda (name address) @var{expression} @dots{}) -@end lisp - -@noindent -is a newly created procedure that takes two arguments: -@code{name} and @code{address}. The behaviour of the -new procedure is determined by the sequence of @var{expression}s in the -@dfn{body} of the procedure definition. (Typically, these -@var{expression}s 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 -@var{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: - -@lisp -(lambda (name address) - (string-append "Name=" name ":Address=" address)) -@end lisp - -We noted in the previous subsection that the @var{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: - -@lisp -((lambda (name address) - (string-append "Name=" name ":Address=" address)) - "FSF" - "Cambridge") -@end lisp - -@noindent -This is a valid procedure invocation expression, whose result is the -string @code{"Name=FSF:Address=Cambridge"}. - -It it more common, though, to store the procedure value in a variable --- - -@lisp -(define make-combined-string - (lambda (name address) - (string-append "Name=" name ":Address=" address))) -@end lisp - -@noindent ---- and then to use the variable name in the procedure invocation: - -@lisp -(make-combined-string "FSF" "Cambridge") -@end lisp - -@noindent -Which has exactly the same result. - -It's important to note that procedures created using @code{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. - - -@node Lambda Alternatives -@subsection 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 -@code{define} syntax that allows you to do just that. - -A @code{define} expression of the form - -@lisp -(define (@var{name} [@var{arg1} [@var{arg2} @dots{}]]) - @var{expression} @dots{}) -@end lisp - -@noindent -is exactly equivalent to the longer form - -@lisp -(define @var{name} - (lambda ([@var{arg1} [@var{arg2} @dots{}]]) - @var{expression} @dots{})) -@end lisp - -So, for example, the definition of @code{make-combined-string} in the -previous subsection could equally be written: - -@lisp -(define (make-combined-string name address) - (string-append "Name=" name ":Address=" address)) -@end lisp - -This kind of procedure definition creates a procedure that requires -exactly the expected number of arguments. There are two further forms -of the @code{lambda} expression, which create a procedure that can -accept a variable number of arguments: - -@lisp -(lambda (@var{arg1} @dots{} . @var{args}) @var{expression} @dots{}) - -(lambda @var{args} @var{expression} @dots{}) -@end lisp - -@noindent -The corresponding forms of the alternative @code{define} syntax are: - -@lisp -(define (@var{name} @var{arg1} @dots{} . @var{args}) @var{expression} @dots{}) - -(define (@var{name} . @var{args}) @var{expression} @dots{}) -@end lisp - -@noindent -For details on how these forms work, see @xref{Lambda}. - -(It could be argued that the alternative @code{define} forms are rather -confusing, especially for newcomers to the Scheme language, as they hide -both the role of @code{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.) - - -@node About Expressions -@section Expressions and Evaluation - -So far, we have met expressions that @emph{do} things, such as the -@code{define} expressions that create and initialize new variables, and -we have also talked about expressions that have @emph{values}, for -example the value of the procedure invocation expression: - -@lisp -(string-append "/home" "/" "andrew") -@end lisp - -@noindent -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 @dfn{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. - -@menu -* Evaluating:: How a Scheme program is executed. -* The REPL:: Interacting with the Guile interpreter. -* Syntax Summary:: Common syntactic expressions -- in brief. -@end menu - - -@node Evaluating -@subsection Evaluating Expressions and Executing Programs - -In Scheme, the process of executing an expression is known as -@dfn{evaluation}. Evaluation has two kinds of result: - -@itemize @bullet -@item -the @dfn{value} of the evaluated expression - -@item -the @dfn{side effects} of the evaluation, which consist of any effects of -evaluating the expression that are not represented by the value. -@end itemize - -Of the expressions that we have met so far, @code{define} and -@code{set!} expressions have side effects --- the creation or -modification of a variable --- but no value; @code{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. - -@noindent -So, some@footnote{These definitions are approximate. For the whole and -detailed truth, see @xref{Formal syntax and semantics,R5RS -syntax,,r5rs}.} definitions@dots{} - -@itemize @bullet - -@item -A Scheme program consists of a sequence of expressions. - -@item -A Scheme interpreter executes the program by evaluating these -expressions in order, one by one. - -@item -An expression can be - -@itemize @bullet -@item -a piece of literal data, such as a number @code{2.3} or a string -@code{"Hello world!"} -@item -a variable name -@item -a procedure invocation expression -@item -one of Scheme's special syntactic expressions. -@end itemize -@end itemize - -@noindent -The following subsections describe how each of these types of expression -is evaluated. - -@menu -* Eval Literal:: Evaluating literal data. -* Eval Variable:: Evaluating variable references. -* Eval Procedure:: Evaluating procedure invocation expressions. -* Eval Special:: Evaluating special syntactic expressions. -@end menu - -@node Eval Literal -@subsubsection 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. - -@noindent -So, for example, - -@itemize @bullet -@item -the value of the expression @code{"abc"} is the string value -@code{"abc"} - -@item -the value of the expression @code{3+4i} is the complex number 3 + 4i - -@item -the value of the expression @code{#(1 2 3)} is a three-element vector -containing the numeric values 1, 2 and 3. -@end itemize - -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 @dfn{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 -@code{lambda} expression (@pxref{Creating a Procedure}) or implicitly -using the shorthand form of @code{define} (@pxref{Lambda Alternatives}). - - -@node Eval Variable -@subsubsection 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 - -@lisp -(define key "Paul Evans") -@end lisp - -@noindent -the value of the expression @code{key} is the string value @code{"Paul -Evans"}. If @var{key} is then modified by - -@lisp -(set! key 3.74) -@end lisp - -@noindent -the value of the expression @code{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. - - -@node Eval Procedure -@subsubsection Evaluating a Procedure Invocation Expression - -This is where evaluation starts getting interesting! As already noted, -a procedure invocation expression has the form - -@lisp -(@var{procedure} [@var{arg1} [@var{arg2} @dots{}]]) -@end lisp - -@noindent -where @var{procedure} must be an expression whose value, when evaluated, -is a procedure. - -The evaluation of a procedure invocation expression like this proceeds -by - -@itemize @bullet -@item -evaluating individually the expressions @var{procedure}, @var{arg1}, -@var{arg2}, and so on - -@item -calling the procedure that is the value of the @var{procedure} -expression with the list of values obtained from the evaluations of -@var{arg1}, @var{arg2} etc. as its parameters. -@end itemize - -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 @var{procedure}, @var{arg1}, @var{arg2}, and so on. - -To illustrate this, let's look again at the procedure invocation -expression: - -@lisp -(string-length (string-append "/home" "/" "andrew")) -@end lisp - -In the outermost expression, @var{procedure} is @code{string-length} and -@var{arg1} is @code{(string-append "/home" "/" "andrew")}. - -@itemize @bullet -@item -Evaluation of @code{string-length}, which is a variable, gives a -procedure value that implements the expected behaviour for -``string-length''. - -@item -Evaluation of @code{(string-append "/home" "/" "andrew")}, which is -another procedure invocation expression, means evaluating each of - -@itemize @bullet -@item -@code{string-append}, which gives a procedure value that implements the -expected behaviour for ``string-append'' - -@item -@code{"/home"}, which gives the string value @code{"/home"} - -@item -@code{"/"}, which gives the string value @code{"/"} - -@item -@code{"andrew"}, which gives the string value @code{"andrew"} -@end itemize - -and then invoking the procedure value with this list of string values as -its arguments. The resulting value is a single string value that is the -concatenation of all the arguments, namely @code{"/home/andrew"}. -@end itemize - -In the evaluation of the outermost expression, the interpreter can now -invoke the procedure value obtained from @var{procedure} with the value -obtained from @var{arg1} as its arguments. The resulting value is a -numeric value that is the length of the argument string, which is 12. - - -@node Eval Special -@subsubsection Evaluating Special Syntactic Expressions - -When a procedure invocation expression is evaluated, the procedure and -@emph{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. - -@lisp -(if (string=? (read-answer "Should I delete this file?") - "yes") - (delete-file file)) -@end lisp - -If the outermost @code{(if @dots{})} expression here was a procedure -invocation expression, the expression @code{(delete-file file)}, whose -effect is to actually delete a file, would already have been executed -before the @code{if} procedure even got invoked! Clearly this is no use ---- the whole point of an @code{if} expression is that the -@dfn{consequent} expression is only evaluated if the condition of the -@code{if} expression is ``true''. - -Therefore @code{if} must be special syntax, not a procedure. Other -special syntaxes that we have already met are @code{define}, @code{set!} -and @code{lambda}. @code{define} and @code{set!} are syntax because -they need to know the variable @emph{name} that is given as the first -argument in a @code{define} or @code{set!} expression, not that -variable's value. @code{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 @xref{Syntax Summary}. - - -@node The REPL -@subsection 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 -@dfn{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 @code{string-append}, -for example, the REPL replies @code{#}, illustrating the relationship between the variable -@code{string-append} and the procedure value stored in that variable. - -In this manual, the notation @result{} is used to mean ``evaluates -to''. Wherever you see an example of the form - -@lisp -@var{expression} -@result{} -@var{result} -@end lisp - -@noindent -feel free to try it out yourself by typing @var{expression} into the -REPL and checking that it gives the expected @var{result}. - - -@node Syntax Summary -@subsection 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. - -@code{if} (REFFIXME) and @code{cond} (REFFIXME) provide conditional -evaluation of argument expressions depending on whether one or more -conditions evaluate to ``true'' or ``false''. - -@code{case} (REFFIXME) provides conditional evaluation of argument -expressions depending on whether a variable has one of a specified group -of values. - -@code{define} (REFFIXME) is used to create a new variable and set its -initial value. - -@code{set!} (REFFIXME) is used to modify an existing variable's value. - -@code{lambda} (REFFIXME) is used to construct procedure objects. - -@code{let} (REFFIXME), @code{let*} (REFFIXME) and @code{letrec} -(REFFIXME) 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 @xref{About Closure}. - -@code{begin} (REFFIXME) 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. - -@code{and} (REFFIXME) executes a sequence of expressions in order until -either there are no expressions left, or one of them evaluates to -``false''. - -@code{or} (REFFIXME) executes a sequence of expressions in order until -either there are no expressions left, or one of them evaluates to -``true''. - - -@node About Closure -@section The Concept of Closure - -@cindex closure - -The concept of @dfn{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. - -@menu -* About Environments:: Names, locations, values and environments. -* Local Variables:: Local variables and local environments. -* Chaining:: Environment chaining. -* Lexical Scope:: The meaning of lexical scoping. -* Closure:: Explaining the concept of closure. -* Serial Number:: Example 1: a serial number generator. -* Shared Variable:: Example 2: a shared persistent variable. -* Callback Closure:: Example 3: the callback closure problem. -* OO Closure:: Example 4: object orientation. -@end menu - -@node About Environments -@subsection Names, Locations, Values and Environments - -@cindex location -@cindex environment -@cindex vcell -@cindex top level environment -@cindex environment, top level - -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 -@code{define} syntax into three parts: @code{define} - -@itemize @bullet -@item -creates a new location - -@item -establishes an association between that location and the name specified -as the first argument of the @code{define} expression - -@item -stores in that location the value obtained by evaluating the second -argument of the @code{define} expression. -@end itemize - -A collection of associations between names and locations is called an -@dfn{environment}. When you create a top level variable in a program -using @code{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. - - -@node Local Variables -@subsection Local Variables and Environments - -@cindex local variable -@cindex variable, local -@cindex local environment -@cindex environment, local - -We have seen how to create top level variables using the @code{define} -syntax (@pxref{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 @code{let} syntax, or one of -its modified forms @code{let*} and @code{letrec}. These syntaxes are -described in full later in the manual (REFFIXME). 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 @code{s} to -simplify the computation of the area of a triangle given the lengths of -its three sides. - -@lisp -(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))))) -@end lisp - -The effect of the @code{let} expression is to create a new environment -and, within this environment, an association between the name @code{s} -and a new location whose initial value is obtained by evaluating -@code{(/ (+ a b c) 2)}. The expressions in the body of the @code{let}, -namely @code{(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 @code{let} -expression, and therefore the value of the variable @code{area}. - - -@node Chaining -@subsection Environment Chaining - -@cindex shadowing an imported variable binding -@cindex chaining environments - -In the example of the previous subsection, we glossed over an important -point. The body of the @code{let} expression in that example refers not -only to the local variable @code{s}, but also to the top level variables -@code{a}, @code{b}, @code{c} and @code{sqrt}. (@code{sqrt} is the -standard Scheme procedure for calculating a square root.) If the body -of the @code{let} expression is evaluated in the context of the -@emph{local} @code{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 @code{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 @code{s} created by the expression: - -@lisp -(define s "Some beans, my lord!") -@end lisp - -Then both the top level environment and the local @code{let} environment -would contain bindings for the name @code{s}. When evaluating code -within the @code{let} body, the interpreter looks first in the local -@code{let} environment, and so finds the binding for @code{s} created by -the @code{let} syntax. Even though this environment has a reference to -the top level environment, which also has a binding for @code{s}, the -interpreter doesn't get as far as looking there. When evaluating code -outside the @code{let} body, the interpreter looks up variable names in -the top level environment, so the name @code{s} refers to the top level -variable. - -Within the @code{let} body, the binding for @code{s} in the local -environment is said to @dfn{shadow} the binding for @code{s} in the top -level environment. - - -@node Lexical Scope -@subsection Lexical Scope - -The rules that we have just been describing are the details of how -Scheme implements ``lexical scoping''. This subsection takes a brief -diversion to explain what lexical scope means in general and to present -an example of non-lexical scoping. - -``Lexical scope'' in general is the idea that - -@itemize @bullet -@item -an identifier at a particular place in a program always refers to the -same variable location --- where ``always'' means ``every time that the -containing expression is executed'', and that - -@item -the variable location to which it refers can be determined by static -examination of the source code context in which that identifier appears, -without having to consider the flow of execution through the program as -a whole. -@end itemize - -In practice, lexical scoping is the norm for most programming languages, -and probably corresponds to what you would intuitively consider to be -``normal''. You may even be wondering how the situation could possibly ---- and usefully --- be otherwise. To demonstrate that another kind of -scoping is possible, therefore, and to compare it against lexical -scoping, the following subsection presents an example of non-lexical -scoping and examines in detail how its behavior differs from the -corresponding lexically scoped code. - -@menu -* Scoping Example:: An example of non-lexical scoping. -@end menu - - -@node Scoping Example -@subsubsection An Example of Non-Lexical Scoping - -To demonstrate that non-lexical scoping does exist and can be useful, we -present the following example from Emacs Lisp, which is a ``dynamically -scoped'' language. - -@lisp -(defvar currency-abbreviation "USD") - -(defun currency-string (units hundredths) - (concat currency-abbreviation - (number-to-string units) - "." - (number-to-string hundredths))) - -(defun french-currency-string (units hundredths) - (let ((currency-abbreviation "FRF")) - (currency-string units hundredths))) -@end lisp - -The question to focus on here is: what does the identifier -@code{currency-abbreviation} refer to in the @code{currency-string} -function? The answer, in Emacs Lisp, is that all variable bindings go -onto a single stack, and that @code{currency-abbreviation} refers to the -topmost binding from that stack which has the name -``currency-abbreviation''. The binding that is created by the -@code{defvar} form, to the value @code{"USD"}, is only relevant if none -of the code that calls @code{currency-string} rebinds the name -``currency-abbreviation'' in the meanwhile. - -The second function @code{french-currency-string} works precisely by -taking advantage of this behaviour. It creates a new binding for the -name ``currency-abbreviation'' which overrides the one established by -the @code{defvar} form. - -@lisp -;; Note! This is Emacs Lisp evaluation, not Scheme! -(french-currency-string 33 44) -@result{} -"FRF33.44" -@end lisp - -Now let's look at the corresponding, @emph{lexically scoped} Scheme -code: - -@lisp -(define currency-abbreviation "USD") - -(define (currency-string units hundredths) - (string-append currency-abbreviation - (number->string units) - "." - (number->string hundredths))) - -(define (french-currency-string units hundredths) - (let ((currency-abbreviation "FRF")) - (currency-string units hundredths))) -@end lisp - -According to the rules of lexical scoping, the -@code{currency-abbreviation} in @code{currency-string} refers to the -variable location in the innermost environment at that point in the code -which has a binding for @code{currency-abbreviation}, which is the -variable location in the top level environment created by the preceding -@code{(define currency-abbreviation @dots{})} expression. - -In Scheme, therefore, the @code{french-currency-string} procedure does -not work as intended. The variable binding that it creates for -``currency-abbreviation'' is purely local to the code that forms the -body of the @code{let} expression. Since this code doesn't directly use -the name ``currency-abbreviation'' at all, the binding is pointless. - -@lisp -(french-currency-string 33 44) -@result{} -"USD33.44" -@end lisp - -This begs the question of how the Emacs Lisp behaviour can be -implemented in Scheme. In general, this is a design question whose -answer depends upon the problem that is being addressed. In this case, -the best answer may be that @code{currency-string} should be -redesigned so that it can take an optional third argument. This third -argument, if supplied, is interpreted as a currency abbreviation that -overrides the default. - -It is possible to change @code{french-currency-string} so that it mostly -works without changing @code{currency-string}, but the fix is inelegant, -and susceptible to interrupts that could leave the -@code{currency-abbreviation} variable in the wrong state: - -@lisp -(define (french-currency-string units hundredths) - (set! currency-abbreviation "FRF") - (let ((result (currency-string units hundredths))) - (set! currency-abbreviation "USD") - result)) -@end lisp - -The key point here is that the code does not create any local binding -for the identifier @code{currency-abbreviation}, so all occurences of -this identifier refer to the top level variable. - - -@node Closure -@subsection Closure - -Consider a @code{let} expression that doesn't contain any -@code{lambda}s: - -@lisp -(let ((s (/ (+ a b c) 2))) - (sqrt (* s (- s a) (- s b) (- s c)))) -@end lisp - -@noindent -When the Scheme interpreter evaluates this, it - -@itemize @bullet -@item -creates a new environment with a reference to the environment that was -current when it encountered the @code{let} - -@item -creates a variable binding for @code{s} in the new environment, with -value given by @code{(/ (+ a b c) 2)} - -@item -evaluates the expression in the body of the @code{let} in the context of -the new local environment, and remembers the value @code{V} - -@item -forgets the local environment - -@item -continues evaluating the expression that contained the @code{let}, using -the value @code{V} as the value of the @code{let} expression, in the -context of the containing environment. -@end itemize - -After the @code{let} expression has been evaluated, the local -environment that was created is simply forgotten, and there is no longer -any way to access the binding that was created in this environment. If -the same code is evaluated again, it will follow the same steps again, -creating a second new local environment that has no connection with the -first, and then forgetting this one as well. - -If the @code{let} body contains a @code{lambda} expression, however, the -local environment is @emph{not} forgotten. Instead, it becomes -associated with the procedure that is created by the @code{lambda} -expression, and is reinstated every time that that procedure is called. -In detail, this works as follows. - -@itemize @bullet -@item -When the Scheme interpreter evaluates a @code{lambda} expression, to -create a procedure object, it stores the current environment as part of -the procedure definition. - -@item -Then, whenever that procedure is called, the interpreter reinstates the -environment that is stored in the procedure definition and evaluates the -procedure body within the context of that environment. -@end itemize - -The result is that the procedure body is always evaluated in the context -of the environment that was current when the procedure was created. - -This is what is meant by @dfn{closure}. The next few subsections -present examples that explore the usefulness of this concept. - - -@node Serial Number -@subsection Example 1: A Serial Number Generator - -This example uses closure to create a procedure with a variable binding -that is private to the procedure, like a local variable, but whose value -persists between procedure calls. - -@lisp -(define (make-serial-number-generator) - (let ((current-serial-number 0)) - (lambda () - (set! current-serial-number (+ current-serial-number 1)) - current-serial-number))) - -(define entry-sn-generator (make-serial-number-generator)) - -(entry-sn-generator) -@result{} -1 - -(entry-sn-generator) -@result{} -2 -@end lisp - -When @code{make-serial-number-generator} is called, it creates a local -environment with a binding for @code{current-serial-number} whose -initial value is 0, then, within this environment, creates a procedure. -The local environment is stored within the created procedure object and -so persists for the lifetime of the created procedure. - -Every time the created procedure is invoked, it increments the value of -the @code{current-serial-number} binding in the captured environment and -then returns the current value. - -Note that @code{make-serial-number-generator} can be called again to -create a second serial number generator that is independent of the -first. Every new invocation of @code{make-serial-number-generator} -creates a new local @code{let} environment and returns a new procedure -object with an association to this environment. - - -@node Shared Variable -@subsection Example 2: A Shared Persistent Variable - -This example uses closure to create two procedures, @code{get-balance} -and @code{deposit}, that both refer to the same captured local -environment so that they can both access the @code{balance} variable -binding inside that environment. The value of this variable binding -persists between calls to either procedure. - -Note that the captured @code{balance} variable binding is private to -these two procedures: it is not directly accessible to any other code. -It can only be accessed indirectly via @code{get-balance} or -@code{deposit}, as illustrated by the @code{withdraw} procedure. - -@lisp -(define get-balance #f) -(define deposit #f) - -(let ((balance 0)) - (set! get-balance - (lambda () - balance)) - (set! deposit - (lambda (amount) - (set! balance (+ balance amount)) - balance))) - -(define (withdraw amount) - (deposit (- amount))) - -(get-balance) -@result{} -0 - -(deposit 50) -@result{} -50 - -(withdraw 75) -@result{} --25 -@end lisp - -A detail here is that the @code{get-balance} and @code{deposit} -variables must be set up by @code{define}ing them at top level and then -@code{set!}ing their values inside the @code{let} body. Using -@code{define} within the @code{let} body would not work: this would -create variable bindings within the local @code{let} environment that -would not be accessible at top level. - - -@node Callback Closure -@subsection Example 3: The Callback Closure Problem - -A frequently used programming model for library code is to allow an -application to register a callback function for the library to call when -some particular event occurs. It is often useful for the application to -make several such registrations using the same callback function, for -example if several similar library events can be handled using the same -application code, but the need then arises to distinguish the callback -function calls that are associated with one callback registration from -those that are associated with different callback registrations. - -In languages without the ability to create functions dynamically, this -problem is usually solved by passing a @code{user_data} parameter on the -registration call, and including the value of this parameter as one of -the parameters on the callback function. Here is an example of -declarations using this solution in C: - -@example -typedef void (event_handler_t) (int event_type, - void *user_data); - -void register_callback (int event_type, - event_handler_t *handler, - void *user_data); -@end example - -In Scheme, closure can be used to achieve the same functionality without -requiring the library code to store a @code{user-data} for each callback -registration. - -@lisp -;; In the library: - -(define (register-callback event-type handler-proc) - @dots{}) - -;; In the application: - -(define (make-handler event-type user-data) - (lambda () - @dots{} - - @dots{})) - -(register-callback event-type - (make-handler event-type @dots{})) -@end lisp - -As far as the library is concerned, @code{handler-proc} is a procedure -with no arguments, and all the library has to do is call it when the -appropriate event occurs. From the application's point of view, though, -the handler procedure has used closure to capture an environment that -includes all the context that the handler code needs --- -@code{event-type} and @code{user-data} --- to handle the event -correctly. - - -@node OO Closure -@subsection Example 4: Object Orientation - -Closure is the capture of an environment, containing persistent variable -bindings, within the definition of a procedure or a set of related -procedures. This is rather similar to the idea in some object oriented -languages of encapsulating a set of related data variables inside an -``object'', together with a set of ``methods'' that operate on the -encapsulated data. The following example shows how closure can be used -to emulate the ideas of objects, methods and encapsulation in Scheme. - -@lisp -(define (make-account) - (let ((balance 0)) - (define (get-balance) - balance) - (define (deposit amount) - (set! balance (+ balance amount)) - balance) - (define (withdraw amount) - (deposit (- amount))) - - (lambda args - (apply - (case (car args) - ((get-balance) get-balance) - ((deposit) deposit) - ((withdraw) withdraw) - (else (error "Invalid method!"))) - (cdr args))))) -@end lisp - -Each call to @code{make-account} creates and returns a new procedure, -created by the expression in the example code that begins ``(lambda -args''. - -@lisp -(define my-account (make-account)) - -my-account -@result{} -# -@end lisp - -This procedure acts as an account object with methods -@code{get-balance}, @code{deposit} and @code{withdraw}. To apply one of -the methods to the account, you call the procedure with a symbol -indicating the required method as the first parameter, followed by any -other parameters that are required by that method. - -@lisp -(my-account 'get-balance) -@result{} -0 - -(my-account 'withdraw 5) -@result{} --5 - -(my-account 'deposit 396) -@result{} -391 - -(my-account 'get-balance) -@result{} -391 -@end lisp - -Note how, in this example, both the current balance and the helper -procedures @code{get-balance}, @code{deposit} and @code{withdraw}, used -to implement the guts of the account object's methods, are all stored in -variable bindings within the private local environment captured by the -@code{lambda} expression that creates the account object procedure. - - -@c Local Variables: -@c TeX-master: "guile.texi" -@c End: diff --git a/doc/scheme-modules.texi b/doc/scheme-modules.texi index 63c86f5c4..293ab0517 100644 --- a/doc/scheme-modules.texi +++ b/doc/scheme-modules.texi @@ -394,38 +394,38 @@ Mikael Djurfeldt's source-level debugging support for Guile Guile's support for multi threaded execution (@pxref{Scheduling}). @item (ice-9 rdelim) -Line- and character-delimited input (REFFIXME). +Line- and character-delimited input (@pxref{Line/Delimited}). @item (ice-9 documentation) Online documentation (REFFIXME). @item (srfi srfi-2) -Support for @code{and-let*} (REFFIXME). +Support for @code{and-let*} (@pxref{SRFI-2}). @item (srfi srfi-6) -Support for some additional string port procedures (REFFIXME). +Support for some additional string port procedures (@pxref{SRFI-6}). @item (srfi srfi-8) -Multiple-value handling with @code{receive} (REFFIXME). +Multiple-value handling with @code{receive} (@pxref{SRFI-8}). @item (srfi srfi-9) -Record definition with @code{define-record-type} (REFFIXME). +Record definition with @code{define-record-type} (@pxref{SRFI-9}). @item (srfi srfi-10) -Read hash extension @code{#,()} (REFFIXME). +Read hash extension @code{#,()} (@pxref{SRFI-10}). @item (srfi srfi-11) Multiple-value handling with @code{let-values} and @code{let-values*} -(REFFIXME). +(@pxref{SRFI-11}). @item (srfi srfi-13) -String library (REFFIXME). +String library (@pxref{SRFI-13}). @item (srfi srfi-14) -Character-set library (REFFIXME). +Character-set library (@pxref{SRFI-14}). @item (srfi srfi-17) -Getter-with-setter support (REFFIXME). +Getter-with-setter support (@pxref{SRFI-17}). @item (ice-9 slib) This module contains hooks for using Aubrey Jaffer's portable Scheme diff --git a/doc/scheme-procedures.texi b/doc/scheme-procedures.texi dissimilarity index 100% index 2dc28968f..e69de29bb 100644 --- a/doc/scheme-procedures.texi +++ b/doc/scheme-procedures.texi @@ -1,779 +0,0 @@ -@page -@node Procedures and Macros -@chapter Procedures and Macros - -@menu -* Lambda:: Basic procedure creation using lambda. -* Optional Arguments:: Handling keyword, optional and rest arguments. -* Procedure Properties:: Procedure properties and metainformation. -* Procedures with Setters:: Procedures with setters. -* Macros:: Lisp style macro definitions. -* Syntax Rules:: Support for R5RS @code{syntax-rules}. -* Syntax Case:: Support for the @code{syntax-case} system. -* Internal Macros:: Guile's internal representation. -@end menu - - -@node Lambda -@section Lambda: Basic Procedure Creation - -@c FIXME::martin: Review me! - -A @code{lambda} expression evaluates to a procedure. The environment -which is in effect when a @code{lambda} expression is evaluated is -enclosed in the newly created procedure, this is referred to as a -@dfn{closure} (@pxref{About Closure}). - -When a procedure created by @code{lambda} is called with some actual -arguments, the environment enclosed in the procedure is extended by -binding the variables named in the formal argument list to new locations -and storing the actual arguments into these locations. Then the body of -the @code{lambda} expression is evaluation sequentially. The result of -the last expression in the procedure body is then the result of the -procedure invocation. - -The following examples will show how procedures can be created using -@code{lambda}, and what you can do with these procedures. - -@lisp -(lambda (x) (+ x x)) @result{} @r{a procedure} -((lambda (x) (+ x x)) 4) @result{} 8 -@end lisp - -The fact that the environment in effect when creating a procedure is -enclosed in the procedure is shown with this example: - -@lisp -(define add4 - (let ((x 4)) - (lambda (y) (+ x y)))) -(add4 6) @result{} 10 -@end lisp - - -@deffn syntax lambda formals body -@var{formals} should be a formal argument list as described in the -following table. - -@table @code -@item (@var{variable1} @dots{}) -The procedure takes a fixed number of arguments; when the procedure is -called, the arguments will be stored into the newly created location for -the formal variables. -@item @var{variable} -The procedure takes any number of arguments; when the procedure is -called, the sequence of actual arguments will converted into a list and -stored into the newly created location for the formal variable. -@item (@var{variable1} @dots{} @var{variablen} . @var{variablen+1}) -If a space-delimited period precedes the last variable, then the -procedure takes @var{n} or more variablesm where @var{n} is the number -of formal arguments before the period. There must be at least one -argument before the period. The first @var{n} actual arguments will be -stored into the newly allocated locations for the first @var{n} formal -arguments and the sequence of the remaining actual arguments is -converted into a list and the stored into the location for the last -formal argument. If there are exactly @var{n} actual arguments, the -empty list is stored into the location of the last formal argument. -@end table - -@var{body} is a sequence of Scheme expressions which are evaluated in -order when the procedure is invoked. -@end deffn - - -@node Optional Arguments -@section Optional Arguments - -@c FIXME::martin: Review me! - -Scheme procedures, as defined in R5RS, can wither handle a fixed number -of actual arguments, or a fixed number of actual arguments followed by -arbitrarily many additional arguments. Writing procedures of variable -arity can be useful, but unfortunately, the syntactic means for handling -argument lists of varying length is a bit inconvenient. It is possible -to give names to the fixed number of argument, but the remaining -(optional) arguments can be only referenced as a list of values -(@pxref{Lambda}). - -Guile comes with the module @code{(ice-9 optargs)}, which makes using -optional arguments much more convenient. In addition, this module -provides syntax for handling keywords in argument lists -(@pxref{Keywords}). - -Before using any of the procedures or macros defined in this section, -you have to load the module @code{(ice-9 optargs)} with the statement: - -@lisp -(use-modules (ice-9 optargs)) -@end lisp - -@menu -* let-optional Reference:: Locally binding optional arguments. -* let-keywords Reference:: Locally binding keywords arguments. -* lambda* Reference:: Creating advanced argument handling procedures. -* define* Reference:: Defining procedures and macros. -@end menu - - -@node let-optional Reference -@subsection let-optional Reference - -@c FIXME::martin: Review me! - -The syntax @code{let-optional} and @code{let-optional*} are for -destructuring rest argument lists and giving names to the various list -elements. @code{let-optional} binds all variables simultaneously, while -@code{let-optional*} binds them sequentially, consistent with @code{let} -and @code{let*} (REFFIXME). - -@deffn {libary syntax} let-optional rest-arg (binding @dots{}) expr @dots{} -@deffnx {library syntax} let-optional* rest-arg (binding @dots{}) expr @dots{} -These two macros give you an optional argument interface that is very -@dfn{Schemey} and introduces no fancy syntax. They are compatible with -the scsh macros of the same name, but are slightly extended. Each of -@var{binding} may be of one of the forms @var{var} or @code{(@var{var} -@var{default-value})}. @var{rest-arg} should be the rest-argument of the -procedures these are used from. The items in @var{rest-arg} are -sequentially bound to the variable names are given. When @var{rest-arg} -runs out, the remaining vars are bound either to the default values or -left unbound if no default value was specified. @var{rest-arg} remains -bound to whatever may have been left of @var{rest-arg}. - -After binding the variables, the expressions @var{expr} @dots{} are -evaluated in order. -@end deffn - - -@node let-keywords Reference -@subsection let-keywords Reference - -@c FIXME::martin: Review me! - -@code{let-keywords} and @code{let-keywords*} are used for extracting -values from argument lists which use keywords instead of argument -position for binding local variables to argument values. - -@code{let-keywords} binds all variables simultaneously, while -@code{let-keywords*} binds them sequentially, consistent with @code{let} -and @code{let*} (REFFIXME). - -@deffn {library syntax} let-keywords rest-arg allow-other-keys? (binding @dots{}) expr @dots{} -@deffnx {library syntax} let-keywords rest-arg allow-other-keys? (binding @dots{}) expr @dots{} -These macros pick out keyword arguments from @var{rest-arg}, but do not -modify it. This is consistent at least with Common Lisp, which -duplicates keyword arguments in the rest argument. More explanation of what -keyword arguments in a lambda list look like can be found below in -the documentation for @code{lambda*} - (@pxref{lambda* Reference}). @var{binding}s can have the same form as -for @code{let-optional}. If @var{allow-other-keys?} is false, an error -will be thrown if anything that looks like a keyword argument but does -not match a known keyword parameter will result in an error. - -After binding the variables, the expressions @var{expr} @dots{} are -evaluated in order. -@end deffn - - -@node lambda* Reference -@subsection lambda* Reference - -@c FIXME::martin: Review me! - -When using optional and keyword argument lists, using @code{lambda} for -creating procedures and using @code{let-optional} or @code{let-keywords} -is a bit lengthy. Therefore, @code{lambda*} is provided, which combines -the features of those macros into a single convenient syntax. - -For quick reference, here is the syntax of the formal argument list for -@code{lambda*} (brackets are used to indicate grouping only): - -@example -ext-param-list ::= [identifier]* [#:optional [ext-var-decl]+]? - [#:key [ext-var-decl]+ [#:allow-other-keys]?]? - [[#:rest identifier]|[. identifier]]? - -ext-var-decl ::= identifier | ( identifier expression ) -@end example - -The characters `*', `+' and `?' are not to be taken literally; they mean -respectively, zero or more occurences, one or more occurences, and one -or zero occurences. - -@deffn {library syntax} lambda* formals body -@code{lambda*} creates a procedure that takes optional arguments. These -are specified by putting them inside brackets at the end of the -paramater list, but before any dotted rest argument. For example, - -@lisp -(lambda* (a b #:optional c d . e) '()) -@end lisp - -creates a procedure with fixed arguments @var{a} and @var{b}, optional -arguments @var{c} and @var{d}, and rest argument @var{e}. If the -optional arguments are omitted in a call, the variables for them are -unbound in the procedure. This can be checked with the @code{bound?} -macro (documented below). - -@code{lambda*} can also take keyword arguments. For example, a procedure -defined like this: - -@lisp -(lambda* (#:key xyzzy larch) '()) -@end lisp - -can be called with any of the argument lists @code{(#:xyzzy 11)} -@code{(#:larch 13)} @code{(#:larch 42 #:xyzzy 19)} @code{()}. Whichever -arguments are given as keywords are bound to values. - -Optional and keyword arguments can also be given default values -which they take on when they are not present in a call, by giving a -two-item list in place of an optional argument, for example in: - -@lisp -(lambda* (foo #:optional (bar 42) #:key (baz 73)) - (list foo bar baz)) -@end lisp - -@var{foo} is a fixed argument, @var{bar} is an optional argument with -default value 42, and baz is a keyword argument with default value 73. -Default value expressions are not evaluated unless they are needed and -until the procedure is called. - -@code{lambda*} also supports two more special parameter list keywords. - -@code{lambda*}-defined procedures now throw an error by default if a -keyword other than one of those specified is found in the actual -passed arguments. However, specifying @code{#:allow-other-keys} -immediately after the keyword argument declarations restores the -previous behavior of ignoring unknown keywords. @code{lambda*} also now -guarantees that if the same keyword is passed more than once, the -last one passed is the one that takes effect. For example, - -@lisp -((lambda* (#:key (heads 0) (tails 0)) (display (list heads tails))) - #:heads 37 #:tails 42 #:heads 99) -@end lisp - -would result in (99 47) being displayed. - -@code{#:rest} is also now provided as a synonym for the dotted syntax -rest argument. The argument lists @code{(a . b)} and @code{(a #:rest b)} -are equivalent in all respects to @code{lambda*}. This is provided for -more similarity to DSSSL, MIT-Scheme and Kawa among others, as well as -for refugees from other Lisp dialects. -@end deffn - -@deffn {library syntax} bound? variable -Check if a variable is bound in the current environment. - -The procedure @code{defined?} doesn't quite cut it as it stands, since -it only checks bindings in the top-level environment, not those in local -scope only. -@end deffn - - -@node define* Reference -@subsection define* Reference - -@c FIXME::martin: Review me! - -Just like @code{define} has a shorthand notation for defining procedures -(@pxref{Lambda Alternatives}), @code{define*} is provided as an -abbreviation of the combination of @code{define} and @code{lambda*}. - -@code{define*-public} is the @code{lambda*} version of -@code{define-public}; @code{defmacro*} and @code{defmacro*-public} exist -for defining macros with the improved argument list handling -possibilities. The @code{-public} versions not only define the -procedures/macros, but also export them from the current module. - -@deffn {library syntax} define* formals body -@deffnx {library syntax} define*-public formals body -@code{define*} and @code{define*-public} support optional arguments with -a similar syntax to @code{lambda*}. They also support arbitrary-depth -currying, just like Guile's define. Some examples: - -@lisp -(define* (x y #:optional a (z 3) #:key w . u) - (display (list y z u))) -@end lisp -defines a procedure @code{x} with a fixed argument @var{y}, an optional -agument @var{a}, another optional argument @var{z} with default value 3, -a keyword argument @var{w}, and a rest argument @var{u}. - -@lisp -(define-public* ((foo #:optional bar) #:optional baz) '()) -@end lisp - -This illustrates currying. A procedure @code{foo} is defined, which, -when called with an optional argument @var{bar}, returns a procedure -that takes an optional argument @var{baz}. - -Of course, @code{define*[-public]} also supports @code{#:rest} and -@code{#:allow-other-keys} in the same way as @code{lambda*}. -@end deffn - -@deffn {library syntax} defmacro* name formals body -@deffnx {library syntax} defmacro*-public name formals body -These are just like @code{defmacro} and @code{defmacro-public} except that they -take @code{lambda*}-style extended paramter lists, where @code{#:optional}, -@code{#:key}, @code{#:allow-other-keys} and @code{#:rest} are allowed with the usual -semantics. Here is an example of a macro with an optional argument: - -@lisp -(defmacro* transmorgify (a #:optional b) - (a 1)) -@end lisp -@end deffn - - -@node Procedure Properties -@section Procedure Properties and Metainformation - -@c FIXME::martin: Review me! - -Procedures always have attached the environment in which they were -created and information about how to apply them to actual arguments. In -addition to that, properties and metainformation can be stored with -procedures. The procedures in this section can be used to test whether -a given procedure satisfies a condition; and to access and set a -procedure's property. - -The first group of procedures are predicates to test whether a Scheme -object is a procedure, or a special procedure, respectively. -@code{procedure?} is the most general predicates, it returns @code{#t} -for any kind of procedure. @code{closure?} does not return @code{#t} -for primitive procedures, and @code{thunk?} only returns @code{#t} for -procedures which do not accept any arguments. -@c FIXME::martin: thunk? returns true for `id'. What's wrong here? - -@rnindex procedure? -@deffn primitive procedure? obj -Return @code{#t} if @var{obj} is a procedure. -@end deffn - -@deffn primitive closure? obj -Return @code{#t} if @var{obj} is a closure. -@end deffn - -@deffn primitive thunk? obj -Return @code{#t} if @var{obj} is a thunk. -@end deffn - -@c FIXME::martin: Is that true? -@cindex procedure properties -Procedure properties are general properties to be attached to -procedures. These can be the name of a procedure or other relevant -information, such as debug hints. - -@deffn primitive procedure-properties proc -Return @var{obj}'s property list. -@end deffn - -@deffn primitive procedure-property p k -Return the property of @var{obj} with name @var{key}. -@end deffn - -@deffn primitive set-procedure-properties! proc new_val -Set @var{obj}'s property list to @var{alist}. -@end deffn - -@deffn primitive set-procedure-property! p k v -In @var{obj}'s property list, set the property named @var{key} to -@var{value}. -@end deffn - -@cindex procedure documentation -Documentation for a procedure can be accessed with the procedure -@code{procedure-documentation}. - -@deffn primitive procedure-documentation proc -Return the documentation string associated with @code{proc}. By -convention, if a procedure contains more than one expression and the -first expression is a string constant, that string is assumed to contain -documentation for that procedure. -@end deffn - -@cindex source properties -@c FIXME::martin: Is the following true? -Source properties are properties which are related to the source code of -a procedure, such as the line and column numbers, the file name etc. - -@deffn primitive set-source-properties! obj plist -Install the association list @var{plist} as the source property -list for @var{obj}. -@end deffn - -@deffn primitive set-source-property! obj key datum -Set the source property of object @var{obj}, which is specified by -@var{key} to @var{datum}. Normally, the key will be a symbol. -@end deffn - -@deffn primitive source-properties obj -Return the source property association list of @var{obj}. -@end deffn - - -@deffn primitive source-property obj key -Return the source property specified by @var{key} from -@var{obj}'s source property list. -@end deffn - - -@node Procedures with Setters -@section Procedures with Setters - -@c FIXME::martin: Review me! - -@c FIXME::martin: Document `operator struct'. - -@cindex procedure with setter -@cindex setter -A @dfn{procedure with setter} is a special kind of procedure which -normally behaves like any accesor procedure, that is a procedure which -accesses a data structure. The difference is that this kind of -procedure has a so-called @dfn{setter} attached, which is a procedure -for storing something into a data structure. - -Procedures with setters are treated specially when the procedure appears -in the special form @code{set!} (REFFIXME). How it works is best shown -by example. - -Suppose we have a procedure called @code{foo-ref}, which accepts two -arguments, a value of type @code{foo} and an integer. The procedure -returns the value stored at the given index in the @code{foo} object. -Let @code{f} be a variable containing such a @code{foo} data -structure.@footnote{Working definitions would be: -@lisp -(define foo-ref vector-ref) -(define foo-set! vector-set!) -(define f (make-vector 2 #f)) -@end lisp -} - -@lisp -(foo-ref f 0) @result{} bar -(foo-ref f 1) @result{} braz -@end lisp - -Also suppose that a corresponding setter procedure called -@code{foo-set!} does exist. - -@lisp -(foo-set! f 0 'bla) -(foo-ref f 0) @result{} bla -@end lisp - -Now we could create a new procedure called @code{foo}, which is a -procedure with setter, by calling @code{make-procedure-with-setter} with -the accessor and setter procedures @code{foo-ref} and @code{foo-set!}. -Let us call this new procedure @code{foo}. - -@lisp -(define foo (make-procedure-with-setter foo-ref foo-set!)) -@end lisp - -@code{foo} can from now an be used to either read from the data -structure stored in @code{f}, or to write into the structure. - -@lisp -(set! (foo f 0) 'dum) -(foo f 0) @result{} dum -@end lisp - -@deffn primitive make-procedure-with-setter procedure setter -Create a new procedure which behaves like @var{procedure}, but -with the associated setter @var{setter}. -@end deffn - -@deffn primitive procedure-with-setter? obj -Return @code{#t} if @var{obj} is a procedure with an -associated setter procedure. -@end deffn - -@deffn primitive procedure proc -Return the procedure of @var{proc}, which must be either a -procedure with setter, or an operator struct. -@end deffn - -@deffn primitive setter proc -Return the setter of @var{proc}, which must be either a procedure with -setter or an operator struct. -@end deffn - - -@node Macros -@section Lisp Style Macro Definitions - -@cindex macros -@cindex transformation -Macros are objects which cause the expression that they appear in to be -transformed in some way @emph{before} being evaluated. In expressions -that are intended for macro transformation, the identifier that names -the relevant macro must appear as the first element, like this: - -@lisp -(@var{macro-name} @var{macro-args} @dots{}) -@end lisp - -In Lisp-like languages, the traditional way to define macros is very -similar to procedure definitions. The key differences are that the -macro definition body should return a list that describes the -transformed expression, and that the definition is marked as a macro -definition (rather than a procedure definition) by the use of a -different definition keyword: in Lisp, @code{defmacro} rather than -@code{defun}, and in Scheme, @code{define-macro} rather than -@code{define}. - -@fnindex defmacro -@fnindex define-macro -Guile supports this style of macro definition using both @code{defmacro} -and @code{define-macro}. The only difference between them is how the -macro name and arguments are grouped together in the definition: - -@lisp -(defmacro @var{name} (@var{args} @dots{}) @var{body} @dots{}) -@end lisp - -@noindent -is the same as - -@lisp -(define-macro (@var{name} @var{args} @dots{}) @var{body} @dots{}) -@end lisp - -@noindent -The difference is analogous to the corresponding difference between -Lisp's @code{defun} and Scheme's @code{define}. - -@code{false-if-exception}, from the @file{boot-9.scm} file in the Guile -distribution, is a good example of macro definition using -@code{defmacro}: - -@lisp -(defmacro false-if-exception (expr) - `(catch #t - (lambda () ,expr) - (lambda args #f))) -@end lisp - -@noindent -The effect of this definition is that expressions beginning with the -identifier @code{false-if-exception} are automatically transformed into -a @code{catch} expression following the macro definition specification. -For example: - -@lisp -(false-if-exception (open-input-file "may-not-exist")) -@equiv{} -(catch #t - (lambda () (open-input-file "may-not-exist")) - (lambda args #f)) -@end lisp - - -@node Syntax Rules -@section The R5RS @code{syntax-rules} System - -R5RS defines an alternative system for macro and syntax transformations -using the keywords @code{define-syntax}, @code{let-syntax}, -@code{letrec-syntax} and @code{syntax-rules}. - -The main difference between the R5RS system and the traditional macros -of the previous section is how the transformation is specified. In -R5RS, rather than permitting a macro definition to return an arbitrary -expression, the transformation is specified in a pattern language that - -@itemize @bullet -@item -does not require complicated quoting and extraction of components of the -source expression using @code{caddr} etc. - -@item -is designed such that the bindings associated with identifiers in the -transformed expression are well defined, and such that it is impossible -for the transformed expression to construct new identifiers. -@end itemize - -@noindent -The last point is commonly referred to as being @dfn{hygienic}: the R5RS -@code{syntax-case} system provides @dfn{hygienic macros}. - -For example, the R5RS pattern language for the @code{false-if-exception} -example of the previous section looks like this: - -@lisp -(syntax-rules () - ((_ expr) - (catch #t - (lambda () expr) - (lambda args #f)))) -@end lisp - -In Guile, the @code{syntax-rules} system is provided by the @code{(ice-9 -syncase)} module. To make these facilities available in your code, -include the expression @code{(use-modules (ice-9 syncase))} or -@code{(use-syntax (ice-9 syncase))} (@pxref{Using Guile Modules}) -before the first usage of @code{define-syntax} etc. If you are writing -a Scheme module, you can alternatively use one of the keywords -@code{#:use-module} and @code{#:use-syntax} in your @code{define-module} -declaration (@pxref{Creating Guile Modules}). - -@menu -* Pattern Language:: The @code{syntax-rules} pattern language. -* Define-Syntax:: Top level syntax definitions. -* Let-Syntax:: Local syntax definitions. -@end menu - - -@node Pattern Language -@subsection The @code{syntax-rules} Pattern Language - - -@node Define-Syntax -@subsection Top Level Syntax Definitions - -define-syntax: The gist is - - (define-syntax ) - -makes the into a macro so that - - ( ...) - -expands at _compile_ or _read_ time (i.e. before any -evaluation begins) into some expression that is -given by the . - - -@node Let-Syntax -@subsection Local Syntax Definitions - - -@node Syntax Case -@section Support for the @code{syntax-case} System - - - -@node Internal Macros -@section Internal Representation of Macros and Syntax - -Internally, Guile uses three different flavours of macros. The three -flavours are called @dfn{acro} (or @dfn{syntax}), @dfn{macro} and -@dfn{mmacro}. - -Given the expression - -@lisp -(foo @dots{}) -@end lisp - -@noindent -with @code{foo} being some flavour of macro, one of the following things -will happen when the expression is evaluated. - -@itemize @bullet -@item -When @code{foo} has been defined to be an @dfn{acro}, the procedure used -in the acro definition of @code{foo} is passed the whole expression and -the current lexical environment, and whatever that procedure returns is -the value of evaluating the expression. You can think of this a -procedure that receives its argument as an unevaluated expression. - -@item -When @code{foo} has been defined to be a @dfn{macro}, the procedure used -in the macro definition of @code{foo} is passed the whole expression and -the current lexical environment, and whatever that procedure returns is -evaluated again. That is, the procedure should return a valid Scheme -expression. - -@item -When @code{foo} has been defined to be a @dfn{mmacro}, the procedure -used in the mmacro definition of `foo' is passed the whole expression -and the current lexical environment, and whatever that procedure returns -replaces the original expression. Evaluation then starts over from the -new expression that has just been returned. -@end itemize - -The key difference between a @dfn{macro} and a @dfn{mmacro} is that the -expression returned by a @dfn{mmacro} procedure is remembered (or -@dfn{memoized}) so that the expansion does not need to be done again -next time the containing code is evaluated. - -The primitives @code{procedure->syntax}, @code{procedure->macro} and -@code{procedure->memoizing-macro} are used to construct acros, macros -and mmacros respectively. However, if you do not have a very special -reason to use one of these primitives, you should avoid them: they are -very specific to Guile's current implementation and therefore likely to -change. Use @code{defmacro}, @code{define-macro} (@pxref{Macros}) or -@code{define-syntax} (@pxref{Syntax Rules}) instead. (In low level -terms, @code{defmacro}, @code{define-macro} and @code{define-syntax} are -all implemented as mmacros.) - -@deffn primitive procedure->syntax code -Return a macro which, when a symbol defined to this value appears as the -first symbol in an expression, returns the result of applying @var{code} -to the expression and the environment. -@end deffn - -@deffn primitive procedure->macro code -Return a macro which, when a symbol defined to this value appears as the -first symbol in an expression, evaluates the result of applying -@var{code} to the expression and the environment. For example: - -@lisp -(define trace - (procedure->macro - (lambda (x env) - `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x)))))) - -(trace @i{foo}) -@equiv{} -(set! @i{foo} (tracef @i{foo} '@i{foo})). -@end lisp -@end deffn - -@deffn primitive procedure->memoizing-macro code -Return a macro which, when a symbol defined to this value appears as the -first symbol in an expression, evaluates the result of applying -@var{code} to the expression and the environment. -@code{procedure->memoizing-macro} is the same as -@code{procedure->macro}, except that the expression returned by -@var{code} replaces the original macro expression in the memoized form -of the containing code. -@end deffn - -In the following primitives, @dfn{acro} flavour macros are referred to -as @dfn{syntax transformers}. - -@deffn primitive macro? obj -Return @code{#t} if @var{obj} is a regular macro, a memoizing macro or a -syntax transformer. -@end deffn - -@deffn primitive macro-type m -Return one of the symbols @code{syntax}, @code{macro} or -@code{macro!}, depending on whether @var{m} is a syntax -transformer, a regular macro, or a memoizing macro, -respectively. If @var{m} is not a macro, @code{#f} is -returned. -@end deffn - -@deffn primitive macro-name m -Return the name of the macro @var{m}. -@end deffn - -@deffn primitive macro-transformer m -Return the transformer of the macro @var{m}. -@end deffn - -@deffn primitive cons-source xorig x y -Create and return a new pair whose car and cdr are @var{x} and @var{y}. -Any source properties associated with @var{xorig} are also associated -with the new pair. -@end deffn - - -@c Local Variables: -@c TeX-master: "guile.texi" -@c End: diff --git a/doc/srfi-modules.texi b/doc/srfi-modules.texi index 8c9543889..da2cefee0 100644 --- a/doc/srfi-modules.texi +++ b/doc/srfi-modules.texi @@ -1,6 +1,6 @@ @page @node SRFI Support -@chapter Various SRFI Support Modules +@chapter SRFI Support Modules SRFI is an acronym for Scheme Request For Implementation. The SRFI documents define a lot of syntactic and procedure extensions to standard @@ -13,6 +13,7 @@ get the relevant SRFI documents from the SRFI home page @url{http://srfi.schemers.org}. @menu +* About SRFI Usage:: What to know about Guile's SRFI support. * SRFI-0:: cond-expand * SRFI-2:: and-let*. * SRFI-6:: Basic String Ports. @@ -27,6 +28,40 @@ get the relevant SRFI documents from the SRFI home page @end menu +@node About SRFI Usage +@section About SRFI Usage + +@c FIXME::martin: Review me! + +SRFI support in Guile is currently implemented partly in the core +library, and partly as add-on modules. That means that some SRFIs are +automatically available when the interpreter is started, whereas the +other SRFIs require you to use the appropriate support module +explicitly. + +There are several reasons for this inconsistency. First, the feature +checking syntactic form @code{cond-expand} (@pxref{SRFI-0}) must be +available immediately, because it must be there when the user wants to +check for the Scheme implementation, that is, before she can know that +it is safe to use @code{use-modules} to load SRFI support modules. The +second reason is that some features defined in SRFIs had been +implemented in Guile before the developers started to add SRFI +implementations as modules (for example SRFI-6 (@pxref{SRFI-6})). In +the future, it is possible that SRFIs in the core library might be +factored out into separate modules, requiring explicit module loading +when they are needed. So you should be prepared to have to use +@code{use-modules} someday in the future to access SRFI-6 bindings. If +you want, you can do that already. We have included the module +@code{(srfi srfi-6)} in the distribution, which currently does nothing, +but ensures that you can write future-safe code. + +Generally, support for a specific SRFI is made available by using +modules named @code{(srfi srfi-@var{number})}, where @var{number} is the +number of the SRFI needed. Another possibility is to use the command +line option @code{--use-srfi}, which will load the necessary modules +automatically (@pxref{Invoking Guile}). + + @node SRFI-0 @section SRFI-0 - cond-expand @@ -78,6 +113,8 @@ If the feature requirement is the keyword @code{else} and it is the last clause, it is satisfied if no prior clause matched. @end itemize +If no clause is satisfied, an error is signalled. + Since @code{cond-expand} is needed to tell what a Scheme implementation provides, it must be accessible without using any implementation-dependant operations, such as @code{use-modules} in @@ -85,11 +122,13 @@ Guile. Thus, it is not necessary to use any module to get access to this form. Currently, the feature identifiers @code{guile}, @code{r5rs} and -@code{srfi-0} are supported. The other SRFIs are not in that list, -because the SRFI modules must be explicitly used before their exported -bindings can be used. So if a Scheme program wishes to detect whether -SRFI-8 is supported in the running implementation, code similar to this -may be needed: +@code{srfi-0} are supported. The other SRFIs are not in that list by +default, because the SRFI modules must be explicitly used before their +exported bindings can be used. + +So if a Scheme program wishes to use SRFI-8, it has two possibilities: +First, it can check whether the running Scheme implementation is Guile, +and if it is, it can use the appropriate module: @lisp (cond-expand @@ -100,6 +139,23 @@ may be needed: ;; otherwise fail. @end lisp +The other possibility is to use the @code{--use-srfi} command line +option when invoking Guile (@pxref{Invoking Guile}). When you do that, +the specified SRFI support modules will be loaded and add their feature +identifier to the list of symbols checked by @code{cond-expand}. + +So, if you invoke Guile like this: + +@example +$ guile --use-srfi=8 +@end example + +the following snippet will expand to @code{'hooray}. + +@lisp +(cond-expand (srfi-8 'hooray)) +@end lisp + @node SRFI-2 @section SRFI-2 - and-let* @@ -154,7 +210,7 @@ procedures easier. It is documented in @xref{Multiple Values}. This is the SRFI way for defining record types. The Guile implementation is a layer above Guile's normal record construction -procedures (REFFIXME). The nice thing about this kind of record +procedures (@pxref{Records}). The nice thing about this kind of record definition method is that no new names are implicitly created, all constructor, accessor and predicates are explicitly given. This reduces the risk of variable capture. @@ -242,8 +298,8 @@ read in. The result of @var{proc} is returned by the Scheme reader. This module implements the binding forms for multiple values @code{let-values} and @code{let-values*}. These forms are similar to -@code{let} and @code{let*} (REFFIXME), but they support binding of the -values returned by multiple-valued expressions. +@code{let} and @code{let*} (@pxref{Local Bindings}), but they support +binding of the values returned by multiple-valued expressions. Write @code{(use-modules (srfi srfi-11))} to make the bindings available. @@ -272,7 +328,8 @@ In this section, we will describe all procedures defined in SRFI-13 Note that only the procedures from SRFI-13 are documented here which are not already contained in Guile. For procedures not documented here please refer to the relevant chapters in the Guile Reference Manual, for -example the documentation of strings and string procedures (REFFIXME). +example the documentation of strings and string procedures +(@pxref{Strings}). All of the procedures defined in SRFI-13, which are not already included in the Guile core library, are implemented in the module @code{(srfi @@ -387,7 +444,8 @@ produce the corresponding string element. The order in which The procedure @code{string->list} is extended by SRFI-13, that is why it is included in @code{(srfi srfi-13)}. The other procedures are new. The Guile core already contains the procedure @code{list->string} for -converting a list of characters into a string (REFFIXME). +converting a list of characters into a string (@pxref{List/String +Conversion}). @deffn primitive string->list str [start end] Convert the string @var{str} into a list of characters. @@ -436,7 +494,8 @@ These procedures are called @dfn{selectors}, because they access information about the string or select pieces of a given string. Additional selector procedures are documented in the Strings section -(REFFIXME), like @code{string-length} or @code{string-ref}. +(@pxref{String Selection}), like @code{string-length} or +@code{string-ref}. @code{string-copy} is also available in core Guile, but this version accepts additional start/end indices. @@ -512,7 +571,8 @@ trimmed. The procedure @code{string-fill!} is extended from R5RS because it accepts optional start/end indices. This bindings shadows the procedure of the same name in the Guile core. The second modification procedure -@code{string-set!} is documented in the Strings section (REFFIXME). +@code{string-set!} is documented in the Strings section (@pxref{String +Modification}). @deffn primitive string-fill! str chr [start end] Stores @var{chr} in every element of the given @var{str} and @@ -943,9 +1003,10 @@ guile> @node SRFI-14 Character Set Data Type @subsection Character Set Data Type -The data type @dfn{charset} implements sets of characters (REFFIXME). -Because the internal representation of character sets is not visible to -the user, a lot of procedures for handling them are provided. +The data type @dfn{charset} implements sets of characters +(@pxref{Characters}). Because the internal representation of character +sets is not visible to the user, a lot of procedures for handling them +are provided. Character sets can be created, extended, tested for the membership of a characters and be compared to other character sets. @@ -1327,8 +1388,8 @@ EBNF grammar. The value returned by a @code{case-lambda} form is a procedure which matches the number of actual arguments against the formals in the various clauses, in order. @dfn{Formals} means a formal argument list -just like with @code{lambda} (REFFIXME). The first matching clause is -selected, the corresponding values from the actual parameter list are +just like with @code{lambda} (@pxref{Lambda}). The first matching clause +is selected, the corresponding values from the actual parameter list are bound to the variable names in the clauses and the body of the clause is evaluated. If no clause matches, an error is signalled. @@ -1382,3 +1443,4 @@ the setter of a procedure. In fact, @code{(set! (setter @var{proc}) procedure is to create a new object (a @dfn{procedure with setter}) via the @code{getter-with-setter} procedure. This procedure is also specified in the SRFI. Using it avoids the described problems. + -- 2.20.1