Table of Contents
Larceny implements the Scheme programming language as defined by IEEE Standard 1178-1990, the Revised5 Report, the Revised6 Report, and ERR5RS. Those language standards serve as Larceny's primary documentation.
This manual describes aspects of Larceny that are not described by the IEEE standard, the Revised Reports, or ERR5RS. For the most current version of this manual, please visit Larceny's main web page. That page also links to the Common Larceny User Manual and to the Larceny mailing list.
To report bugs, please send email to the Larceny
developers at <larceny@ccs.neu.edu>, or submit a
bug ticket using Larceny's
Trac system.
There are three main varieties of Larceny.
Native Larceny is the fastest and most convenient variety of Larceny. It compiles directly to native machine code for Intel x86-32 or SPARC microprocessors running Windows, Linux, MacOS X, or Solaris operating systems.
Petit Larceny compiles to C instead of machine code. It runs on most Unix machines, including PowerPC Macintoshes with MacOS X.
Common Larceny compiles to JIT-compiled IL on Microsoft's Common Language Runtime (CLR) or Mono. It provides access to the .NET libraries from Scheme.
The current versions of Larceny are available for download at Larceny's main web page.
Twobit and Larceny are distributed in two forms: as a precompiled binary, or as source code that can be used to reconstruct any of the precompiled binary distributions. Unless you intend to modify Larceny yourself, you do not need to download the source code.
If you are installing or running Common Larceny, please consult the Common Larceny User Manual instead of becoming confused by the instructions in this manual.
Unpack the distribution files with an appropriate command such as one of the following:
tar -xzf larceny-X.Y-bin-native-sparc-solaris.tar.gz tar -xzf larceny-X.Y-bin-native-ia32-macosx.tar.gz tar -xzf larceny-X.Y-bin-native-ia32-linux86.tar.gz tar -xzf larceny-X.Y-bin-native-ia32-win32.tar.gz tar -xzf larceny-X.Y-bin-petit-stdc-macosx.tar.gz tar -xzf larceny-X.Y-src.tar.gz
This will create a directory called larceny in your current working
directory. Assuming you have unpacked a binary distribution, that
directory will contain the following files:
larceny.bin Run-time system larceny.heap Heap image with all libraries, FFI, and compiler twobit.heap Heap image with some libraries and compiler larceny Shell script that runs larceny.heap twobit Shell script that runs twobit.heap scheme-script Shell script that runs Scheme scripts compile-stale Scheme script that compiles ERR5RS/R6RS libraries startup.sch Pathnames for the require and autoload features
If you unpacked the source code there will be many other files and
directories, but larceny.bin, larceny.heap, and twobit.heap
will not be present. You can reconstruct those files from their
source code, but that process requires a working version of Larceny
or MzScheme; unless you're porting Larceny or Petit Larceny to a
brand new target architecture, it's easier to obtain those three
files from a binary distribution of Larceny.
The scripts and heap images are discussed in the following section.
You should decide where you want to install Larceny;
let's suppose you want to install it in /usr/local/bin and
/usr/local/lib/larceny. Copy larceny, twobit,
and scheme-script to /usr/local/bin and edit the definition of
LARCENY_PATH at the head of each file to point to the correct
directory:
LARCENY_PATH=/usr/local/lib/larceny
Then move or copy larceny.bin, larceny.heap, twobit.heap,
startup.sch, and the lib directory to /usr/local/lib/larceny.
You should now be able to run Larceny by typing "larceny" at a
Unix prompt. On Windows, type "larceny.bat".
Before you can run Larceny in ERR5RS or R6RS modes, you may have to compile the ERR5RS/R6RS runtime and standard libraries, which is accomplished as follows:
$ ./larceny
Larceny v0.96 "Fluoridation" (...)
> (require 'r6rsmode)
> (larceny:compile-r6rs-runtime)
> (exit)This step is definitely required if you are using Petit Larceny or building any variety of Larceny from source code. With the prebuilt native varieties of Larceny, however, this step should not be necessary.
Compiling the ERR5RS/R6RS runtime as shown above causes all previously compiled ERR5RS/R6RS libraries and top-level programs to become stale. That means those previously compiled files will need to be recompiled or removed.
If the lib/R6RS directory and its subdirectories are read-only,
then the standard libraries will not be touched, modified, or
recompiled by accident.
Unless you are doing compiler development, you should use the
"larceny" script, not the "twobit" script. The difference
is that larceny runs the heap image named "larceny.heap"
while twobit runs the heap image named "twobit.heap".
Both of these heap images contain the Twobit compiler and the
compile-file procedure that is used to compile files of Scheme code,
but they differ in other ways.
In "larceny.heap", every expression is compiled before it is
evaluated, but the internals of the Twobit compiler are hidden
(except for compilation switches).
In "twobit.heap", some of the libraries that are present in
"larceny.heap" are missing, and all internals of Twobit are exposed:
every top-level name in Twobit is bound in the interaction environment
and may be changed interactively, with immediate effect. Since
compiler development can be a risky business, "twobit.heap" uses an
interpreter to evaluate the Scheme code you load and type — the
interpreter is unaffected by changes to Twobit.
If you are using "twobit.heap" for compiler development,
you will need the source code as well as a binary distribution
of Larceny.
Larceny runs in any of four distinct modes:
R5RS traditional read/eval/print loop (the default) ERR5RS ERR5RS read/eval/print loop R6RS batch execution of R6RS top-level programs Scheme script batch execution of R6RS Scheme scripts
These modes correspond to the four distinct kinds of Scheme programs that are described by the current de facto standards for Scheme. (IEEE/ANSI Std 1178 is so similar to the R5RS standard that Larceny implements both languages in R5RS mode.)
When you start Larceny in R5RS mode (the default), you will be presented with a banner message and the read-eval-print loop's prompt:
% larceny
Larceny vX.Y "<version_name>" (MMM DD YYYY HH:MM:SS, ...)
larceny.heap, built ...
>You can enter a Scheme expression at the prompt. After a complete expression has been read, it will be evaluated and its results printed.
In native Larceny, the expression is evaluated by compiling it to native machine code, which is then executed. In Petit Larceny, the expression is evaluated by an interpreter because compiling to C, running the C compiler, and loading the compiled C code would take too long. Interpreted code behaves like compiled code, so most of what this manual says about the compiler is also true of Petit Larceny's interpreter.
By default, Larceny's Twobit compiler makes several assumptions that allow it to generate faster code; for example, the compiler assumes Scheme's standard procedures will not be redefined. To obtain strict conformance to R5RS semantics at the expense of slower code, evaluate the expression
(compiler-switches 'standard)
For more information on compiler switches, see the section of this user manual devoted to performance.
To interact with Larceny's ERR5RS read/eval/print loop,
specify the -err5rs option on Larceny's command line:
% larceny -err5rs
Larceny v0.95 "First Safety" (...)
ERR5RS mode (no libraries have been imported)Since no libraries have been imported, the only forms you can evaluate are constant literals, variable references (but no variables have been imported!), procedure calls (but no procedure values are accessible!), library definitions, and import forms. The first thing you'll want to do is to import some libraries, such as:
> (import (rnrs base)
(rnrs io simple)
(err5rs records syntactic))Once you have imported (rnrs base) or a composite library
that includes it, you can evaluate definitions and use
all other syntax and variables you have imported.
As an extension to ERR5RS, Larceny attempts to load libraries automatically when they are first imported. Autoloading makes interactive development and separate compilation much more convenient.
All of Larceny's predefined libraries can be autoloaded.
To enable autoloading of other ERR5RS/R6RS libraries, you can:
-path command-line option
current-require-path
startup.sch in Larceny's root directory
lib directory
Larceny automatically loads ERR5RS/R6RS libraries when
they are first imported. This is usually the most
convenient way to load a library, but autoloading
can't be used to load a top-level program. Explicit
loading is needed for top-level programs, for libraries
that don't reside in Larceny's
current-require-path,
and for libraries that are defined in files whose names
do not follow Larceny's
standard naming conventions.
Explicit loading is the only portable way for ERR5RS programs to load a library.
Explicit loading also makes it possible to write portable programs whose source files conform to both the R5RS and ERR5RS. Two different configuration files, one for the R5RS and one for ERR5RS, can perform all of the imports and loads needed to run the program.
For explicit loading of nonstandard libraries, top-level programs, or unadorned R5RS-style code from a file, you must first import a suitable load procedure:
> (import (err5rs load))
Loading a library does not automatically import it. To use the variables and syntax that are exported by a library, you must import that library explicitly:
> (load "lib/R6RS/larceny/benchmarking.sls")
> (import (larceny benchmarking))
> (time (vector-for-each + (make-vector 1000000 0)))
Words allocated: 3095752
Words reclaimed: 0
Elapsed time...: 111 ms (User: 104 ms; System: 8 ms)
Elapsed GC time: 4 ms (CPU: 4 in 8 collections.)In Larceny, you may omit the call to load because the
(larceny benchmarking) library will be autoloaded when
it is imported. In most other ERR5RS systems, however,
you must load all of the nonstandard libraries that will
be imported by a top-level program or library before you
load that top-level program or library.
You do not have to import those libraries into the ERR5RS top level, however, unless you want to use the variables and syntax exported by those libraries in the expressions and definitions you evaluate at the top level.
Larceny predefines several nonstandard libraries in addition to the standard ERR5RS and R6RS libraries, and autoloads them for your convenience. The predefined, autoloadable libraries include:
R6RS standard libraries:
(rnrs base (6)) ; R6RS chapter 9 (rnrs unicode (6)) ; R6RS library chapter 1 (rnrs bytevectors (6)) ; R6RS library chapter 2 (rnrs lists (6)) ; R6RS library chapter 3 (rnrs sorting (6)) ; R6RS library chapter 4 (rnrs control (6)) ; R6RS library chapter 5 (rnrs exceptions (6)) ; R6RS library section 7.1 (rnrs conditions (6)) ; R6RS library sections 7.2 and 7.3 (rnrs io ports (6)) ; R6RS library sections 8.1 and 8.2 (rnrs io simple (6)) ; R6RS library sections 8.1 and 8.3 (rnrs files (6)) ; R6RS library chapter 9 (rnrs programs (6)) ; R6RS library chapter 10 (rnrs arithmetic fixnums (6)) ; R6RS library section 11.2 (rnrs arithmetic flonums (6)) ; R6RS library section 11.3 (rnrs arithmetic bitwise (6)) ; R6RS library section 11.4 (rnrs syntax-case (6)) ; R6RS library chapter 12 (rnrs hashtables (6)) ; R6RS library chapter 13 (rnrs enums) ; R6RS library chapter 14 (rnrs (6)) ; R6RS library chapter 15 (rnrs eval (6)) ; R6RS library chapter 16 (rnrs mutable-pairs (6)) ; R6RS library chapter 17 (rnrs mutable-strings (6)) ; R6RS library chapter 18 (rnrs r5rs (6)) ; R6RS library chapter 19
R6RS standard libraries that are autoloadable but deprecated in Larceny:
(rnrs records procedural (6)) ; R6RS library section 6.3 (deprecated) (rnrs records inspection (6)) ; R6RS library section 6.4 (deprecated) (rnrs records syntactic (6)) ; R6RS library section 6.2 (deprecated)
Other autoloadable libraries:
(err5rs records procedural) ; ERR5RS records (procedural API) (err5rs records inspection) ; ERR5RS records (inspection API) (err5rs records syntactic) ; ERR5RS records (syntactic API) (err5rs load) ; ERR5RS load procedure (rnrs load) ; equivalent to (err5rs load) (larceny load) ; extension of (err5rs load) (larceny compiler) ; separate compilation for ERR5RS/R6RS (larceny benchmarking) ; timing facilities (larceny records printer) ; custom printing of records (r5rs) ; approximates the R5RS top level (explicit-renaming) ; macro system with explicit renaming
Larceny's autoload feature locates ERR5RS/R6RS libraries
by performing a depth-first search of the directories
that belong to Larceny's
current-require-path.
Libraries will not be autoloaded unless they are defined
in files whose names follow
Larceny's standard conventions.
The
current-require-path
is initialized by the startup.sch file in Larceny's root
directory.
Larceny's -path command-line option adds a single directory
to the directories in the
current-require-path.
To execute a top-level R6RS program that is contained
within a file named pgm, type:
larceny -r6rs -program pgm
The -program option can be omitted, in which case
Larceny will read the top-level program from standard
input:
larceny -r6rs < pgm
If you omit the -program option and do not redirect
standard input, then Larceny will wait patiently
for you to type a complete top-level program into
standard input, terminating it with an end-of-file.
You probably don't want to do that. Had you wanted to type R6RS code at Larceny, you'd be using ERR5RS mode instead.
The R6RS standard does not specify any way for a top-level program to define its own libraries. Portable R6RS programs are therefore limited to importing a subset of the R6RS standard libraries.
As an extension to the R6RS, Larceny allows R6RS top-level programs and Scheme scripts to import any libraries that are predefined in Larceny's ERR5RS mode.
As another extension to the R6RS, Larceny allows
R6RS top-level programs to import any libraries
that can be found in the directory specified by the
-path option on Larceny's command line using
Larceny's standard translation
from library names to file names.
Note that the -path option cannot be used by Scheme scripts,
because command-line options are passed along to the Scheme
script without being interpreted by the scheme-script processor.
We emphasize that this extension is non-portable. It is not supported by Ikarus, which is currently the only other system that implements a substantial fraction of the R6RS. (Ikarus may provide a similar feature, but Ikarus's mapping from library names to file names is incompatible with Larceny's mapping.)
As an extension to the R6RS, Larceny allows a top-level program or Scheme script to define R6RS libraries within the file that contains the top-level program or Scheme script, before the import form that begins the top-level program. These libraries must be arranged so that no library depends upon libraries that come later in the file.
We emphasize that this extension is non-portable. It is not supported by Ikarus.
On most Unix systems (including MacOS X and Linux), Larceny's
scheme-script will execute Scheme scripts as described in R6RS
non-normative appendix D, with or without the optional script
header. To make Scheme scripts executable in their own
right, without executing scheme-script directly, add Larceny's
root directory to your path as described in doc/HOWTO-INSTALL.
Suppose, for example, that /home/myself/hello is an R6RS
Scheme script whose first line is the optional script header
(#!/usr/bin/env scheme-script). If you do not have execute
permission for this script, or Larceny's root directory is
not in your path, you can still run the script from
Larceny's root directory as follows:
% ./scheme-script /home/myself/hello
If you have execute permission for the script, and Larceny's root directory is in your path, you can also run the script as follows:
% /home/myself/hello
If, in addition, the directory that contains the script is in your path, you can run the script as follows:
% hello
Suppose hello.sch contains the following R5RS code:
(display "Hello world!")
(newline)
(exit)You can run hello.sch as a script by executing Larceny as follows:
% larceny -nobanner -- hello.sch
You can redirect Larceny's standard input, in which case you may want to eliminate the herald announcement and the read/eval/print loop's prompt:
% larceny -nobanner -- -e "(begin (herald #f) (repl-prompt values))" \
< hello.schFor an explanation of why that works, which may suggest other creative uses of Larceny, ask for help:
% larceny -help
In R6RS modes, errors should result in an error message followed by a clean exit from the program, but some errors may enter the debugger; this is a known bug.
If your program encounters an error in an interactive mode (R5RS or ERR5RS), it will enter the debugger; this is believed to be a feature.
Despite its crudity, and to some extent because of it, Larceny's debugger works at least as well with optimized compiled code as with interpreted code.
If you type a question mark at the debugger prompt, the debugger will print a help message. That message is more helpful if you understand the Twobit compiler and Larceny's internal representations and invariants, but this manual is not the place to explain those things.
The debugging context is saved so you can exit the debugger and re-enter it from the main read/eval/print loop's prompt:
> (debug)
The debugger is pretty much a prototype; you don't need to tell us how bad it is.
When attempting to run an R6RS program, you may see
a warning about "loading source in favor of stale
fasl file",
following by a long series of error messages about
syntactic keywords used as a variable, ending with
the kind of error you'd expect to see when a large
R6RS program is fed to a Scheme compiler that was
expecting to see R5RS-compatible code. That means
the R6RS runtime and standard libraries were not
installed correctly, or their source files have been
touched or modified since they were last compiled.
To fix the problem,
recompile the R6RS standard libraries as described in step 4 of doc/HOWTO-BUILD.
The precompiled binary forms of Larceny should run on
most machines with the appropriate processor and operating
system, but the executable program "larceny.bin" may be
incompatible with very old or with very new versions of
the processor or operating system. If that appears to be
the case, you should see whether a newer version of Larceny
fixes the problem. If not, you may be able to use
MzScheme v37x to recompile larceny.bin from source.
First, though, you should report the problem
to us (larceny@ccs.neu.edu).
Please report success stories as well.
If something goes wrong while
compiling the ERR5RS/R6RS runtime,
make sure you are running the copy of Larceny you think
you are running and have read and write permission
for lib/R6RS and all its subdirectories and files.
If you get an error message about something being
"expanded against a different build of this library",
then one or more of the compiled files in lib/R6RS
and its subdirectories has gone
stale.
Removing all .slfasl files from lib/R6RS and its
subdirectories will eliminate the stale file(s).
Don't remove the .sch or .sls files.
If Larceny attempts to autoload an imported ERR5RS/R6RS
library but cannot find the library, then the library
may be defined in a file that doesn't follow
Larceny's standard naming conventions.
Another possibility is that the -path option was
omitted or incorrect.
If an ERR5RS/R6RS library is compiled, then all compiled
libraries and top-level programs that depend upon it must
also be recompiled. In particular, recompiling the standard
R6RS runtime will invalidate all compiled libraries and
top-level programs. Larceny's compile-stale script
and the
compile-stale-libraries
procedure of (larceny compiler) make it convenient
to recompile all of the libraries and top-level
programs within any given directory in an order
consistent with their dependencies.
Please report all crashes with as much information is possible; a backtrace from a debugger or a core dump is ideal (but please do not mail the core dump without contacting us first). Larceny's run-time system is compiled with full debugging information by default and a debugger like GDB should be able to provide at least some clues.
By default, Larceny's Twobit compiler assumes that Scheme's standard procedures will not be redefined, which allows the compiler to generate inline code for many calls to standard procedures. If you want to be able to redefine standard procedures, then you should evaluate the expression
(integrate-procedures #f)
After this expression has been evaluated, the compiler will generate slower code.
To make the compiler generate faster code, you can promise not to redefine standard procedures and not to redefine any top-level procedure while it is running. To make this promise, evaluate
(compiler-switches 'fast-safe)
To view the current settings of Twobit's numerous compiler switches, evaluate
(compiler-switches)
All of Twobit's compiler switches are procedures whose setting can be changed by passing the new value of the switch as an argument.
For more information, evaluate
(help)
Some of the help information that will be printed may be irrelevant to the heap image you are using.
Larceny's default lexical syntax extends the lexical syntax required by the R5RS, R6RS, and ERR5RS standards.
The R6RS forbids most lexical extensions, however, so Larceny provides several mechanisms for turning its lexical extensions on and off.
By default, Larceny recognizes several Larceny-specific flags of the form permitted by the R6RS. The flag you are most likely to encounter represents one of Larceny's unspecified values:
#!unspecified
Certain other flags have special meanings to Larceny's
read and get-datum procedures. They are described below.
By default, Larceny is case-sensitive.
This global default can be overridden by specifying
—foldcase or —nofoldcase on Larceny's command line,
or by changing the value of Larceny's case-sensitive? parameter.
The case-sensitivity of a particular textual input port
is affected by reading one of the following flags from
the port using the read or get-datum procedures:
#!fold-case
#!no-fold-caseThe #!fold-case flag enables case-folding on data read from
the port by the read and get-datum procedures, while the
#!no-fold-case flag disables case-folding. The behavior
established by one of these flags extends to the next flag
read from the port by read or get-datum.
Both #!fold-case and #!no-fold-case evaluate to an
unspecified value. To obtain the effect of one of these flags
while treating it as a comment, place #; in front of the flag.
When a port is first opened, the Larceny-specific lexical extensions that are accepted on the port are determined by Larceny's lexical parameters.
The following flags change the case-sensitivity and lexical extensions on the specific port from which they are read:
#!r6rs ; implies #!no-fold-case, negates other flags
#!r5rs ; implies #!fold-case, #!err5rs
#!err5rs ; allows Larceny-specific extensions
#!larceny ; implies #!no-fold-case, #!err5rsThe #!r6rs flag is a comment, while all of Larceny's other
flags evaluate to an unspecified value. To obtain the effect
of a flag other than #!r6rs while treating it as a comment,
place #; in front of the flag.
The R6RS requires implementations to treat #!r6rs as a
comment; it is the only flag that implementations of the R6RS
are required to treat as a comment. Since the #!r6rs flag
behaves differently from all other flags, it is deprecated.
When given no argument, these parameters return the current default for some aspect of the lexical syntax that will be accepted on newly created ports. When given an argument, these procedures change the default as specified by the argument.
(case-sensitive? [boolean]) => boolean
Determines whether newly created textual ports default to case-sensitive.
Procedure read-larceny-weirdness?
(read-larceny-weirdness? [boolean]) => boolean
Determines whether newly created textual ports allow
Larceny's usual extensions to R5RS lexical syntax.
This parameter also determines whether newly created
ports allow # as an insignificant digit; this is
required by the R5RS, but disallowed by the R6RS.
Procedure read-traditional-weirdness?
(read-traditional-weirdness? [boolean]) => boolean
Determines whether newly created textual ports allow certain lexical extensions that are deprecated in Larceny. These extensions include symbols enclosed by vertical bars and read-time evaluation.
For the current semantics of these parameters, please consult the Larceny developers' web page that describes Larceny's lexical syntax.
In Larceny, file names generally follow Unix conventions, even on Windows. The following suffixes have special meanings to some components of Larceny.
.sls
is the preferred suffix for files that consist
of ERR5RS/R6RS-compatible library definitions.
.sch
is the preferred suffix for files that contain R5RS
source code.
.scm
is an alternative suffix for files that contain R5RS source code.
.slfasl
is the suffix for files that contain the pre-compiled
form of ERR5RS/R6RS-compatible code.
.fasl
is the suffix for files that contain the pre-compiled form of R5RS code.
.mal
is the preferred suffix for files that contain MacScheme
assembly language in symbolic form.
.lap
is the suffix for files that contain MacScheme assembly language.
.lop
is the suffix for files that contain machine code
segments in the form expected by Larceny's heap linker.
.heap
is the suffix for files that contain an executable heap
image (must be combined with the
larceny.bin runtime).
Larceny's root directory should contain the following files:
larceny
twobit
scheme-script
larceny.bin
larceny.heap
twobit.heap
startup.schThe following subdirectories are also essential for correct operation of some features of some modes in some varieties of Larceny:
include
lib
lib/Base
lib/Debugger
lib/Ffi
lib/MzScheme
lib/R6RS
lib/SRFI
lib/Standard
lib/TeachPacksThe include subdirectory is used when compiling files with
Petit Larceny.
The startup.sch file tells Larceny's require procedure to
search some of the lib subdirectories for libraries that are
loaded dynamically.
The R6RS does not specify any mapping from library names to files or to other locations at which the code for a library might be found. As R6RS non-normative appendix E puts it:
Implementations may take radically different approaches to storing source code for libraries, among them: files in the file system where each file contains an arbitrary number of library forms, files in the file system where each file contains exactly one library form, records in a database, and data structures in memory….Implementations may provide a means for importing libraries…. | ||
| -- | ||
In other words, implementations are allowed to extend the R6RS with arbitrary mechanisms for resolving references to imported libraries, but R6RS programs that rely on such mechanisms are not portable. In particular, R6RS libraries are not portable.
Larceny provides four distinct Larceny-specific mechanisms that non-portable R6RS programs can use to import or to define libraries:
(larceny compiler),
may be placed in one of the directories that are searched
by Larceny's
autoload feature, provided
those libraries are located in files that follow Larceny's
standard naming conventions as described in the next section.
-path option
to specify a directory that contains other libraries
the program may import, provided those libraries are
located in files that follow Larceny's standard naming
conventions as described in the next section.
ERR5RS programs may use any of those four mechanisms, and may also use a fifth mechanism: An ERR5RS program can be written as a little configuration program that loads the program's libraries from files before any libraries are imported. This fifth mechanism is portable, but is not available to R6RS programs.
Suppose Larceny's -path option is used to specify
a certain directory, and the program imports a
nonstandard library whose name is of the form
(name1 name2 … lastname).
Larceny will search for that library in the following
files:
directory/name1/name2/…/lastname.slfasl
directory/name1/name2/…/lastname.sls
directory/name1/name2.slfasl
directory/name1/name2.sls
directory/name1.slfasl
directory/name1.sls
The search starts with the first of those file names, continues with the following file names in order, and ends when a file with one of those names is found. The imported library must be one of the libraries defined within the first file found by this search, since the search is not continued after that first file is found (except as noted in the next paragraph).
If the search ends by finding a file whose name ends
with .slfasl, then Larceny checks to see whether
there is a file in the same directory with the same
root name but ending with .sls instead of .slfasl.
If the .sls file has been modified since the .slfasl
file was last modified, then a warning is printed and
the .sls file is loaded instead of the .slfasl file.
Otherwise the .slfasl file is loaded.
The R6RS allows arbitrary mappings from library names to library
code. Larceny takes advantage of this by ignoring version
numbers when mapping library names to files, and by (virtually)
rewriting any version number that may be specified in the
definition of a library so it matches any version specification
that appears within the import form. Furthermore Larceny
allows different versions of the same library to be imported,
but Larceny's algorithm for resolving library references
ensures that the different versions of a library will be
identical except for their version numbers, which have no
meaningful semantics. Although Larceny's treatment of versions
conforms to the R6RS specification, it should be clear that
version numbers serve no purpose in Larceny. Since the R6RS
version feature has no usefully portable semantics, it is
deprecated.
In R5RS mode, Larceny's -path option may be used to
specify a directory to be searched by the require
procedure, which takes a single symbol libname as
its argument.
The require procedure will search for the following
files in every directory that is part of the current
require path, starting with the directory specified
by the -path option:
libname.fasl
libname.sch
libname.scm
These files are expected to contain R5RS code, not library definitions. Otherwise the search proceeds much the same as when searching for an ERR5RS/R6RS library.
The require path is specified by startup.sch in Larceny's
root directory, but may be changed dynamically using the
current-require-path parameter. Changing the require path
is not recommended, however, because Larceny relies on the
require path for dynamic loading of libraries used by several
important features of Larceny, notably ERR5RS and R6RS modes.
libname must be a symbol that names an R5RS-compatible library within the current require path.
If the library has not already been loaded, then it is
located and loaded. If the library is found and loaded
successfully, then require returns true; otherwise an
error is signalled.
If the library has already been loaded, then require
returns false without loading the library a second time.
Procedure current-require-path
(current-require-path [stringlist]) => stringlist
The optional argument is a list of directory names
(without slashes at the end) that should be searched
by require and (in ERR5RS/R6RS modes)
by Larceny's autoload
feature.
Returns the list of directory names that will be
searched.
This chapter explains how you can use Larceny to compile Scheme source code to native machine code.
The native varieties of Larceny have a just-in-time compiler that compiles to native code automatically whenever you evaluate an expression, load a source file, or import a source library. Even so, files will load faster if they are compiled ahead of time.
Petit Larceny does not have a just-in-time compiler, so compiling ahead of time is the only way to enjoy the speed of native machine code in Petit Larceny.
Common Larceny uses an interpreter for expressions
that are typed at the interactive read/eval/print
loop, but files will be compiled as they are loaded
if you specify Larceny.fasl on the command line.
For more information on compiling files in Common
Larceny, please consult the
Common Larceny User Manual.
The main disadvantage of compiling files and libraries is that compiled code goes stale when its original source code is changed or when a library on which the compiled code depends is changed or recompiled. Stale compiled code can be dangerously inconsistent with libraries on which it depends, so Larceny checks for staleness and refuses to execute a stale library or program.
On Unix machines, the most convenient way to compile
a group of ERR5RS/R6RS libraries and top-level programs
is to use the compile-stale script in Larceny's root
directory.
If Larceny's root directory is in your execution path,
then there are just two steps:
cd to change to the directory that contains
the ERR5RS/R6RS files you want to compile. (Files
that lie within subdirectories of that directory will
be compiled also.)
compile-stale script.
For example:
% cd lib/R6RS
% compile-staleOn non-Unix machines, you can accomplish the same thing
using Larceny's ERR5RS mode and the (larceny compiler)
library:
% pushd lib\R6RS
% ..\..\larceny.bat -err5rs
Larceny v0.96 "Fluoridation"
ERR5RS mode (no libraries have been imported)
> (import (larceny compiler))
> (compile-stale-libraries)To compile individual files, use the compile-file or
compile-library procedures that are exported by
(larceny compiler).
Compiles sourcefile, which must be a string naming
a file that contains R5RS source code.
If faslfile is supplied as a second argument,
then it must be a string naming the file that will
contain the compiled code; otherwise the name of
the compiled file is obtained from sourcefile
by replacing the ".sch" or ".scm" suffix with
".fasl".
For ERR5RS/R6RS libraries and top-level programs, see above.
ERR5RS is still being developed, so the specifications described below are subject to change as its standard libraries are revised.
This section describes the (err5rs load) library.
Loads ERR5RS code from filename, evaluating each form as though it had been entered at the interactive read/eval/print loop.
The load procedure should be used only at an interactive top
level and in files that will be loaded into an interactive top
level. Calls to the load procedure have no effect at compile
time, and should not appear in files that will be compiled
separately; use the library and import syntaxes instead.
When a procedure is said to be equivalent to an R6RS procedure, the equivalence holds only when all arguments have the properties required of them by the R6RS specification. ERR5RS does not mandate R6RS exception semantics for programs that violate the specification.
This section describes the (err5rs records procedural) library.
(make-rtd name fieldspecss parent-rtd)
(make-rtd name fieldspecss parent-rtd option …)
name is a symbol, which matters only to the
rtd-name procedure of the inspection layer.
fieldspecs is a vector of field specifiers, where
each field specifier is one of
(mutable name),
where name is a symbol naming the mutable field;
(immutable name),
where name is a symbol naming the immutable field.
The optional parent is an rtd or #f. It is an error for
any of the symbols in fieldspecs to name more than one
of the fields specified by fieldspecs, but the field names
in fieldspecs may shadow field names in the parent rtd.
make-rtd returns an R6RS-compatible record-type
descriptor.
Larceny allows the following optional arguments to follow the optional parent-rtd argument:
sealed means the new rtd cannot be used
as the parent of other rtds;
opaque means the record? predicate
will not recognize instances of the new rtd;
uid, followed by another symbol id,
means the new rtd is non-generative with uid id; the
semantics of this extension is the same as in the R6RS.
These Larceny-specific options may be used in any combination, giving Larceny's ERR5RS records the same expressive power as R6RS records, with which they are fully interoperable.
This predicate returns true if and only if its argument
is a record-type descriptor.
rtd? is equivalent to the record-type-descriptor?
procedure of the R6RS.
(rtd-constructor rtd fieldspecs)
rtd is a record-type descriptor, and fieldspecs is an optional vector of symbols.
If no fieldspecs argument is supplied,
then rtd-constructor returns a procedure that expects
one argument for each field of the record-type described
by rtd and returns an instance of that record-type
with its fields initialized to the corresponding
arguments.
Arguments that correspond to the fields of the
record-type's parent (if any) come first.
If fieldspecs is supplied, then rtd-constructor
returns a procedure that expects one argument for each
element of fieldspecs and returns an instance of the
record-type described by rtd with the named fields
initialized to the corresponding arguments.
It is an error if some symbol occurs more than once in fieldspecs. Fields of a derived record-type shadow fields of the same name in its parent; the fieldspecs argument cannot be used to initialize a shadowed field.
Equivalent to the record-predicate procedure of the R6RS.
field is a symbol that names a field of the record-type described by the record-type descriptor rtd. Returns a unary procedure that accepts instances of rtd (or any record-type that inherits from rtd) and returns the current value of the named field.
Fields in derived record-types shadow fields of the same name in a parent record-type.
field is a symbol that names a field of the record-type described by the record-type descriptor rtd. Returns a binary procedure that accepts instances of rtd (or any record-type that inherits from rtd) and a new value to be stored into the named field, performs that side effect, and returns an unspecified value.
Fields in derived record-types shadow fields of the same name in a parent record-type.
This section describes the (err5rs records inspection) library.
Equivalent to its R6RS namesake.
Equivalent to its R6RS namesake.
Equivalent to the record-type-name procedure of the R6RS.
Equivalent to the record-type-parent procedure of the R6RS.
Equivalent to the record-type-field-names procedure of the R6RS.
(That is, it returns a vector of the symbols that name the fields
of the record-type represented by rtd, excluding the fields of
parent record-types.)
Returns a vector of the symbols that name the fields of
the record-type represented by rtd, including the fields
of its parent record-types, if any, with the fields of
parent record-types coming before the fields of its children,
with each subsequence in the same order as in the vectors
that would be returned by calling rtd-field-names
on rtd and on all its ancestral record-type descriptors.
(rtd-field-mutable? rtd field)
rtd is a record-type descriptor, and field is a
symbol naming a field of the record-type described by rtd.
Returns #t if the named field is mutable; otherwise returns #f.
This section describes the (err5rs records syntactic) library.
The syntactic layer consists of SRFI 9 extended with single inheritance and (optional) implicit naming.
All ERR5RS record-type definitions are generative (unless
Larceny's optional uid feature is used), but
ERR5RS drops the SRFI 9 restriction to top level, mainly
because the R6RS allows generative definitions wherever
a definition may appear.
The syntax of an ERR5RS record-type definition is
<definition>
-> <record type definition> ; addition to 7.1.6 in R5RS
<record type definition>
-> (define-record-type <type spec>
<constructor spec>
<predicate spec>
<field spec> ...)
<type spec> -> <type name>
-> (<type name> <parent>)
<constructor spec>
-> #f
-> #t
-> <constructor name>
-> (<constructor name> <field name> ...)
<predicate spec>
-> #f
-> #t
-> <predicate name>
<field spec> -> <field name>
-> (<field name>)
-> (<field name> <accessor name>)
-> (<field name> <accessor name> <mutator name>)
<parent> -> <expression>
<type name> -> <identifier>
<constructor name> -> <identifier>
<predicate name> -> <identifier>
<accessor name> -> <identifier>
<mutator name> -> <identifier>
<field name> -> <identifier>The semantics of a record type definition is the same as in SRFI 9: the record type definition macro-expands into a cluster of definitions that
<type name> as the record-type descriptor
for the new record-type;
#f);
#f);
An ERR5RS record type definition extends SRFI 9 with the following additional options:
<parent> expression is specified, then it must
evaluate to an rtd that serves as the parent record-type
for the record-type being defined.
#f is specified for the constructor or predicate,
then no constructor or predicate procedure is defined.
(This is useful when the record-type being defined will
be used as an abstract base class.)
#t is specified for the constructor or predicate,
then the name of the constructor is the type name prefixed
by make-, and the name of the predicate is the type name
followed by a question mark (?).
#t or as an
identifier, then the constructor's arguments correspond
to the fields of the parent (if any) followed by the new
fields added by this record-type definition.
If a field spec consists of a single identifier, then
-) followed by the field name.
If a field spec consists of a list of one identifier, then
-) followed by the field name;
-) followed by the field name followed by -set!.
Two ERR5RS records with fields are eqv? if and only if
they were created by the same (dynamic) call to some
record constructor.
Two ERR5RS records are eq? if and only if they are eqv?.
Apart from the usual constraint that equivalence according
to eqv? implies equivalence according to equal?, the
behavior of equal? on ERR5RS records is unspecified.
(This is compatible with the R6RS.)
A define-record-type form macro-expands into code that
calls make-rtd each time the expanded record-type
definition is executed.
Two ERR5RS record-type descriptors are eqv? if and only if
they were created by the same (dynamic) call to
make-rtd.
This chapter explains which features of the R6RS standard libraries are available in each of Larceny's major modes of execution.
Larceny was the first substantially complete implementation of the R6RS. Any features that are missing from R6RS modes are missing because of bugs or because the features are deprecated in Larceny. The most up-to-date listing of Larceny's known deviations from the R6RS standard can be found on the web page that describes the current status of Larceny's R6RS-compatible mode.
Larceny is R6RS-compatible but not R6RS-conforming. When Larceny is said to support a feature of the R6RS, that means the feature is present and will behave as specified by the R6RS so long as no exception is raised. Larceny does not always raise the specific conditions specified by the R6RS, and does not perform all of the checking for portability problems that is mandated by the R6RS. These deviations do not affect the execution of production code, and do not compromise Larceny's traditional safety.
ERR5RS and R6RS modes support all procedures and syntaxes
exported by the (rnrs base) library.
Larceny's R5RS mode does not support library, import, or
identifier-syntax.
The following deviations from R6RS semantics are known bugs that should be fixed in a future release.
In Larceny v0.96, the imaginary part of an inexact real is inexact. Some of the algebraic and transcendental functions do not yet behave as specified by the R6RS, especially with regard to branch cuts.
The number->string and string->number procedures do not
yet support mantissa widths.
The semantics of quasiquote, let-syntax, and letrec-syntax
differ between the R5RS and the R6RS. Larceny's R5RS mode still
supports the R5RS semantics.
All of Larceny's modes support all features of the (rnrs unicode)
library.
Larceny v0.96 conforms to The Unicode Standard, Version 5.0.
ERR5RS and R6RS modes support all procedures and syntaxes
exported by (rnrs bytevectors), but the endianness
syntax is deprecated because it is redundant with quote.
Larceny's R5RS mode does not support endianness.
In Larceny, any symbol names a supported endianness.
The symbols big and little have their expected meanings.
All other symbols mean (native-endianness) with respect
to integer operations, but mean the opposite of
(native-endianness) with respect to
IEEE-754 operations.
For string operations, the endianness must be the symbol
big or the symbol little. All of these extensions are
permitted by the R6RS standard.
Larceny's utf16->string and utf32->string accept one,
two, or three arguments. The R6RS specification of these
procedures does not allow them to accept a single argument,
but that is believed to be an error in the R6RS.
ERR5RS and R6RS modes support all procedures and syntaxes
exported by
(rnrs records procedural),
(rnrs records inspection), and
(rnrs records syntactic).
Those libraries are deprecated, however;
the make-record-constructor-descriptor procedure does
not simplify unusually complex cases enough to justify
the complexity it adds to typical cases, and
the entire syntactic layer is gratuitously incompatible
with the procedural layer.
Larceny's R5RS mode supports all features of the deprecated
(rnrs records procedural) and (rnrs records inspection)
libraries. R5RS mode does not support (rnrs records syntactic).
All of Larceny's modes support all features of the
(err5rs records procedural)
and
(err5rs records inspection)
libraries. ERR5RS and R6RS modes also support the
(err5rs records syntactic)
library.
The record definition syntax of
SRFI 9
is a proper subset
of the syntax provided by the (err5rs records syntactic)
library. In R5RS mode, SRFI 9 can be loaded dynamically
using the
require procedure:
> (require 'srfi-9)
We recommend the ERR5RS and/or SRFI 9 libraries be used instead of the corresponding R6RS libraries.
The R6RS spouts some tendentious nonsense about procedural records being slower than syntactic records, but this is not true of Larceny's records, and is unlikely to be true of other implementations either.
Larceny continues to support its old-style records, which are almost but not quite compatible with ERR5RS and R6RS records. This can be confusing, since some of Larceny's procedures have the same names as R6RS procedures. That has made it necessary to overload those procedures to work with both old-style and R6RS records. We apologize for the mess.
All of Larceny's modes support all features of the
(rnrs exceptions) and (rnrs conditions) libraries.
ERR5RS and R6RS modes support all names exported by the
(rnrs io ports), (rnrs io simple), and
(rnrs files) libraries.
The buffer-mode, eol-style, and error-handling-mode
syntaxes are deprecated because they are redundant
with quote. These deprecated syntaxes may be provided
in the form of procedures rather than syntax, but this
deviation from R6RS semantics cannot be detected by
portable R6RS programs.
Larceny's R5RS mode supports all non-deprecated features of those libraries.
Larceny supports four distinct buffer modes: none,
line, datum, and block. The R6RS requires
the buffer-mode syntax to raise an exception for the
datum buffer mode, which is the buffer mode Larceny
uses for interactive output ports.
In Larceny, any symbol names a supported end-of-line style. All end-of-line and error-handling-mode symbols whose meanings are not described by the R6RS have locale-dependent meanings, which is an extension permitted by the R6RS standard.
Although Larceny supports the UTF-16 codec, it is not really useful on Windows machines (where it should be most useful) because Larceny's low-level file system mimics a byte-oriented Unix file system even on Windows. This problem should be addressed in some future version of Larceny.
The most up-to-date list of known deviations from R6RS io semantics can be found on the web page that describes the current status of Larceny's R6RS-compatible mode.
ERR5RS and R6RS modes support the (rnrs programs) library.
Larceny's R5RS mode provides the exit procedure but
not the command-line procedure of that library.
Larceny's traditional command-line-arguments procedure
can be used to implement an approximation to command-line.
For a definition, see lib/R6RS/rnrs/programs.sls.
All of Larceny's modes support all features of the
(rnrs arithmetic fixnums),
(rnrs arithmetic flonums), and
(rnrs arithmetic bitwise)
libraries.
R6RS fixnum and flonum operations may be slower than the corresponding generic operations, since the fixnum and flonum operations are required to check their arguments and may also have to check their results. Isolated operations in small micro-benchmarks are likely to be slower than groups of similar operations in larger programs, because the Twobit compiler removes redundant checks and propagates type information.
ERR5RS and R6RS modes support the (rnrs syntax-case) library.
Larceny's R5RS mode does not.
All of Larceny's modes support all features of the
(rnrs hashtables) library.
Larceny's traditional make-hashtable procedure has been
renamed to make-oldstyle-hashtable. In Larceny v0.96,
make-hashtable prints a warning when it is called. To
avoid that warning, call make-r6rs-hashtable instead.
ERR5RS and R6RS modes support the (rnrs enums) library.
Larceny's R5RS mode provides all of the procedures exported by
(rnrs enums) but does not provide the define-enumeration
syntax.
ERR5RS and R6RS modes are believed to support the (rnrs eval)
library, but the environment procedure has not been tested.
Larceny's R5RS mode provides an R5RS-compatible eval procedure,
not an R6RS-compatible eval procedure, and does not provide the
environment procedure.
All of Larceny's modes support all features of the
(rnrs mutable-pairs) and (rnrs mutable-strings) libraries.
Larceny provides libraries for loading and compiling ERR5RS/R6RS libraries and for timing benchmarks. Future versions of Larceny will offer more ERR5RS/R6RS libraries.
The (larceny load) library exports both the
load procedure of (err5rs load)
and Larceny's
require procedure.
In Larceny's ERR5RS mode,
the load and require procedures can load
R5RS libraries and programs as well as ERR5RS/R6RS
libraries.
These procedures should be used only at an interactive top
level and in files that will be loaded into an interactive top
level. Calls to these procedures have no effect at compile
time, and should not appear in files that will be compiled
separately; use the library and import syntaxes instead.
The (larceny compiler) library exports the
load and require procedures of (larceny load),
the
current-require-path
procedure, and the
compile-file,
compile-library, and
compile-stale-libraries
procedures described below.
These procedures can be used to compile ERR5RS/R6RS libraries and top-level programs before they are imported or executed. This is especially important for Petit Larceny, which would otherwise use an interpreter. For native Larceny, whose just-in-time compiler generates native machine code as source libraries and programs are loaded, imported, or executed, the main advantage of separate compilation is that compiled libraries and programs will load much faster than source libraries and programs.
The main disadvantage of separate compilation is that
compiled libraries and programs go stale when their
source code is changed or when a library on which they
depend is changed or recompiled. Stale libraries and
programs can be dangerously inconsistent with libraries
on which they depend, so Larceny checks for staleness
and refuses to execute a stale library or program.
The compile-stale-libraries
procedure provides a convenient way to recompile stale
libraries and programs.
(compile-file sourcefile [slfaslfile])
Compiles sourcefile, which must be a string naming
a file that contains source code for one or more
ERR5RS/R6RS libraries or a top-level program.
If slfaslfile is supplied as a second argument,
then it must be a string naming the file that will
contain the compiled code; otherwise the name of
the compiled file is obtained from sourcefile
by replacing the ".sls" suffix with ".slfasl".
(compile-library sourcefile [slfaslfile])
Compiles sourcefile, which must be a string naming
a file that contains source code for one or more
ERR5RS/R6RS libraries.
Apart from its unwillingness to compile top-level
programs, compile-library behaves the same as
compile-file above.
Procedure compile-stale-libraries
(compile-stale-libraries [changedfile])
If no argument is supplied, then all ".sls" files that
lie within the current directory or a subdirectory are
recompiled.
If changedfile is supplied, then it must be a string giving the absolute pathname of a file. (In typical usage, changedfile is a source file that has been modified, making it necessary to recompile all files that depend upon it.) Compiles all ERR5RS/R6RS library files that lie within the same directory as changedfile or a subdirectory, and have not yet been compiled or whose compiled files are older than changedfile.
In future versions of Larceny, compile-stale-libraries
might compile only the source files that depend upon
changedfile.
The (larceny benchmarking) library exports the
time syntax and run-benchmark procedure described
below.
Syntax time
(time expression)
Evaluates expression and returns its result after printing approximations to the storage allocated and time taken during evaluation of expression.
> (time (fib 30))
Words allocated: 0
Words reclaimed: 0
Elapsed time...: 49 ms (User: 48 ms; System: 0 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)
832040(run-benchmark name iterations thunk predicate)
Given the name of a benchmark, the number of iterations to be performed, a zero-argument procedure thunk that runs the benchmark, and a unary predicate that checks the result of thunk, prints approximations to the storage allocated and time taken by iterations calls to thunk.
> (run-benchmark "fib30"
100
(lambda () (fib 30))
(lambda (x) (= x 832040)))
--------------------------------------------------------
fib30
Words allocated: 0
Words reclaimed: 0
Elapsed time...: 4828 ms (User: 4824 ms; System: 4 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)The (larceny records printer) library exports the
two procedures described below. These procedures
can be used to override Larceny's usual printing
of records and opaque types that were defined using
the records libraries.
(rtd-printer rtd) => maybe-procedure
Given a record type descriptor, returns its custom print procedure, or returns false if the rtd has no custom print procedure.
(rtd-printer-set! rtd printer)
Given a record type descriptor rtd and a printer for instances of that rtd, installs printer as a custom print procedure for rtd. The printer should be a procedure that, given an instance of the rtd and a textual output port, writes a representation of the instance to the port.
The procedures described in this chapter are nonstandard. Some are deprecated after being rendered obsolete by ERR5RS or R6RS standard libraries. Others still provide useful capabilities that the standard libraries don't.
Larceny provides Unicode strings with R6RS semantics.
The string-downcase and string-upcase procedures
perform Unicode-compatible case folding, which can result
in a string whose length is different from that of the original.
Larceny may still provide string-downcase! and string-upcase!
procedures, but they are deprecated.
A bytevector is a data structure that stores bytes — exact 8-bit unsigned integers. Bytevectors are useful in constructing system interfaces and other low-level programming. In Larceny, many bytevector-like structures — bignums, for example — are implemented in terms of a lower-level bytevector-like data type. The operations on generic bytevector-like structures are particularly fast but useful largely in code that manipulates Larceny's data representations.
The (rnrs bytevectors) library now
provides a large set of procedures that, in Larceny, are
defined using the procedures described below.
Integrable procedure make-bytevector
(make-bytevector length) => bytevector
(make-bytevector length fill) => bytevector
Returns a bytevector of the desired length. If no second argument is given, then the bytevector has not been initialized and most likely contains garbage.
Operations on bytevector structures
(bytevector? obj) => boolean
(bytevector-length bytevector) => integer
(bytevector-ref bytevector offset) => byte
(bytevector-set! bytevector offset byte) => unspecified
(bytevector-equal? bytevector1 bytevector2) => boolean
(bytevector-fill! bytevector byte) => unspecified
(bytevector-copy bytevector) => bytevector
These procedures do what you expect.
All are integrable, except bytevector-equal? and bytevector-copy.
The bytevector-equal? name is deprecated, since the
R6RS calls it bytevector=?.
Operations on bytevector-like structures
(bytevector-like? obj) => boolean
(bytevector-like-length bytevector) => integer
(bytevector-like-ref bytevector offset) => byte
(bytevector-like-set! bytevector offset byte) => unspecified
(bytevector-like-equal? bytevector1 bytevector2) => boolean
(bytevector-like-copy bytevector) => bytevector
A bytevector-like structure is a low-level representation for indexed arrays of uninterpreted bytes. Bytevector-like structures are used to represent types such as bignums and flonums.
There is no way to construct a "generic" bytevector-like structure; use the constructors for specific bytevector-like types.
The bytevector-like operations operate on all bytevector-like
structures. All are integrable, except bytevector-like-equal?
and bytevector-like-copy. All are deprecated because they
violate abstraction barriers and make your code
representation-independent; they are useful mainly to
Larceny developers, who might otherwise be tempted to
write some low-level operations in C or assembly language.
(vector-copy vector) => vector
Returns a shallow copy of its argument.
Operations on vector-like structures
(vector-like? object) => boolean
(vector-like-length vector-like) => fixnum
(vector-like-ref vector-like k) => object
(vector-like-set! vector-like k object) => unspecified
A vector-like structure is a low-level representation for indexed arrays of Scheme objects. Vector-like structures are used to represent types such as vectors, records, symbols, and ports.
There is no way to construct a "generic" vector-like structure; use the constructors for specific data types.
The vector-like operations operate on all vector-like structures. All are integrable. All are deprecated because they violate abstraction barriers and make your code representation-independent; they are useful mainly to Larceny developers, who might otherwise be tempted to write some low-level operations in C or assembly language.
Operations on procedures
(make-procedure length) => procedure
(procedure-length procedure) => fixnum
(procedure-ref procedure offset) => object
(procedure-set! procedure offset object) => unspecified
These procedures operate on the representations of procedures and allow user programs to construct, inspect, and alter procedures.
(procedure-copy procedure) => procedure
Returns a shallow copy of the procedure.
The procedures above are deprecated because they violate abstraction barriers and make your code representation-independent; they are useful mainly to Larceny developers, who might otherwise be tempted to write some low-level operations in C or assembly language.
The rest of this section describes some procedures that reach through abstraction barriers in a more controlled way to extract heuristic information from procedures for debugging purposes.
The following text is copied from a straw proposal authored by Will Clinger and sent to rrr-authors on 09 May 1996. The text has been edited lightly. See the end for notes about the Larceny implementation.
The procedures that extract heuristic information from procedures are permitted to return any result whatsoever. If the type of a result is not among those listed below, then the result represents an implementation-dependent extension to this interface, which may safely be interpreted as though no information were available from the procedure. Otherwise the result is to be interpreted as described below.
Returns information about the arity of proc. If the result is #f,
then no information is available. If the result is an exact
non-negative integer k, then proc requires exactly k
arguments. If the result is an inexact non-negative integer n, then
proc requires n or more arguments. If the result is a pair, then
it is a list of non-negative integers, each of which indicates a
number of arguments that will be accepted by proc; the list is not
necessarily exhaustive.
Procedure procedure-documentation-string
(procedure-documentation-string proc)
Returns general information about proc. If the result is #f, then no
information is available. If the result is a string, then it is to be
interpreted as a "documentation string" (see Common Lisp).
Returns information about the name of proc. If the result is #f,
then no information is available. If the result is a symbol or string,
then it represents a name. If the result is a pair, then it is a list
of symbols and/or strings representing a path of names; the first
element represents an outer name and the last element represents an
inner name.
Procedure procedure-source-file
Returns information about the name of a file that contains the source
code for proc. If the result is #f, then no information is
available. If the result is a string, then the string is the name of a
file.
Procedure procedure-source-position
(procedure-source-position proc)
Returns information about the position of the source code for proc
whithin the source file specified by procedure-source-file. If the
result is #f, then no information is available. If the result is an
exact integer k, then k characters precede the opening parenthesis
of the source code for proc within that source file.
Procedure procedure-expression
Returns information about the source code for proc. If the result is
#f, then no information is available. If the result is a pair, then it
is a lambda expression in the traditional representation of a list.
Procedure procedure-environment
Returns information about the environment of proc. If the result is
#f, then no information is available. In any case the result may be
passed to any of the environment inquiry functions.
Notes on the Larceny implementation
Twobit does not yet produce data for all of these functions, so some
of them always return #f.
The (rnrs lists) library now
provides a set of procedures that may supersede some
of the procedures described below.
If one of Larceny's procedures duplicates the semantics of
an R6RS procedure whose name is different, then Larceny's
name is deprecated.
(append! list1 list2 … obj) => object
append! destructively appends its arguments, which must be lists, and
returns the resulting list. The last argument can be any object. The
argument lists are appended by changing the cdr of the last pair of
each argument except the last to point to the next argument.
(every? procedure list1 list2 …) => object
every? applies procedure to each element tuple of list_s in
first-to-last order, and returns #f as soon as _procedure returns
#f. If procedure does not return #f for any element tuple of
list_s, then the value returned by _procedure for the last element
tuple of _list_s is returned.
(last-pair list-structure) => pair
last-pair returns the last pair of the list structure, which must be
a sequence of pairs linked through the cdr fields.
list-copy makes a shallow copy of the list and returns that copy.
Each of these procedures returns a new list which contains all the
elements of list in the original order, except that those elements of
the original list that were equal to key (or that satisfy pred?) are
not in the new list. Remove uses equal? as the equivalence predicate;
remq uses eq?, and remv uses eqv?.
These procedures are like remove, remq, remv, and remp,
except they modify list instead of returning a fresh list.
reverse! destructively reverses its argument and returns the reversed
list.
(some? procedure list1 list2 …) => object
some? applies procedure to each element tuple of list_s in
first-to-last order, and returns the first non-false value returned by
_procedure. If procedure does not return a true value for any
element tuple of _list_s, then some? returns #f.
The (rnrs sorting) library now
provides a small set of procedures that supersede most
of the procedures described below.
All of the procedures described below are therefore
deprecated.
Procedures sort and sort!
(sort list less?) => list
(sort vector less?) => vector
(sort! list less?) => list