Lecture 01
For next time:
Sign up for the class mailing list and (optionally) the CS @ Olin mailing list.
Get the book(s).
Read Louden, Programming Languages, Chapter 1, Sections 1.1 through 1.3 and answer the reading questions below.
Do the Warmup exercises in Homework 1.
What is this class about?
Programming paradigms
1) functional programming in Scheme
2) logic programming in Prolog
Automata
1) regular expressions and finite automata
2) context-free grammars and pushdown automata
Theory of computation
1) Turing machine
2) decidability
Complexity
1) analysis of algorithms
2) P and NP
3) Incompleteness
Algorithms and data structures
1) especially tree-shaped structures and computation
Language translation
1) parsing
2) maybe code generation
Skills
1) polyparadigmatic thinking
2) practical language design and translation
3) algorithmic thinking
4) proof design
5) theory appreciation
Scheme syntax
[Note: this presentation follows Abelson and Sussman, Structure and Interpretation of Computer Programs.
You might prefer to read The Racket Guide.]
Numbers are primitive expressions.
Standard arithmetic operators are built in: +-*/
Applying operators to operands looks like this:
(+ 1 2)
The parentheses are not decorative; they are the "apply" operator.
+ 1 2
is just a sequence of three values.
This placement of the operator is called prefix, as opposed to infix and postfix.
Do you know languages/contexts that use infix? postfix?
What are the pros and cons of each?
This is a small example of a kind of discussion I want us to have:
1) map out the space of possible designs by exploring endpoints
2) understand tradeoffs in the space.
Compound expressions
An advantage of Scheme syntax is that the meaning of an expression is unambiguous.
In "normal" notation, what does 1 + 2 * 3 mean?
What are the two possibilities?
How do you represent the possibilities?
How do you know which one is right?
Draw a tree that represents this compound expression:
(* (+ 2 (* 4 6))
(+ 3 5 7))
Evaluating expressions
Here is Racket syntax in BNF:
‹expr› ::= ‹id›
| ( ‹expr›+ )
| ( lambda ( ‹id›* ) ‹expr› )
| ‹val›
‹val› ::= ‹number› | ‹primop›
‹id› ::= any name except for lambda
Where ::= is pronounced "can be" and | is pronounced "or".
An expression can be
1) An identifier,
2) One or more identifiers in parens,
3) A lambda expression, or
4) A value.
That's pretty much it.
Variable binding
define is an operator that creates a binding between a name and a value
(define pi 3.1415926535897931)
Now the expression
pi
has the value 3.1415926535897931
This is not the same as an assignment statement in an imperative language, because you cannot rebind a name.
An environment is a set of bindings.
Procedures
A procedure is an object* that represents a function.
[*LISP/Scheme programmers probably wouldn't call it that.]
There are two ways to create a procedure. One is the lambda operator
(lambda (x) (+ x 1))
The value of this expression is an object that represents the function SUCCESSOR.
(lambda (y) (+ y 1))
The value of this expression is an object that _also_ represents the function SUCCESSOR. So these two procedures are equivalent.
You can bind a name to a procedure.
(define square (lambda (x) (* x x)))
But this sort of thing happens so often that there is a simplified syntax, also known as 'syntactic sugar':
(define (square x)
(* x x))
If you are used to languages with a return statement, this might seem odd. All procedures contains a single expression; the 'return value' is the value of that expression.
Write a procedure, (sum-of-squares), that takes two arguments and uses (square) to compute their sum of squares.
Reading questions
Louden, Programming Languages, Chapter 1, Sections 1.1 through 1.3
1) The first sentence of the chapter is a statement of what famous hypothesis in linguistics?
2) What are the elements of the von Neumann model of a computer?
3) What is Church's thesis? You might want to read the Wikipedia page, too.
4) Louden claims that one of the necessary features of a programming language is that it be machine-readable. Can you think of some limitations this requirement puts on programming languages?
5) In the context of data, give an example of a basic abstraction, a structured abstraction and a unit abstraction.
6) In the context of control flow, give an example of a basic abstraction, a structured abstration and a unit abstraction.
7) In Louden's vocabulary, what's the difference between a procedure and a function?
[The paragraph in the middle of page 1-9 is important.]
8) What are the 3.5 programming paradigms?
9) What is the lambda calculus?
10) What does it mean to say that a language is Turing complete?
11) What is a very high level language?