7 Common Modules
The following modules are provided under the (common ...)
hierarchy, which is reserved for modules distributed with Common-Scheme.
The rationale for including something as a Common-Scheme module is
either that it cannot be supported portably or is a simple and common
feature.
7.1 combinator
Some basic higher-order functions. Although these could easily be defined portably, many Schemes already have some or all of these, and they are useful for discussing the behavior of other procedures.
true
=>#t
false
=>#f
More descriptive aliases for #t and #f which.
(constantly x)
=>(lambda args x)
Create a procedure which always returns a given value.
(always-true [args ...])
=>#t
(always-false [args ...])
=>#f
Procedures which always return true/false regardless of what it is applied to.
(identity x)
=>x
Returns the argument passed to it. Accepts only one argument, if you want multiple-values use
values
.(complement proc)
=>(lambda (x) (not (proc x)))
Create a procedure which returns the boolean complement of
proc
.(compose f g ...)
=>(lambda (x) (f (g (... x))))
Procedure composition. The returned procedure only accepts one value.
(conjoin f g ...)
=>(lambda (x) (and (f x) (g x) ...))
(disjoin f g ...)
=>(lambda (x) (or (f x) (g x) ...))
Create procedures which return the short-circuit logical and/or of any number of procedures applied to the argument passed. The returned procedure only accepts one value.
(noop [args ...])
=>unspecified
Procedure which ignores its arguments and returns an unspecified value.
I
=>(lambda (x) x)
K
=>(lambda (x y) x)
S
=>(lambda (f g x) ((f x) (g x)))
U
=>(lambda (x) (x x))
Y
=>(lambda (g) (U (lambda (f) (g (lambda (x) ((f f) x))))))
Standard single-character names for the basic lambda calculus combinators.
7.2 env
Access to current system environment, machine and user information. Slightly POSIX-centric - pretend the descriptions are generalizated to arbitrary systems.
(getenv varname)
=>string or #f
(setenv varname string)
(unsetenv varname)
Access to environment variables.
(current-host-name)
=>string
(current-host-os)
=>string
(current-host-architecture)
=>string
The current machine name, operating-system and architecture. The values for OS and architecture are not yet standardized.
(current-user-id)
=>integer
(current-group-id)
=>integer
Returns the integer user-id of the current process.
(user-id->name id)
=>string
(user-name->id string)
=>integer
Convert between user-ids and user-names.
(user-home [user])
=>string
The path string for the home directory of a user. The argument may be either a user-name string or user-id integer - if omitted the current-user-id is used.
(group-id->name id)
=>string
(group-name->id string)
=>integer
Convert between group-ids and group-names.
7.3 file
Basic file-system access. Notably lacking at the moment are access to modes and extensive permissions.
(file-exists? pathname)
=>boolean
(file-regular? pathname)
=>boolean
(file-directory? pathname)
=>boolean
(file-readable? pathname)
=>boolean
(file-writable? pathname)
=>boolean
Test various file attributes of a given pathname. These should return #f and not signal an error even if the file is missing or lacking the needed permissions.
(file-modification-time pathname)
=>number
Return the monotonic time the file was last modified. The result should be an integer comparable with
<
and related operators.(file-size pathname)
=>integer
Return the size in bytes of the file as a data stream (not necessarily the space used on disk).
(directory-fold dir kons knil)
=>object
Perform a fold operation on all files contained in the directory
dir
(in no particular order).kons
should be a procedure of two values: the string name of the file in the directory, and the accumulated result so far, starting withknil
. . and .. are not used.(directory-fold-tree dir kons knil)
=>object
Similar to
directory-fold
but descends recursiveley into all sub-directories.kons
is passed 3 values - the current parent directory pathname, the filename being processed, and the accumulated result stating withknil
.(directory-files dir)
=>list-of-strings
Return a list of files in
dir
. Could be defined as(lambda (dir) (directory-fold dir cons '()))
.(find-in-path file paths [pred])
- path/file or #fReturns the full path of the first instance of
file
inpaths
, satisfyingpred
if specified. If the file can't be found returns#f
.(create-directory pathname)
Create a new directory.
(create-directory* pathname)
Create a new directory and all
(delete-file pathname)
Delete a single file or (empty) directory.
(rename-file source target)
Move a file from one location to another.
(copy-file source target)
Copy a file.
7.4 io
Some basic input/output utilities.
(pr x ...)
Display each argument to
(current-output-port)
. An abbreviation ofscm(for-each display (list x ...)), useful since this is such a common idiom.nl
An alias for the newline sequence as output by
(newline)
.(flush-output [port])
Forces output to be flushed from
port
, which defaults to(current-output-port)
.(read-line [port])
Read a single line as a string. Should handle both Unix-style LF and network CRLF endings. The returned string does not include the line separator.
(current-error-port)
The default port errors and warnings should be printed to. Most Schemes provide this - if they don't it is simply defined as
current-output-port
.(with-input-from-port port thunk)
(with-output-to-port port thunk)
These let you dynamically change
current-input-port
andcurrent-output-port
, something which R5RS provides no means of doing, though many Schemes provide.(call-with-input-string str proc)
(call-with-output-string proc)
(with-input-from-string str thunk)
(with-output-to-string thunk)
These are the obvious extensions to SRFI-6 string ports, which again many Schemes provide but SRFI-6 does not.
(with-string-io str thunk)
When processing a string a character at a time and translating it to a new string as a result,
string-map
is in many cases insufficient since there may not be a one-to-one correspondence of characters. A more general idiom is to read and write individual characters or other values from/to string ports.with-string-io
abbreviates the common idiom of reading fromstr
and outputting to a new string:(with-output-to-string (lambda () (with-input-from-string str thunk)))
7.5 pathname
A library to manipulate pathnames as strings. Many Schemes provide something similar, and most have bugs. We provide a complete and thoroughly tested implementation.
These work the same on all platforms using the Unix-style slash ``/'' delimiter with dot ``.'' and double-dot ``..'' for the current and parent directories respectively. This is fairly universally accepted on systems these days and moreover is the pathname syntax for URLs. The procedures however, should not be used directly on URLs but only on the pathname components thereof - a URL library will likely be included in Common-Scheme soon.
An alternative strategy to manipulating pathname strings is to use records with fields for each pathname component, which depending on the application in question may be more or less efficient. Since at the operating system and web application level we must convert to a string anyway we start with the string-based API and leave records for future consideration.
With the exception of current-directory
and
set-current-directory!
all procedures are prefixed with ``path-''
for consistency. This seems no less descriptive than a ``pathname-''
prefix while being shorter. It also avoids the confusion of whether the
extra hyphen should be used in prefixes such as ``path-name-'' and
``file-name-''.
With the exception of [set-]current-directory[!]
and
path-expand
none of these procedures access the filesystem. The
library is intended to manipulate arbitrary paths which may be referring
to another system or URL, not necessarily a file on the current system.
(current-directory)
The current working directory of the process.
(set-current-directory! pathname)
Set the current working directory of the process.
(path-directory pathname)
The directory component as a string of
pathname
. This is equivalent to dirname(3).path-directory
always returns a reference to what would be a valid directory if the original file exists.(path-directory ``/usr/bin'') => ``/usr''
(path-directory ``/usr'') => ``/''
(path-directory ``/'') => ``/''
(path-directory ``.'') => ``.''
(path-directory ``..'') => ``.''
(path-directory ``'') => ``.''
(path-strip-directory pathname)
The pathname without its directory component, i.e. the base file name. This is equivalent to the GNU version of basename(3). The POSIX version differs in how files with trailing slashe(s) are handled - in POSIX the trailing slashe(s) are ignored and the basename is the last directory component. In GNU trailing slashe(s) are taken to indicate we are specifically referring to a directory and the file component is the empty string. This is consistent with most Scheme implementations (Guile is a notable exception which adheres to POSIX) as well as Perl's File::Basename module and Python's os.path module.
(string-append (path-directory f) ``/'' (path-strip-directory f))
always refers to the filef
.(path-strip-directory ``/usr/bin'') => ``bin''
(path-strip-directory ``/usr'') => ``''
(path-strip-directory ``/'') => ``''
(path-strip-directory ``.'') => ``.''
(path-strip-directory ``..'') => ``..''
(path-strip-directory ``'') => ``''
(path-extension pathname)
The extension of pathname, a string following a ``.'' at the end of a file name. The dot is not included in the result. If pathname doesn't have an extension
#f
is returned. The extension cannot be empty.(path-extension ``foo.scm'') => ``scm''
(path-extension ``foo.scm.c'') => ``c''
(path-extension ``foo'') => #f
(path-extension ``foo.'') => #f
(path-extension ``foo..'') => #f
(path-extension ``'') => #f
(path-strip-extension pathname)
Returns
pathname
without the trailing dot and extension if there is an extension, otherwise returns the original pathname.(path-strip-extension ``foo.scm'') => ``foo''
(path-strip-extension ``foo.scm.c'') => ``foo.scm''
(path-strip-extension ``foo'') => ``foo''
(path-strip-extension ``foo.'') => ``foo.''
(path-strip-extension ``foo..'') => ``foo..''
(path-strip-extension ``'') => ``''
(path-replace-extension pathname newext)
Returns
pathname
with the extension replaced bynewext
. Itpathname
has no extension thennewext
is appended as a new extension. This could be defined as:(string-append (path-strip-extension pathname) ``.'' newext)
(path-absolute? pathname)
Returns #f iff
pathname
is absolute (i.e. begins with a ``/'').(path-expand pathname [cwd])
Expands
pathname
to an absolute pathname if not already absolute. The pathname is taken relative tocwd
which defaults to(current-directory)
. Tilde prefixed paths of the form `` user/file'' are expanded to the user's home directory, and `` /file'' is expanded to the current user's home directory.(path-relative pathname [cwd])
If
pathname
is a file insidecwd
(default(current-directory)
), then the relative shortened form is returned, otherwise #f is returned.(path-relative ``/usr/local/bin/ls'' ``/usr/local'') => ``bin/ls''
(path-relative ``/usr/bin/ls'' ``/usr/local'') => #f
(path-normalize pathname)
Removes ``.'' and ``..'' components from
pathname
and reduces multiple slashes to a single slash.(path-build components ...)
Symbolic path builder. Concatenates all components separated by slashes, taking care not to add an extra slash if one of the components already has a trailing slash. Symbols and numbers may be passed and are converted to strings as with symbol->string and number->string respectively. If one of the components is itself a list, it is expanded recursively with each subcomponent separated by slashes.
7.6 process
Handling subprocesses.
(process-run command [args ...])
Runs a command string in the host system's shell. Command should be an arbitrary command string - any subsequent arguments are escape and appended to the command. Returns a true value if the command succeeds.
(process-run-and-exit command [args ...])
Same as above, but exits immediately afterwards. This may be more effeciently implemented on some platforms.
(with-input-from-process command thunk)
Runs
thunk
with(current-input-port)
bound to the command's output.command
may be a string or a list of command followed by arguments as in the above procedures.(with-output-to-process command thunk)
Runs
thunk
with(current-output-port)
bound to the command's input.(with-process-io command thunk)
=>object
Runs
thunk
with(current-input-port)
and(current-output-port)
bound to the command's input and output respectively.(process-output->string command [args ...])
Runs
command
and returns the output as an accumulated string.(process-output->string-list command [args ...])
=>list
Runs
command
and returns the output as an accumulated list of strings, one for each line of the output.(shell-escape string)
Escapes any shell meta-characters in string.
7.7 regex
Standardized regex API. Note the name of the module is the least common prefix of the common abbreviated plurals of regular expression: ``regexes,'' ``regexps,'' and ``regexen.''
(string->regexp str)
Compile
str
into a regexp object, which is not necessarily of disjoint type from other Scheme objects.(regexp? x)
Returns #f iff
x
can be passed torxmatch
.(rxmatch rx str)
Matches regexp object
rx
against the stringstr
, returning an rxmatch object on success and #f on failure. The rxmatch object is of an opaque type, not necessarily disjoint from other Scheme types, which may be accessed with the procedures below.(rxmatch-num-matches m)
Return the number of matches in m, counting at 1 for a valid overall match and 1 for each submatch. If m is not a valid rxmatch object 0 is returned.
(rxmatch-start m [count])
(rxmatch-end m [count])
Returns the start/end index of the
count
submatch in the original string, defaulting to the start/end index of the total match if count is 0 or not specified.(rxmatch-substring m [count])
string
Returns the substring corresponding to the
count
submatch in the original string, defaulting to the total match if count is 0 or not specified.
7.8 string-cursor
An alternate interface to strings, friendly to non-array-based string implementations such as ropes and variable-width encodings, just as efficient and yet more flexible because the same interface allows working with ``character'' units of different conceptual levels.
(string-cursor? x)
=>boolean
Returns #t iff
x
could be valid as a cursor object. Cursors are an opaque and not necessarily disjoint type, so this doesn't guarantee the object really is a cursor.(string-start-cursor str)
=>string-cursor
Return a new cursor pointing to the start of the string.
(string-end-cursor str)
=>string-cursor
Return a new cursor pointing just past the end of the string. It is an error to reference such a cursor.
(string-cursor-start? str c)
=>boolean
Returns #t iff
c
points to the start of stringstr
.(string-cursor-end? str c)
=>boolean
Returns #t iff
c
points just past the end of stringstr
.(string-cursor=? str c1 c2)
=>boolean
Returns #t iff
c1
andc2
point to the same position withinstr
.(string-cursor-next str c1)
=>string-cursor
Returns the next cursor after
c1
in stringscm
at the Unicode codepoint level.(string-cursor-prev str c2)
=>string-cursor
Returns the previous cursor before
c1
in stringscm
at the Unicode codepoint level.(string-cursor-ref str c1)
=>char
Returns the character at position
c1
in stringstr
at the Unicode codepoint level.(string-cursor-substring str c1 c2)
=>string
Returns the substring between cursors
c1
(inclusive) andc2
(non-inclusive) in stringstr
.(string-cursor-next-grapheme str c1)
=>string-cursor
Returns the next cursor after
c1
in stringscm
at the Unicode grapheme level.(string-cursor-prev-grapheme str c1)
=>string-cursor
Returns the previous cursor before
c1
in stringscm
at the Unicode grapheme level.(string-cursor-ref-grapheme str c1)
Returns the character at position
c1
in stringstr
at the Unicode grapheme level. This may be a single native Scheme char, or a substring for compound characters.
7.9 tcp
Simplest TCP interface I could come up with.
(with-tcp-io host port thunk)
Open a TCP connection to host
host
on portport
, and run thunk with current input and output bound to that connection. The connection is implicitly closed when thunk returns.(tcp-serve handler port [interfaces])
Beware, this API will probably change.
Listen for TCP connections on port(s)
port
(currently only a single integer port is accepted portably), and for each one call handler on the single argument of the connecting IP address in string form, with input and output bound to the client connection. The connection is implicitly closed when the handler returns. If possible multiple handlers should be able to run simultaneously.