SX User’s Manual

Scheme with eXtensions

Stewart A. Brown
Dennis Braddy

The PACT SCHEME Language

The PACT SCHEME/SX Reference

Interfacing Compiled and Interpreted Code

Related Documents


A special acknowledgement is due to Lee Taylor who designed and implemented the internal interface between the PACT SCHEME interpreter and PDBLib. That code eventually became SX when the remainder of PACT was thrown into the pot.

The PACT SCHEME Language

This section introduces the reader to the PACT implementation of the SCHEME programming language. It does this through a formal description of the language (section 1.2) and a tutorial (section 1.3). For readers who are already familiar with SCHEME in general, this section may be skimmed. Note should be taken, however, of the differences between PACT SCHEME and other SCHEME implementations.



The LISP programming language is one of the most powerful computer languages ever developed. Somewhat ironically, it is also one of the simplest to implement, at least to a certain level. Many applications would benefit by being able to provide their users with the ability to extend the application via a macro or scripting mechanism. LISP turns out to be ideal for this purpose. The language is syntactically simple and can be molded to meet a variety of needs. It also offers more power than most applications care to provide to their users, but one would rather be in that position than in having an underpowered extension mechanism.

Scheme is a lexically scoped, properly tail recursive dialect of the LISP programming language. The PACT implementation is described abstractly in Abelson and Sussman’s book, Structure and Interpretation of Computer Programs. It features all of the “essential procedures” described in the Revised3 Report on Scheme (Jonathan Rees and William Clinger, ed) which defines the standard for Scheme.

PACT SCHEME is implemented as a library; however, a small driver delivers a stand alone SCHEME interpreter. This is useful for people who want to learn the language as well as people who want to prototype algorithms (one of LISP’s strong points).

The PACT implementation features a reference counting incremental garbage collector. This distributes the overhead of memory management throughout the running of Scheme code. It also tends to keep Scheme from trying to grab the entire machine on which it is running which some garbage collection schemes will attempt to do.


SX is perhaps the ultimate PACT statement. It is simply Scheme plus the other parts of PACT. A more precise way to describe it is as a dialect of LISP with extensions for PGS, PDB, PDBX, PML, and PANACEA. What this yields is an interpretive language whose primitive procedures span the functionality of all of PACT.

Like the PACT SCHEME implementation which it extends, SX provides both a library and a stand alone application. The stand alone interpreter is the engine behind applications such as PDBView and PDBDiff. These examples demonstrate the extreme power of the PACT design. The modularization and layering make it possible to use the PACT components like building blocks.

In addition to the above mentioned functionality, SX contains functionality which is the generalization of that found in ULTRA II. This means that as the development of SX proceeds, an SX driven application will be able to perform arbitrary dimensional presentation, analysis, and manipulation tasks.

Because of the fundamental unity of these two PACT parts, they are documented in a single manual. The first part will cover the “standard” Scheme functionality and the second part will discuss the SX extensions.

SCHEME Language Guide

The PACT SCHEME implementation derives from two main sources. First, Abelson and Sussman’s book, The Structure and Interpretation of Computer Programs gives an account of a basic Scheme interpreter. To fill in the details and build a somewhat standard Scheme, I used the Revised3 Report on the Algorithmic Language Scheme. This has subsequently been updated with some of the features of the Revised4 Report on the Algorithmic Language Scheme (R4RS).

This implementation differs from standard Scheme in a few fundamental ways. First, the numerics defined in R4RS are not suited to the main audience of PACT. For example, the notions of exactness and inexactness of floating point numbers are not practical concepts in actual numerical simulation codes. Furthermore, for ease of implementation and good matching to the needs of applications using the library version of the interpreter, the numeric types implemented map to the standard types of the C language. In short, I implemented integers, reals, and characters as C longs, doubles, and chars respectively. Second, keeping in mind that this interpreter is implemented in C and needs to be as compatible with C usages as possible, I chose to follow C conventions in situations where it was the convenient and “obvious” thing to do.

Throughout this manual little will be said of the differences between Scheme and LISP in general. The reader may assume that unless otherwise explicitly stated comments about the character of Scheme apply also to LISP in general. The functions in Scheme differ in many cases from those in LISP but the character of the languages is similar. For example, they are both fully parenthesized and they both use prefix notation.

General Concepts of Scheme

