@c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @page @node SRFI Support @section SRFI Support Modules @cindex SRFI SRFI is an acronym for Scheme Request For Implementation. The SRFI documents define a lot of syntactic and procedure extensions to standard Scheme as defined in R5RS. Guile has support for a number of SRFIs. This chapter gives an overview over the available SRFIs and some usage hints. For complete documentation, design rationales and further examples, we advise you to 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-1:: List library. * SRFI-2:: and-let*. * SRFI-4:: Homogeneous numeric vector datatypes. * SRFI-6:: Basic String Ports. * SRFI-8:: receive. * SRFI-9:: define-record-type. * SRFI-10:: Hash-Comma Reader Extension. * SRFI-11:: let-values and let-values*. * SRFI-13:: String library. * SRFI-14:: Character-set library. * SRFI-16:: case-lambda * SRFI-17:: Generalized set! * SRFI-19:: Time/Date library. * SRFI-26:: Specializing parameters * SRFI-31:: A special form `rec' for recursive evaluation * SRFI-39:: Parameter objects @end menu @node About SRFI Usage @subsection 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 @subsection SRFI-0 - cond-expand @cindex SRFI-0 This SRFI lets a portable Scheme program test for the presence of certain features, and adapt itself by using different blocks of code, or fail if the necessary features are not available. There's no module to load, this is in the Guile core. A program designed only for Guile will generally not need this mechanism, such a program can of course directly use the various documented parts of Guile. @deffn syntax cond-expand (feature body@dots{}) @dots{} Expand to the @var{body} of the first clause whose @var{feature} specification is satisfied. It is an error if no @var{feature} is satisfied. Features are symbols such as @code{srfi-1}, and a feature specification can use @code{and}, @code{or} and @code{not} forms to test combinations. The last clause can be an @code{else}, to be used if no other passes. For example, define a private version of @code{alist-cons} if SRFI-1 is not available. @example (cond-expand (srfi-1 ) (else (define (alist-cons key val alist) (cons (cons key val) alist)))) @end example Or demand a certain set of SRFIs (list operations, string ports, @code{receive} and string operations), failing if they're not available. @example (cond-expand ((and srfi-1 srfi-6 srfi-8 srfi-13) )) @end example @end deffn @noindent The Guile core has the following features, @example guile r5rs srfi-0 srfi-4 srfi-6 srfi-13 srfi-14 @end example Other SRFI feature symbols are defined once their code has been loaded with @code{use-modules}, since only then are their bindings available. The @samp{--use-srfi} command line option (@pxref{Invoking Guile}) is a good way to load SRFIs to satisfy @code{cond-expand} when running a portable program. Testing the @code{guile} feature allows a program to adapt itself to the Guile module system, but still run on other Scheme systems. For example the following demands SRFI-8 (@code{receive}), but also knows how to load it with the Guile mechanism. @example (cond-expand (srfi-8 ) (guile (use-modules (srfi srfi-8)))) @end example It should be noted that @code{cond-expand} is separate from the @code{*features*} mechanism (@pxref{Feature Tracking}), feature symbols in one are unrelated to those in the other. @node SRFI-1 @subsection SRFI-1 - List library @cindex SRFI-1 @cindex list @c FIXME::martin: Review me! The list library defined in SRFI-1 contains a lot of useful list processing procedures for construction, examining, destructuring and manipulating lists and pairs. Since SRFI-1 also defines some procedures which are already contained in R5RS and thus are supported by the Guile core library, some list and pair procedures which appear in the SRFI-1 document may not appear in this section. So when looking for a particular list/pair processing procedure, you should also have a look at the sections @ref{Lists} and @ref{Pairs}. @menu * SRFI-1 Constructors:: Constructing new lists. * SRFI-1 Predicates:: Testing list for specific properties. * SRFI-1 Selectors:: Selecting elements from lists. * SRFI-1 Length Append etc:: Length calculation and list appending. * SRFI-1 Fold and Map:: Higher-order list processing. * SRFI-1 Filtering and Partitioning:: Filter lists based on predicates. * SRFI-1 Searching:: Search for elements. * SRFI-1 Deleting:: Delete elements from lists. * SRFI-1 Association Lists:: Handle association lists. * SRFI-1 Set Operations:: Use lists for representing sets. @end menu @node SRFI-1 Constructors @subsubsection Constructors @cindex list constructor @c FIXME::martin: Review me! New lists can be constructed by calling one of the following procedures. @deffn {Scheme Procedure} xcons d a Like @code{cons}, but with interchanged arguments. Useful mostly when passed to higher-order procedures. @end deffn @deffn {Scheme Procedure} list-tabulate n init-proc Return an @var{n}-element list, where each list element is produced by applying the procedure @var{init-proc} to the corresponding list index. The order in which @var{init-proc} is applied to the indices is not specified. @end deffn @deffn {Scheme Procedure} list-copy lst Return a new list containing the elements of the list @var{lst}. This function differs from the core @code{list-copy} (@pxref{List Constructors}) in accepting improper lists too. And if @var{lst} is not a pair at all then it's treated as the final tail of an improper list and simply returned. @end deffn @deffn {Scheme Procedure} circular-list elt1 elt2 @dots{} Return a circular list containing the given arguments @var{elt1} @var{elt2} @dots{}. @end deffn @deffn {Scheme Procedure} iota count [start step] Return a list containing @var{count} numbers, starting from @var{start} and adding @var{step} each time. The default @var{start} is 0, the default @var{step} is 1. For example, @example (iota 6) @result{} (0 1 2 3 4 5) (iota 4 2.5 -2) @result{} (2.5 0.5 -1.5 -3.5) @end example This function takes its name from the corresponding primitive in the APL language. @end deffn @node SRFI-1 Predicates @subsubsection Predicates @cindex list predicate @c FIXME::martin: Review me! The procedures in this section test specific properties of lists. @deffn {Scheme Procedure} proper-list? obj Return @code{#t} if @var{obj} is a proper list, or @code{#f} otherwise. This is the same as the core @code{list?} (@pxref{List Predicates}). A proper list is a list which ends with the empty list @code{()} in the usual way. The empty list @code{()} itself is a proper list too. @example (proper-list? '(1 2 3)) @result{} #t (proper-list? '()) @result{} #t @end example @end deffn @deffn {Scheme Procedure} circular-list? obj Return @code{#t} if @var{obj} is a circular list, or @code{#f} otherwise. A circular list is a list where at some point the @code{cdr} refers back to a previous pair in the list (either the start or some later point), so that following the @code{cdr}s takes you around in a circle, with no end. @example (define x (list 1 2 3 4)) (set-cdr! (last-pair x) (cddr x)) x @result{} (1 2 3 4 3 4 3 4 ...) (circular-list? x) @result{} #t @end example @end deffn @deffn {Scheme Procedure} dotted-list? obj Return @code{#t} if @var{obj} is a dotted list, or @code{#f} otherwise. A dotted list is a list where the @code{cdr} of the last pair is not the empty list @code{()}. Any non-pair @var{obj} is also considered a dotted list, with length zero. @example (dotted-list? '(1 2 . 3)) @result{} #t (dotted-list? 99) @result{} #t @end example @end deffn It will be noted that any Scheme object passes exactly one of the above three tests @code{proper-list?}, @code{circular-list?} and @code{dotted-list?}. Non-lists are @code{dotted-list?}, finite lists are either @code{proper-list?} or @code{dotted-list?}, and infinite lists are @code{circular-list?}. @sp 1 @deffn {Scheme Procedure} null-list? lst Return @code{#t} if @var{lst} is the empty list @code{()}, @code{#f} otherwise. If something else than a proper or circular list is passed as @var{lst}, an error is signalled. This procedure is recommended for checking for the end of a list in contexts where dotted lists are not allowed. @end deffn @deffn {Scheme Procedure} not-pair? obj Return @code{#t} is @var{obj} is not a pair, @code{#f} otherwise. This is shorthand notation @code{(not (pair? @var{obj}))} and is supposed to be used for end-of-list checking in contexts where dotted lists are allowed. @end deffn @deffn {Scheme Procedure} list= elt= list1 @dots{} Return @code{#t} if all argument lists are equal, @code{#f} otherwise. List equality is determined by testing whether all lists have the same length and the corresponding elements are equal in the sense of the equality predicate @var{elt=}. If no or only one list is given, @code{#t} is returned. @end deffn @node SRFI-1 Selectors @subsubsection Selectors @cindex list selector @c FIXME::martin: Review me! @deffn {Scheme Procedure} first pair @deffnx {Scheme Procedure} second pair @deffnx {Scheme Procedure} third pair @deffnx {Scheme Procedure} fourth pair @deffnx {Scheme Procedure} fifth pair @deffnx {Scheme Procedure} sixth pair @deffnx {Scheme Procedure} seventh pair @deffnx {Scheme Procedure} eighth pair @deffnx {Scheme Procedure} ninth pair @deffnx {Scheme Procedure} tenth pair These are synonyms for @code{car}, @code{cadr}, @code{caddr}, @dots{}. @end deffn @deffn {Scheme Procedure} car+cdr pair Return two values, the @sc{car} and the @sc{cdr} of @var{pair}. @end deffn @deffn {Scheme Procedure} take lst i @deffnx {Scheme Procedure} take! lst i Return a list containing the first @var{i} elements of @var{lst}. @code{take!} may modify the structure of the argument list @var{lst} in order to produce the result. @end deffn @deffn {Scheme Procedure} drop lst i Return a list containing all but the first @var{i} elements of @var{lst}. @end deffn @deffn {Scheme Procedure} take-right lst i Return the a list containing the @var{i} last elements of @var{lst}. @end deffn @deffn {Scheme Procedure} drop-right lst i @deffnx {Scheme Procedure} drop-right! lst i Return the a list containing all but the @var{i} last elements of @var{lst}. @code{drop-right!} may modify the structure of the argument list @var{lst} in order to produce the result. @end deffn @deffn {Scheme Procedure} split-at lst i @deffnx {Scheme Procedure} split-at! lst i Return two values, a list containing the first @var{i} elements of the list @var{lst} and a list containing the remaining elements. @code{split-at!} may modify the structure of the argument list @var{lst} in order to produce the result. @end deffn @deffn {Scheme Procedure} last lst Return the last element of the non-empty, finite list @var{lst}. @end deffn @node SRFI-1 Length Append etc @subsubsection Length, Append, Concatenate, etc. @c FIXME::martin: Review me! @deffn {Scheme Procedure} length+ lst Return the length of the argument list @var{lst}. When @var{lst} is a circular list, @code{#f} is returned. @end deffn @deffn {Scheme Procedure} concatenate list-of-lists @deffnx {Scheme Procedure} concatenate! list-of-lists Construct a list by appending all lists in @var{list-of-lists}. @code{concatenate!} may modify the structure of the given lists in order to produce the result. @code{concatenate} is the same as @code{(apply append @var{list-of-lists})}. It exists because some Scheme implementations have a limit on the number of arguments a function takes, which the @code{apply} might exceed. In Guile there is no such limit. @end deffn @deffn {Scheme Procedure} append-reverse rev-head tail @deffnx {Scheme Procedure} append-reverse! rev-head tail Reverse @var{rev-head}, append @var{tail} and return the result. This is equivalent to @code{(append (reverse @var{rev-head}) @var{tail})}, but more efficient. @code{append-reverse!} may modify @var{rev-head} in order to produce the result. @end deffn @deffn {Scheme Procedure} zip lst1 lst2 @dots{} Return a list as long as the shortest of the argument lists, where each element is a list. The first list contains the first elements of the argument lists, the second list contains the second elements, and so on. @end deffn @deffn {Scheme Procedure} unzip1 lst @deffnx {Scheme Procedure} unzip2 lst @deffnx {Scheme Procedure} unzip3 lst @deffnx {Scheme Procedure} unzip4 lst @deffnx {Scheme Procedure} unzip5 lst @code{unzip1} takes a list of lists, and returns a list containing the first elements of each list, @code{unzip2} returns two lists, the first containing the first elements of each lists and the second containing the second elements of each lists, and so on. @end deffn @deffn {Scheme Procedure} count pred lst1 @dots{} lstN Return a count of the number of times @var{pred} returns true when called on elements from the given lists. @var{pred} is called with @var{N} parameters @code{(@var{pred} @var{elem1} @dots{} @var{elemN})}, each element being from the corresponding @var{lst1} @dots{} @var{lstN}. The first call is with the first element of each list, the second with the second element from each, and so on. Counting stops when the end of the shortest list is reached. At least one list must be non-circular. @end deffn @node SRFI-1 Fold and Map @subsubsection Fold, Unfold & Map @cindex list fold @cindex list map @c FIXME::martin: Review me! @deffn {Scheme Procedure} fold proc init lst1 @dots{} lstN @deffnx {Scheme Procedure} fold-right proc init lst1 @dots{} lstN Apply @var{proc} to the elements of @var{lst1} @dots{} @var{lstN} to build a result, and return that result. Each @var{proc} call is @code{(@var{proc} @var{elem1} @dots{} @var{elemN} @var{previous})}, where @var{elem1} is from @var{lst1}, through @var{elemN} from @var{lstN}. @var{previous} is the return from the previous call to @var{proc}, or the given @var{init} for the first call. If any list is empty, just @var{init} is returned. @code{fold} works through the list elements from first to last. The following shows a list reversal and the calls it makes, @example (fold cons '() '(1 2 3)) (cons 1 '()) (cons 2 '(1)) (cons 3 '(2 1) @result{} (3 2 1) @end example @code{fold-right} works through the list elements from last to first, ie.@: from the right. So for example the following finds the longest string, and the last among equal longest, @example (fold-right (lambda (str prev) (if (> (string-length str) (string-length prev)) str prev)) "" '("x" "abc" "xyz" "jk")) @result{} "xyz" @end example If @var{lst1} through @var{lstN} have different lengths, @code{fold} stops when the end of the shortest is reached; @code{fold-right} commences at the last element of the shortest. Ie.@: elements past the length of the shortest are ignored in the other @var{lst}s. At least one @var{lst} must be non-circular. @code{fold} should be preferred over @code{fold-right} if the order of processing doesn't matter, or can be arranged either way, since @code{fold} is a little more efficient. The way @code{fold} builds a result from iterating is quite general, it can do more than other iterations like say @code{map} or @code{filter}. The following for example removes adjacent duplicate elements from a list, @example (define (delete-adjacent-duplicates lst) (fold-right (lambda (elem ret) (if (equal? elem (first ret)) ret (cons elem ret))) (list (last lst)) lst)) (delete-adjacent-duplicates '(1 2 3 3 4 4 4 5)) @result{} (1 2 3 4 5) @end example Clearly the same sort of thing can be done with a @code{for-each} and a variable in which build the result, but a self-contained @var{proc} can be re-used in multiple contexts, where a @code{for-each} would have to be written out each time. @end deffn @deffn {Scheme Procedure} pair-fold proc init lst1 @dots{} lstN @deffnx {Scheme Procedure} pair-fold-right proc init lst1 @dots{} lstN The same as @code{fold} and @code{fold-right}, but apply @var{proc} to the pairs of the lists instead of the list elements. @end deffn @deffn {Scheme Procedure} reduce proc identity lst @deffnx {Scheme Procedure} reduce-right proc identity lst @code{reduce} is a variant of @code{fold} (see above), designed for cases where the initial value is an ``identity'', so that @var{proc} can start directly from the first element of @var{lst}. Consider folding with @code{+} and initial value 0, calls would be for instance @example (fold + 0 '(4 5 6)) @result{} (+ 4 0) (+ 5 4) (+ 6 9) @end example The first call @code{(+ 4 0)} is unnecessary, adding 0 to 4 doesn't change that value. The first element @code{4} may as well be the initial ``previous'' value argument to @var{proc}. This is what @code{reduce} does. @example (reduce + 0 '(4 5 6)) @result{} (+ 5 4) (+ 6 9) @end example The @var{identity} parameter is the return when @var{lst} is empty, that's the only time @var{identity} is used. If @var{lst} has just one element, that's the return with no calls to @var{proc}. @code{reduce-right} is a similar variation on @code{fold-right}, working from the end (ie.@: the right) of @var{lst}. Calls in this case become @example (reduce-right + 0 '(4 5 6)) @result{} (+ 5 6) (+ 4 11) @end example @code{reduce} should be preferred over @code{reduce-right} if the order of processing doesn't matter, or can be arranged either way, since @code{reduce} is a little more efficient. In the above examples of course @code{+} takes any number of arguments, so it can be used on a list just with @code{apply}. An example where that's not the case would be SRFI-19 @code{add-duration} (@pxref{SRFI-19 Time}) on a list of durations, @example (use-modules (srfi srfi-19)) (reduce add-duration (make-time time-duration 0 0) (list (make-time time-duration 0 4) (make-time time-duration 0 5) (make-time time-duration 0 6))) @result{} #