Principles of Programming
Principles of Programming
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.
The params are zero or more parameters. body is an expression which refers to the parameters.
There are many different ways of defining equivalent procedures, so what is the best way
to do so? Not using abstraction. SICP 1.1.4
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.
Scheme uses the substitution model for evaluation, so evaluating some simple code
goes like this: SICP p13/14
(triple 5)
(+ 5 (double 5))
(+ 5 (*2 5))
(+ 5 10)
15
Choice
either/or
You can do either/or choices like so: (if expression then else).
SICP 1.1.6
expression is evaluated to true or false.
then is the value of the if expression if the expression is true
else is the value of the if expression if the expression is false.
#f is false, and #t is true, however anything that isn't #f is considered to be true.
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
Evaluation
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
evaluate to « evaluates
+ - » primitive to numbers, symbols,
quote (built in) booleans
compound
(lambda) (built from primitive and other ?
compound)
Lists
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.
(length list)
SICP p102
This is the number of elements in the list.
The definitions bind names to values. Then expr is evaluated in a local environment in which these
bindings are valid.
expr is said to be in scope of these bindings.
SICP 1.1.8
(let ((name value) (name value) ...) expr)
The value of the (let) expression is the value of expr in the environment in which each name
corresponds to a value. This avoids evaluating the same code repeatedly.
N.B. expr is any expression, including another (let). (let)s can be nested.
SICP p63-66
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)
O(something) resource means roughly: "resource is used up no faster than something as the
problem size increases" SICP 1.2.3
ADS
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
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 SICP p35
is the last thing done by the procedure. Tail recursive procedures generate iterative
processes (O(1) space complexity)
Complexity
Abstraction
Abstract (adjective)
1. Separated from matter, practice or particular examples.
2. Ideal or theoretical way of regarding things See: Dictionary
Abstract (verb)
remove, summarise
Abstraction (noun)
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)
(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
(set! name expression)
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.
• 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
(cons x y) creates a new pair
SICP 2.2, 2.3
The contents of the pair are pointers.
Equality
=, two numerical values are the same
SICP p257-258
eq?, two pointers are the same
equal?, two structures are the same (here, it is the representation of the structures
that are compared)
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
To create a one-dimensional table as an association list with a header pair.
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.