The term object is used to refer to an instance of any type of Scheme variable, data, or expression. This usage is similar to that used in connection with other programming languages. One of the distinguishing characteristics of Scheme is that every object in Scheme has a definite (although sometimes only implicit) type which can be queried. For example, an object, x, can be asked if it is a real number

(real? x)
All objects in Scheme have an internal representation and printing representation. That is to say that every object that is represented internally can be indicated in printed form in output operations. Most objects can be indicated in input operations by their printing representation. For example, the string “foo bar baz” has some internal representation in Scheme and has a printing representation that can be used in input or appears in output as

“foo bar baz”
By contrast, an object such as a hash table has an internal representation and a printing representation, but the printing representation cannot be used in input operations to indicate that a complete hash table should be inferred from the printing representation. The printing representation might look like

This clearly does not contain enough information to infer the entire contents of the hash table whose internal representation it is associated with.

The most important data structure in LISP is the list (LISP stands for LISt Processing language or, if you choose to believe, Lots of Irritating Silly Parentheses). This is also true of Scheme. Both programs and data are represented by lists. This feature of the language permits Scheme programs to manipulate Scheme programs as data. This is the source of a great deal of Scheme’s power.

Scheme is a tail recursive dialect of LISP. This means that certain recursively posed procedures execute as simple loops. This permits the Scheme programmer to write procedures using recursion and the interpreter (or compiler) to run these procedures in fixed space. The function call stack is never blown with tail recursive procedures.

Variables in Scheme are said to be bound when they are assigned to locations in which a value may be stored. Variables in Scheme may be either bound, in which case references to the variable yield a value, or unbound, in which case references to the variable yield an UNBOUND VARIABLE error.

The collection of all variables visible at any point in the execution of a program is called the environment in effect at that point. When interacting directly with the Scheme interpreter at the top level (no procedures executing) the environment in effect is called the global environment.

Scheme like C is a call by value language.

