Composing Programs


Composing Programs


1.1 Getting Started

Computer science is a tremendously broad academic discipline.
The high productivity of computer science is only possible because the discipline is built upon an elegant and powerful set of fundamental ideas.
These fundamental ideas have long been taught using the classic textbook Structure and Interpretation of Computer Programs (SICP) by Harold Abelson and Gerald Jay Sussman with Julie Sussman.

1.1.1 Programing in Python

A language isn't something you learn so much as something you join.    —Arika Okrent

These notes maintain the spirit of SICP by introducing the features of Python in step with techniques for abstraction and a rigorous model of computation.

1.1.2 Install Python 3

1.1.3 Interactive Sessions

In an interactive Python session, you type some Python code after the prompt, >>>.

1.1.4 First Example

And, as imagination bodies forth The forms of things to unknown, and the poet's pen
Turns them to shapes, and gives to airy nothing A local habitation and a name.    —William Shakespeare, A Midsummer-Night's Dream

`>>> from urllib.request import urlopen`
**Statements & Expressions**. Python code consists of expressions and statements. Broadly, computer programs consist of instructions to either
1. Compute some value
2. Carry out some action
Statements typically describe actions. When the Python interpreter executes a statement, it carries out the corresponding action. On the other hand, expressions typically describe computations. When Python evaluates an expression, it computes the value of that expression.

`>>> shakespeare = urlopen('http://composingprograms.com/shakespeare.txt')`
**Functions**. Functions encapsulate logic that manipulates data. urlopen is a function. A web address is a piece of data, and the text of Shakespeare's plays is another. The process by which the former leads to the latter may be complex, but we can apply that process using only a simple expression because that complexity is tucked away within a function

`>>> words = set(shakespeare.read().decode().split())`
`Objects`. A set is a type of object, one that supports set operations like computing intersections and membership. An object seamlessly bundles together data and the logic that manipulates that data, in a way that manages the complexity of both.

`>>> {w for w in words if len(w) == 6 and w[::-1] in words}`
{'redder', 'drawer', 'reward', 'diaper', 'repaid'}

`Interpreters`. Evaluating compound expressions requires a precise procedure that interprets code in a predictable way. A program that implements such a procedure, evaluating compound expressions, is called an interpreter.

1.1.5 Errors

The fundamental equation of computers is:

**computer = powerful + stupid**

Computers are very powerful, looking at volumes of data very quickly. Computers can perform billions of operations per second, where each operation is pretty simple.

Computers are also shockingly stupid and fragile. The operations that they can do are extremely rigid, simple, and mechanical. The computer lacks anything like real insight ... it's nothing like the HAL 9000 from the movies. If nothing else, you should not be intimidated by the computer as if it's some sort of brain. It's very mechanical underneath it all.

Programming is about a person using their real insight to build something useful, constructed out of these teeny, simple little operations that the computer can do.    —Francisco Cai and Nick Parlante, Stanford CS101

Learning to interpret errors and diagnose the cause of unexpected errors is called debugging. Some guiding principles of debugging are:

1. Test incrementally: Every well-written program is composed of small, modular components that can be tested individually. Try out everything you write as soon as possible to identify problems early and gain confidence in your components.
2. Isolate errors: An error in the output of a statement can typically be attributed to a particular modular component. When trying to diagnose a problem, trace the error to the smallest fragment of code you can before trying to correct it.
3. Check your assumptions: Interpreters do carry out your instructions to the letter — no more and no less. Their output is unexpected when the behavior of some code does not match what the programmer believes (or assumes) that behavior to be. Know your assumptions, then focus your debugging effort on verifying that your assumptions actually hold.
4. Consult others: You are not alone! If you don't understand an error message, ask a friend, instructor, or search engine. If you have isolated an error, but can't figure out how to correct it, ask someone else to take a look. A lot of valuable programming knowledge is shared in the process of group problem solving.