Professional Documents
Culture Documents
Computer Science Notes
Computer Science Notes
Programming
This minisite contains notes taken by Chris Northwood whilst studying Computer Science at the
University of York between 2005-09 and the University of Sheffield 2009-10.
They are published here in case others find them useful, but I provide no warranty for their
accuracy, completeness or whether or not they are up-to-date.
The contents of this page have dubious copyright status, as great portions of some of my revision
notes are verbatim from the lecture slides, what the lecturer wrote on the board, or what they
said. Additionally, lots of the images have been captured from the lecture slides.
This module relies on the textbook "Structure & Interpretation of Computer Programs (2nd
Edition)" by Abelson, Sussman and Sussman.
This module doesn't teach you how to program in a particular language, but how to program in
general principles that can be applied to any language. A good analogy is that between linguistics
and English. Linguistics teaches the principle of language, whereas English just teaches one
particular language. However, as linguistics is taught in English, we also need to know a
language to demonstrate programming skills in. Such a language is Scheme.
Introduction to Scheme
Scheme uses a Read-Eval-Print loop:
In Scheme, numbers are expressions known as primitive expressions. Other expressions are
compound (or combination) expressions.
Scheme uses prefix notation, for example: (+ 7 6) gives 13. Expressions can be also be
nested. 2 + 3 * 4 is equivalent to (+ 2 (* 3 4)) in Scheme.
The value of a compound expression is the result of applying the procedure specified by the
operator to the operands.
To avoid typing out long expressions multiple times when applying different procedures to it,
you can use definitions, for example: (define name value). This
Creates a new variable - allocates a memory location where values are stored.
Gives the location a name and links the name to that variable.
Puts the value in that location.
Scheme stores the variables in a table of names and values called the environment.
SICP p62
Procedures are defined using lambda. The value of (lambda) is the procedure, which when
applied to a list of operand values evaluates body with substitutions for the corresponding
parameters.
The params are zero or more parameters. body is an expression which refers to the parameters.
SICP 1.1.4
There are many different ways of defining equivalent procedures, so what is the best way to do
so? Not using abstraction.
Abstraction is the generalisation of a method, e.g., defining double and then using that rather
than (* 2 6). Abstraction is our fundamental design methodology.
SICP p13/14
Scheme uses the substitution model for evaluation, so evaluating some simple code goes like
this:
(triple 5)
(+ 5 (double 5))
(+ 5 (*2 5))
(+ 5 10)
15
Choice
either/or
SICP 1.1.6
You can do either/or choices like so: (if expression then else).
To add more power to choice, you can use logical composition operations.
This is evaluated left to right, until one is false or all are true. This is different to the standard
Scheme operation.
This also evaluates left to right, until one is true or all are false.
(not expr)
One of several
SICP p17
The value of (cond) is the value of the first expression whose predicate evaluates to true. If the
predicate is #t, this is always true and is a useful "catch-all" situation.
Evaluation
SICP ex1.5
Normal order substitutes expressions for parameters until left with primitive procedures only.
Applicative does not evaluate the operands until the values were needed. Instead, it substitutes
operand expressions for parameters until it obtained an expression involving only primitive
operators and then evaluates it.
Recursive Definition
All follow the same general pattern. It consists of both a base case (or cases), where the value
does not refer to the procedure and a recursive case, where the value uses the procedure. Which
case it is is determined by the values of the parameters.
(sequence) allows you to chain together multiple procedures, and the value is the value of the
last expression.
(print) is a special form with a side-effect. It prints a value to the terminal but does not effect
the environment in any way.
Compound Data
Procedures Data
+ - primitive numbers, symbols,
quote (built in) booleans
evaluate to « evaluates
» compound to
(lambda) (built from primitive and other ?
compound)
Lists
There are 2 forms of lists, empty and non-empty. Non-empty lists are values followed by another
list. An empty list is the value nil.
Constructors
(cons) allows you to create lists, like so: (cons expr list). This creates a list consisting
of the value of expr followed by list. Lists can also have other lists as values (sublists)
Selectors
(cdr list) returns the list without the first element (tail).
There are also shortcuts, such as (cadr list), which is equivalent to (car (cdr
list)). There are also (caddr list), (cadar list), etc.
There are also some tests (predicates) which can be applied to lists. (null? expr) is true is
the expr is nil. (list? expr) is true if expr is a list.
SICP p100
SICP p103
Creates a list containing all the elements of list1, followed by all of the elements of list2
SICP p102
(length list)
The definitions bind names to values. Then expr is evaluated in a local environment in which
these bindings are valid.
SICP 1.1.8
SICP p63-66
N.B. expr is any expression, including another (let). (let)s can be nested.
Computational Processes
A process is represented by a sequence of operations that are generated by a procedure when it is
evaluated.
Memory is stored in the stack. The stack space required for our our factorial program is
proportional to n, where n is the number to be computed. We say this is of order n, or O(n). The
time complexity is also O(n)
SICP 1.2.3
ADS
O(something) resource means roughly: "resource is used up no faster than something as the
problem size increases"
Factorial Iteratively
To do factorial iteratively, we need to keep a note of the answer so far and a counter which goes
up from 1. This gets passed as parameters in our recursion. When counter > n, the final answer is
the same as the answer so far. This has a space complexity is O(1). Any procedure that has a
space complexity of O(1) is called iterative.
Tail Recursion
SICP p35
A procedure that is tail-recursive if the recursive call is not a sub-expression of some other
expression in the procedure body. Informally, something is tail recursive is a recursive call is the
last thing done by the procedure. Tail recursive procedures generate iterative processes (O(1)
space complexity)
Complexity
SICP 1.2.2
Time Space
Recursive O(kn) O(kn) "exponential"
Iterative O(n) O(1)
Abstraction
See: Dictionary
Abstract (adjective)
Abstract (verb)
remove, summarise
Abstraction (noun)
named by variables
passed as arguments to procedures
returned as the results of procedures
included in data structures
For example, lists are a built in ADT in Scheme. You have constructors (cons, nil), selectors
(car, cdr) and type predicates (list?, null?) .
Using this type of abstraction allows you to split the load of creating a system.
Types
A type is a set of values (and operations, procedures, etc - e.g., eq? a b). x :: t means x is a type
of t. e.g., in Scheme:
Type Constructors
Product: A x B is the type of a pair of values, the first of type A and second of type B.
Union: A + B is the type of a value of type A or of type B.
Function: A -> B is the type of a procedure which takes a value of type A and returns a value of
type B.
(+ a b)
(Number x Number) --> Number
(sigma f a b)
combine-with :: ((number x number) --> number) x number x (number --> number) x number x
number --> number
ax2 + bx + c
Type Checking
Static
Dynamic
Functional languages (Haskell, ML, etc) exist that combine both. They have very powerful static
type checking, the best of both worlds.
Representing Objects
Assignment
SICP 3.1
Changes the value bound to a name to the value of an expression. The name must already be
defined and exist in the environment which set! is evaluated.
To evaluate a compound procedure, evaluate the body of the procedure with each formal
parameter replaced by the value of the corresponding argument.
SICP 3.2
There are problems with global variables to store state. There may be multiple instances of items
and global variables decrease modularity. To work round this, you can encapsulate state within
an object. An object must have internal state and be active. You tell the object what to do with
the state rather than do it directly.
functional
imperative
logic
object-orientated (sometimes called message-passing)
An environment is made of frames, where frames are tables of bindings (names and values) and
a pointer to the enclosing environment. In a frame, a variable can be bound, unbound, the first
binding or a "shadow" binding (overriding any earlier bindings).
A procedure is the code and pointer to an environment. This is the environment in which the
lambda expression defining the pointer was evaluated.
e.g., "blood-donor" is an object which has state (quantity of blood) and responds to "drain"
requests. A constructor of blood donors takes a quantity of blood and returns a blood donor
object. This object is itself a procedure which responds to requests (drain, etc) and then returns
the procedure to do that event, which itself may take multiple arguments.
An object needs to be defined with initial states, the object procedure and request handling
procedures. The object constructor should return the object.
Mutators
Pointers
Box and Pointer Diagrams
SICP p257-258
We can now do (set-car! (cdr z1) 'boom) which changes 'a in the structure to 'boom.
This now makes z1 (('boom 'b) 'boom 'b) and x is now ('boom 'b). However, if
we (cons z2 (list 'a 'b) (list 'a 'b)), this makes z1 equal? to z2, but
now (set-car! (cdr z2) 'boom) gives us (('a 'b) 'boom 'b)
Association List
An association list is a list of records, each of which consists of a key and a value. Each record is
a pair formed by (cons key value).
e.g., ((answer . 23) ('y . #t) ('z . "Hello")) associates answer with 23, y
with #t and z with "Hello".
The procedure (retrieve key associations) returns the first pair in associations
which has key in its car or returns nil if there is no such record.
Tables
SICP 3.3.3
To add a new element, set the cdr of the new list element to the pointer from the header pair and
then change the header pair pointer to point at the new element.