Scheme has a class of procedures called predicates. Predicate procedures return one of the two boolean values: TRUE or FALSE (represented by #t or #f respectively). Most languages have syntactic constructs to express this functionality. In Scheme which has a simple and uniform syntax (except for quote and quasi-quote) this functionality must be expressed as procedures.

Documentation Conventions

In this manual the following notational conventions will apply.

Syntax and Notation

It is a characteristic of LISP dialects to use prefix notation, that is operators precede their operands. LISP and its dialects also use parentheses to group and associate objects. Parentheses are the only syntactic mechanisms for separating groups of objects. So to add four numbers, 3, 25.2, 0.015, and -1.3e-4, one would use the expression
(+ 3 25.2 0.015 -1.3e-4)
Part of the power of the language derives from the fact that such expressions return values that can be used in other expressions, for example
(* 5 (+ 3 25.2 0.015 -1.3e-4))
which multiplies the result of adding 3, 25.2, 0.015, and -1.3e-4 by 5.


The characters (expressed in C style notation) ‘ ’ (blank),’\t’ (tab), ‘\f’ (formfeed), and ‘\n’ (newline) are considered to be whitespace in Scheme programs.


A semicolon begins a comment, and the comment extends to the end of the line containing the semicolon.


Numbers begin with any of the following characters: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘.’, or ‘-’. They must correspond to the standard representations of either integer or floating point types used in C (and most FORTRANs).


Strings are arbitrary groups of characters which are delimited with double quotes ‘”’.


Subject to the special case listed below, all groups of characters delimited by whitespace which are neither numbers nor strings are identifiers. Case is significant in PACT Scheme unlike R4RS.

Special Syntax

The following characters have special meanings in some contexts. They should not be used in identifiers unless escaped by ‘\’.

. used in the notation of pairs and dotted argument lists
( begins a list of objects
) ends a list of objects
quote (don’t evaluate) an object
quasi-quote an object
, used in conjunction with quasi-quotation
,@ used in conjunction with quasi-quotation
# used with character constants, boolean constants, and vector constants
\ used with character constants and in strings as an escape character

Naming Conventions

Predicate functions (returning true or false) end with ‘?’.

Functions which store values end with ‘!’.

Functions which map objects of different types have “->” in their names. For example, the function which maps a list into a vector is called list->vector.

Reserved Identifiers

Identifiers typically occur as the names of variables (or symbols) or functions (or procedures). PACT Scheme allows programmers to use identifiers that have been assigned to the built in procedures of the language for their own variables and functions, but this has the effect of hiding (possibly for the duration of the session or program) the built in procedure. It is recommended that this not be done in the case of the following built in functions. They can be thought of as reserved keywords.

and if quasiquote
begin lambda quote
define let set!
do let* unquote
else or unquote-splicing

Scheme Data Types

The fundamental data types of PACT Scheme are:

boolean there are two boolean objects in Scheme, #t and #f, representing a TRUE and FALSE logical value respectively
char a character object is a single character and is represented by its printing representation preceded by a #\, e.g. #\A represents ‘A’
number a number is any object with a numeric type such as integer or real
pair an object with two parts called the car and cdr. This is the primitive object from which lists are built
string a collection of characters (not character objects) delimited by double quotes.
symbol a synonym for variable
procedure an object which specifies a procedure
vector a 1 dimensional array of objects
guest an object that encapsulates C variables and structures as a part of the interface between PACT Scheme and C applications
Each of these types has a corresponding predicate function. It is guaranteed that no Scheme object will return TRUE for more than one of the associated predicates.

In addition the number type is subdivided into

integer an object representing an integer number
real an object representing a floating point number
PACT Scheme does not implement



The reason for this is that in order to keep the implementation reasonably small and efficient, I chose to adhere closely to underlying C concepts and data types. Both of these types could be implemented as C structures, but handling the arithmetic with them is not consistent with the goals of the implementation.

Predicates exist for the integer and real types, but any object that is either an integer or a real is also a number.

Scheme Expressions

An expression in Scheme is an object which when evaluated returns a value. Scheme has a small set of primitive expression types and all other expressions in Scheme can be built up or derived from more primitive expressions. The primitive expression types are enumerated in this section.

This is the heart of Scheme, and although this is not by any means a tutorial, once the concept of expression is mastered along with the primitive expression types, the remainder of the work of this manual is filling in details on the set of procedures supplied in PACT Scheme.

Literal Expressions

An expression consisting of a constant or a quoted expression is a literal expression. Literal expressions evaluate to themselves. That is a string evaluates to itself, a number evaluates to itself, and so on.

Another kind of literal expression comes about by specifying that an expression should not be evaluated. This is a quoted expression. Its syntax is:

(quote expression)

Variable Definition

Variables are unbound until they are defined in a variable definition expression. The syntax is:

(define variable value)
This expression binds variable to a location where the value is then placed.

Variable Reference

An expression representing a reference to a variable consists of the variable itself.

It is an error to reference an unbound variable, i.e. a variable which has not be been bound in a variable definition expression.

Variable Assignment

The value in the location to which a variable is bound can be changed by the use of a variable assignment expression.

(set! variable value)
It is an error to try to assign a value to an unbound variable.

Conditional Expressions

In Scheme there is a single primitive conditional expression form from which all others may be derived.

(if test consequent alternate)
If test is not FALSE (evaluates to anything but #f) the consequent expression is evaluated and returned. Otherwise the alternate expression is evaluated and returned. The alternate expression is optional in which case if test is FALSE nothing is evaluated and the conditional expression returns #f.

Procedure Calls

Since procedures are a fundamental “data” type in Scheme, the problem of procedure calls splits into two parts. The first part is obtaining a procedure. The next section explores that issue in more detail. The second part is invoking a procedure once you have one. A procedure call is posed as a list consisting of the procedure object as the first element of the list and the arguments to the procedure as the remaining elements of the list.

(procedure argument1 ...)
Some examples of procedure calls are:

(* 2 3 4) => 24

((if #t + -) 20 10 5) => 5

In the first example the procedure object is “*” and the procedure call expression multiplies the numbers 2, 3, and 4 to obtain the value 24. In the second example, the conditional expression

(if #f + -) => -
is evaluated to return the procedure “-” which is then applied to the numbers 20, 10, and 5 to yield the result 5.

Anonymous Procedures

A characteristic of LISP which Scheme shares is the notion of an anonymous procedure. An expression called a lambda expression evaluates to a procedure. A lambda expression is the irreducibly primitive procedure definition mechanism for Scheme. All procedures and most of the special expressions except those mentioned in this section can be defined in terms of lambda expressions.

The syntax of a lambda expression is

(lambda arguments body)
The arguments are a list of formal parameters to the procedure, and the body is the set of expressions which define the action of the procedure.

The arguments can be one of the following:


(variable1 ...)

(variable1 ... variablen . variablen+1)

In the last case variablen+1 is bound to a list of the arguments in the procedure call which remain after the first n arguments are bound to the first n formal parameters.

Some examples of lambda expressions in procedure calls are:

((lambda x x) 1 “foo” 2.3) => (1 “foo” 2 3)

((lambda (x) (+ 1 x)) 4) => 5

((lambda (x y . z) z) 3 4 5 6) => (5 6)

An anonymous procedure can be bound to a variable in order to give a more convenient way of using procedure objects.

(define foo (lambda x x))
This would bind the variable foo to the lambda expression for the identity function. It can then be used as

(foo 3) => 3
This usage is so common that an alternate form of the define expression was created. Its usage is

(define (variable arguments) body)
Here the variable is bound to the procedure being made. The arguments are like those of the lambda expression.


variable1 ...

variable1 ... variablen . variablen+1

Note the absence of parentheses here. Compare with the lambda expression syntax. The first variant means that there are no arguments.

The body of the procedure is identical with that for the lambda expression.

(define (foo x) x)

Scheme Procedures

In most LISP dialects there are two kinds of procedures: those which evaluate their arguments before binding them to the formal parameters; and those which do not evaluate their arguments before binding them to the formal parameters. There are also procedures which carry out an additional evaluation of the result of the procedure call.

PACT SCHEME permits all combinations of evaluating arguments and evaluating results. This makes for a great deal of flexibility in the implementation and in the use of the library in applications. More will be said about this later in this manual.

The majority of Scheme functions evaluate their arguments and do not evaluate the result of the call. These will be referred to simply as procedures. All other functions will be referred to as macros (R4RS calls them special forms).

Scheme Programs

The conceptual structure of a Scheme program differs from that of a C program primarily in the entry into the program. Both will have a collection of function or procedure definitions, and both have a main entry point into the program.

In the case of C there is a special procedure called main which serves as the main entry point into the program. Arguments from the command line invocation of the C program are made available to main. The main procedure may call no other functions and simply do the work of the program itself or it may do nothing but call other functions.

In Scheme, their is no special function like main in C. A file is read in and variables and functions are defined sequentially. Functions and variables must be defined before they are invoked or referenced. Consequently the analog of the main entry point into a Scheme program must come at the end of a file or function definition, and it is just an ordinary procedure call.

Example C code fragment illustrating structure of a C program

foo(int x)

Example Scheme code fragment illustrating the structure of the same program

(define (foo x) ...)

(define (bar) ...)

(foo 1)


NOTE: a common complaint about LISP programming is that one has to count parentheses carefully which is a lot of bother. The answer to that problem is to use a text editor which indicates balancing parentheses. One common editor with this feature is GNU Emacs.

A PACT Scheme Tutorial

About Those Parentheses

Scheme evaluates expressions:

=>(+ 9 2)
=>; Comments can be added after a semicolon.
; Note that => is the SX prompt.
; For clarity, responses from SX will be outlined.
(+ 9 2) ; Scheme uses Polish notation.
Scheme evaluates expressions from left to right and from inside nested pairs of parentheses out:

=> (- (+ 4 2) 7)


The first argument (+ 4 2) is evaluated to 6, and the second argument 7 is evaluated to 7. Then (- 6 7) is evaluated to -1.

A little more integer arithmetic will show how the expression (9 + 2) (7 - 4)/3 might be written in Scheme:

=> (+ 9 2) ; i.e., 9 + 2
=> (- 7 4) ; i.e., 7 - 4
=> (* (+ 9 2) (- 7 4)) ; i.e., (9 + 2) (7 - 4)
=> (/ (* (+ 9 2) (- 7 4)) 3) ; Q.E.D., (9 + 2) (7 - 4)/3
Thus, (9 + 2) (7 - 4)/3 is evaluated in three steps:

(* (+ 9 2) (- 7 4)) 3) -> (/ (* 11 3) 3)
(/ (* 11 3) 3) -> (/ 33 3)
(/ 33 3) -> 11

Lists and Conses

One of the fundamental and powerful data structures of Scheme is a pair of pointers referred to variously as a cons, cell, or pair. To talk about Scheme you have to talk about conses. The printed representation of cons containing a and b is

(a . b)
The first part of the pair is called the car of the cons and the second part is called the cdr of the cons.

Lists consist of chains of conses. For example:

(a . (b . (c . ())))
This is really rather tedious, so a more compact notation is used to represent lists

(a . (b . c . ()))) <==> (a b c)
The rule is that if the cdr of a cons is another cons the “. (“ is suppressed. This also means that you will see things like:

(a b c . d)
which is equivalent to

(a . (b . (c . d)))
Compare this with the above to see another rule about lists and conses. If the final conses cdr is (), then suppress the “ . ()”. For example:

(a . ()) <==> (a)
The Scheme function cons is used to create a new cons:

=> (cons 1 2)

(1 . 2)

You can always use cons to build up lists:

=> (cons 1 (cons 2 (cons 3 ())))

(1 2 3)

However there is a better way. Use the list function:

=> (list 1 2 3)

(1 2 3)

Writing Scheme Functions

Scheme provides predefined primitive functions such as sqrt, equal?, and cons:

=> (sqrt 25)


=> (equal? 3 5)


=> (equal? (* 3 6) (+ 9 9))


=> (cons ‘fish ‘())


=> (cons ‘fish1 (cons ‘fish2 (cons ‘fish3 ‘(fish4))))

(fish1 fish2 fish3 fish4)

The function equal? is one of a number of Boolean functions that return a true-or-false Boolean object: either #t or #f. The input of a decision-making function like cond (see below) is often the output of a Boolean function:

=> (cond ((equal? 2 2) “The numbers are equal.”)
(else “The numbers are not equal.”))
“The numbers are equal.”
=> (cond ((equal? 2 3) “The numbers are equal.”)
(else “The numbers are not equal.”))
“The numbers are not equal.”
In the two examples above, if equal? evaluates to #t, the first message is printed. Otherwise, the second message is printed.

Scheme programming consists of writing your own functions, e.g.:

=> (define (net-vol x2 y2 z2 x1 y1 z1)
(- (* x2 y2 z2) (* x1 y1 z1)))
The name of the function (net-vol) was declared in the define statement, and the arguments (six, in this example) were listed. Then the algorithm was stated, giving the locations of the arguments in the algorithm. SX returned the name of the function to confirm that the definition has been accepted.

After net-vol has been defined, it is called with its arguments like any other function:

=> (net-vol 6 9 27 4 3 1)


Once a function has been defined, it can be included in definitions of other functions. If we defined function square as

=> (define (square n)
(* n n))
we can define function lim-test as:

 => (define (lim-test lim n)

        (<= lim (square n)))    ; Second argument less than

                                ; or equal to first argument? 

 => (lim-test 9 100)


 => (lim-test 11 100)


Recursion in Scheme Functions

A Scheme function becomes recursive if it calls itself within its own definition. It takes the general form:

(define (name ...)
( name ...))
A conditional statement may be placed in the definition before the function calls itself, in order to eventually escape from the loop. Here is a function that uses the if statement, which takes the logical form:

(if (condition)  true false) 

=> (define (query n) 
      (if (zero? n) 
        "The number is zero." 
        "The number is not zero.")) 
=> (query 0) 
"The number is zero." 
=> (query 5) 
"The number is not zero." 
Now we’ll define n-fact, a function that uses recursion to calculate n!:

=> (define (n-fact n)
       (if (= 0 n)
           (* n (n-fact (- n 1)))))
=> (n-fact 0)
=> (n-fact 1)
=> (n-fact 5)

Lists, Symbols, and the car, cdr, and cond Functions

Scheme, which is a dialect of LISP (LISt Processor), processes lists!

A list is a set of space-delimited elements enclosed within a pair of left and right parentheses, e.g.:

(a b c d e)

(Look here)

(1 3 5 7 9)

A list can include other lists:

((a b c) d (e f))
List elements that are not lists are called atoms, e.g.:

(a b c d e) contains the atoms a, b, c, d, and e
(Look here) contains the atoms Look and here
(1 3 5 7 9) contains the atoms 1, 3, 5, 7, and 9
((a b c) d (e f)) contains the atom d.
((a b c) d (e f)) contains the atoms a, b, and c.
((a b c) d (e f)) contains the atoms e and f.
The Scheme function symbol? tests for a symbol:

=>(symbol? ‘(a b c d e))


=>(symbol? ‘a)


An important list, the null list, contains no elements:

In recursive functions, the elements in a list are often removed from the list and operated on one at a time until nothing remains but the null list. The null? function can test for the null list to provide an exit from a recursive loop. The looping action would produce results similar to the following non-looping sequence:

=>(null? `(1 2 3))

#f                      ; Loop again.

=>(null? `(2 3))

#f                      ; Loop again.

=>(null? `(3))

#f                      ; Loop again.

=>(null? `())

#t                      ; Stop.
The output of the function car is the first element in a list:

=>(car ‘(a b c d e))


=> (car ‘((a b c) d (e f)))

(a b c)

The output of the function cdr is the list without the first element:

=> (cdr ‘(a b c d e))

(b c d e)

=> (cdr ‘((a b c) d (e f)))

(d (e f))

The cond function uses the following logic:

if condition A is true then action 1

else if condition B is true then action 2

else if condition C is true then action 3


else action n

The following function uses the car and cdr functions to determine the truth of each condition in a cond function:

=>(define (look-see list1)
; The variable "list1" will be the name given to a list that we will
; examine.
; If the first element in the list is "d", print message.
            ((equal? (car list1) `d)
             "The d is the first element.")
; If the second element (the first of the rest of the list) is "d", 
; print message. 
            ((equal? (car (cdr list1)) `d)
             "The d is the second element.")
; If the third element (the first of the rest of the rest of the list)
; is "d", print message.
            ((equal? (car (cdr (cdr list1))) `d)
             "The d is the third element.")
; If the fourth element (the first of the rest of the rest of the rest
; of the list) is "d", print message.
            ((equal? (car (cdr (cdr (cdr list1)))) `d)
             "The d is the fourth element.")
; If the fifth element (the first of the rest of the rest of the rest
; of  the rest of the list) is "d", print message.
            ((equal? (car (cdr (cdr (cdr (cdr list1))))) `d)
             "The d is the fifth element.")
; All five tests failed; print message.
          (else "The d is not present in the list.")))
Next we’ll define string list1 (to which we’ll assign the five elements "a b c d e"), and then we’ll execute function look-see:

=> (define list1

       `(a b c d e))


=>(look-see list1)

The following recursive function uses the null list and the car and cdr functions to add the numbers in a vector (a list whose elements are numbers). If v-sum is null, the result is 0. If v-sum is non-null, the first element is added to the cdr of v-sum recursively until the cdr of v-sum sum is the null list:

=>(define(v-sum v)
((null? v) 0)
(else (+ (car v) (v-sum (cdr v))))))
Variable v is replaced by a vector when function v-sum is executed:

=> (definev
‘(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23 24 25 26
27 28 29 30))
=>(v-sum v)

A Matrix Example

In this example we create matrix-one, a 5-by-4 matrix. Then, using matrix-one, we create matrix-two, a 5-by-3 matrix whose first column is the product of columns 1 and 2 in matrix-one, and whose second and third columns are columns 3 and 4 in matrix-one.

In Scheme, the matrix

2 6 87 92

5 23 15 8

2 32 45 1

56 7 29 4

8 48 25 6

may be written as:

 =>(define matrix-one 

          ‘((2 6 87 92) 

          (5 23 15 8) 

          (2 32 45 1) 

          (56 7 29 4) 

          (8 48 25 6))) 


We can test this by evaluating matrix-one:

  => matrix-one

  ((2 6 87 92) (5 23 15 8) (2 32 45 1) (56 7 29 4) (8 48 25 6))

The following expression will select column n in any matrix that contains at least n columns:

 => (define (col-n n matrix)

        (cond ((null? matrix) ‘())

              (else (cons (list-ref (car matrix) n)

                          (col-n n (cdr matrix))))))


What’s going on here? First, the list-ref function, which hasn’t been introduced before, selects the nth element in a list, e.g.,

 => (list-ref ‘(101 102 103 104 105) 3)


Returning to col-n, the cond function tests matrix to see if it is null. If matrix isn’t null, the list-ref function selects element n in the current vector (first row of the [current] matrix = "first matrix"), which will be cons-ed with the results of subsequent iterations of col-n of the cdr of matrix. When a new iteration yields a null, the list of elements is cons-ed with ().

Let’s test column 1 in matrix-one:

 =>(col-n 1 matrix-one)

(2 5 2 56 8)

Let’s test column 2 in matrix-one:

 =>(col-n 2 matrix-one)

(6 23 32 7 48)

Now that we know how to get columns 1 and 2, we can modify col-n slightly to get the product of columns 1 and 2:

=> (define (m-times-n m n matrix)

              (cond ((null? matrix) ())


                     (cons (* (list-ref (car matrix) m)

                              (list-ref (car matrix) n)) 

                     (m-times-n m n (cdr matrix)))))) 

We now have two column parameters, m and n, and now we cons the products of the list-ref of m and n of the car of matrix.

Let’s test m-times-n for columns 1 and 2:

=> (m-times-n 1 2 matrix-one)

(12 115 64 392 384)

Now we can get everything we need from matrix-one: any column and the product of any two columns. We need: the product of columns 1 and 2; column 3; and column 4. We get these columns as vectors, so first we’ll lay them out as rows in an intermediate matrix named matrix-temp:

=> (define matrix-temp

              (list (m-times-n 1 2 matrix-one)

                    (col-n 3 matrix-one)

                    (col-n 4 matrix-one)))

We got matrix-temp by cons-ing the product of columns 1 and 2, column 3, column 4, and left & right parentheses.

Let’s see matrix-temp:

=> matrix-temp

((12 115 64 392 384) (87 15 45 29 25) (92 8 1 4 6))

Finally, we’ll use col-n to get columns 1, 2, 3, 4, and 5 from matrix-temp, and we’ll cons them all together within left and right parentheses to get matrix-two, our objective:

=> (define matrix-two 

              (list (col-n 1 matrix-temp)

                    (col-n 2 matrix-temp)

                    (col-n 3 matrix-temp)

                    (col-n 4 matrix-temp)

                    (col-n 5 matrix-temp)))

Now, let’s see matrix-two:

=> matrix-two

((12 87 92) (115 15 8) (64 45 1) (392 29 4) (384 25 6))

The PACT SCHEME/SX Reference

This section constitutes a more formal reference for using PACT SCHEME and SX. There are two main sections (one for SCHEME and one for SX) each of which is divided into two sections (SCHEME level use and C level use).

PACT Scheme Procedures

Although many of the procedures of Scheme can be expressed in terms of an irreducible set of primitive Scheme functions, the PACT Scheme implementation (as well as the R4RS description) provides a fairly rich set of Scheme functions which are coded at the C level. These run faster by virtue of running from compiled rather than interpreted code, and they make life a little bit easier for programmers by providing many procedures which would otherwise have to be supplied by the programmer.

In PACT Scheme, I implemented two sets of functions. The first set constitutes the core of the interpreter. The second set are not so essential to the majority of applications and on small memory machines are expendable given the choice between having these functions and not fitting on the machine. This second set will be referred to as the large set and the first set will be referred to as the core set. I will document these two sets separately.

The description of the functions consists of the following information:


Information for C based applications wanting to use this function

Description of the function

Usage of the function as a formal description


For example:

Macro: Evaluate and return the consequent expression if the test evaluates to #t and evaluate and return the alternate expression otherwise.
Usage: (if test consequent alternate).
Example: (if (= i 3) (display “yes”) (display “no”))

The Core Set

Procedure: Return sum of args or 0 if no args are supplied.

Procedure: Return difference of args.

Procedure: Return product of args or 1 if no args are supplied.

Procedure: Return quotient of args (left associative).

Procedure: Return the first argument raised to the power of the second.

Procedure: Return bitwise and of the arguments (left associative)."

Procedure: Return bitwise or of the arguments (left associative)."

Procedure: Return bitwise complement of the argument."

Procedure: Return left shift of first argument by the number of bits" specified by the second.

Procedure: Return right shift of first argument by the number of bits" specified by the second.

Procedure: Return #t iff the first argument is less than the second.

Procedure: Return #t iff the first argument is less than or equal to the second.

Procedure: Return #t iff the first argument is equal to the second.

Procedure: Return #t iff the first argument is greater than the second.

Procedure: Return #t iff the first argument is greater than or equal to the second.

Procedure: Return the absolute value of a numeric object.

Procedure: Return the arc cosine of the argument.

Macro: Evaluate expressions from left to right until one evaluates to #f. The value of the last evaluated expression is returned.

Procedure: Return a new list made from a copy of the first and the second arguments.

Macro: Cons the procedure onto the args and evaluate the result.

Procedure: Search the symbol table for documentation.

Procedure: Return #t if the object is an ascii file and #f otherwise.

Procedure: Return the arc sine of the argument.

Procedure: Return the first list whose car is equal? to the first arg.

Procedure: Return the first list whose car is eq? to the first arg.

Procedure: Return the first list whose car is eqv? to the first arg.

Procedure: Return the arc tangent of the argument.

Macro: Evaluate a list of expressions and return the value of the last one.

Procedure: Return #t if the object is a boolean and #f otherwise.

Procedure: Enter a Scheme break, return with return-level. A Scheme break is simply a recursively executed read-eval-print loop. It constitutes a separate loop n which to perform tasks before returning to the preceding evaluation.

C Information: SS_caaar
Procedure: Return the caaar of the argument.

C Information: SS_caadr
Procedure: Return the caadr of the argument.

C Information: SS_caar
Procedure: Return the caar, i.e. the car of the car, of the argument.

C Information: SS_cadar
Procedure: Return the cadar, i.e. the car of the cdr of the car, of the argument.

C Information: SS_caddr
Procedure: Return the caddr, i.e. the car of the cdr of the cdr, of the argument.

C Information: SS_cadr
Procedure: Return the cadr, i.e. the car of the cdr, of the argument.

C Information: SS_car
Procedure: Return the first member of the pair which is the argument. For a simple pair this is the left hand member and for a list it is the leftmost member of the list.

Procedure: Pass an escape procedure (a special procedure of one argument) to the argument.

C Information: SS_cdar
Procedure: Return the cdar, i.e. the cdr of the car, of the argument.

C Information: SS_cdaar
Procedure: Return the cdaar, i.e. the cdr of the car of the car, of the argument.

C Information: SS_cdadr
Procedure: Return the cdadr, i.e. the cdr of the car of the cdr, of the argument.

C Information: SS_cddar
Procedure: Return the cddar, i.e. the cdr of the cdr of the car, of the argument.

C Information: SS_cdddr
Procedure: Return the cdddr, i.e. the cdr of the cdr of the cdr of the argument.

C Information: SS_cddr
Procedure: Return the cddr, i.e, the cdr of the cdr, of the argument.

C Information: SS_cdr
Procedure: Return the second member of the pair which is the argument.

Procedure: Return the smallest integer greater than the argument.

Procedure: Close the specified input port and release the IN_PORT object.

Procedure: Close the specified output port and release the OUT_PORT object.

Macro: Evaluate the list of cond clauses returning the value of the first one whose first expression does not evaluate to #f. A cond clause is a list of expressions whose irst element is evaluated and if the result is not #f, the remaining expressions are evaluated and the value of the last one is returned as the value of the clause, otherwise the cond clause evaluates to #f.

Procedure: Return a new pair whose car and cdr are the arguments.

Procedure: Return the cosine of the argument.

Macro: Define variables and procedures in the current environment.

Macro: Define a macro in the current environment.

Procedure: Print the documentation for a procedure to the specified device.

Procedure: Print an object to the specified device in human readable form.

Procedure: Return #t if the object is an end-of-file and #f otherwise.

Procedure: Return #t iff the two objects are identical, i.e. the two objects are the same object.

Procedure: Return the result of recursively applying eqv? to the arguments.

Procedure: Return #t iff the two objects are equivalent, i.e. the values of the two objects are the same.

Procedure: Evaluate the given form and return the value.

Procedure: Return #t iff the argument is a number divisible exactly by 2.

Procedure: Return the exponential of the argument.

Procedure: Return the first argument raised to the power of the second.

Procedure: Return #t if the object is a file and #f otherwise.

Procedure: Return the greatest integer less than the argument.

Procedure: Apply a procedure to a set of lists (for side effect).

Procedure: Return #t if the object is a GUEST object and #f otherwise.

Macro: Evaluate and return the consequent expression if the test evaluates to #t and evaluate and return the alternate expression otherwise.

C Information: SS_inportp
Procedure: Return #t if the object is an input port (IN_PORT) and #f otherwise.

Procedure: Return #t if the object is an integer number and #f otherwise.

Macro: Define an anonymous procedure.

Procedure: Return the last element of a list or return any other object.

C Information: SS_length, SS_nargs
Procedure: Return the number of elements in the given list.

C Information: SS_let, UE_MACRO, SS_nargs
Macro: Define a region with variables of local scope.

Macro: Define a region with variables of local scope. The variables can be used in the definition of other variables as soon as they are defined.

Procedure: Return a new list made up of the arguments.

Procedure: Return the natural logarithm of the argument.

Procedure: Open a file of Scheme forms and eval all the objects in it. If the optional flag is #t load all objects into the global environment.

llnl logo  
  LLNL-CODE-422942| Privacy & Legal Notice
Last modified: January 28, 2010