Week 1
Week 1
Introduction
Type 📒 Lecture
Date @December 27, 2021
Lecture # 1
Week # 1
Programming Languages
A language is a medium for communication
Add the contents of the register R1 and R2 and store the result back in R1
Abstraction
Abstractions used in computational thinking
Conditional execution
Iteration
Functions/Procedures, recursion
Compilers, interpreters
Introduction 1
Trade off expressiveness for efficiency
Styles of programming
Imperative vs Declarative
Imperative
How to compute
Declarative
def sum_list(l):
sum = 0
for x in l:
sum += x
return sum
def sum_list(l):
if l == []:
return 0
else:
return l[0] + sum_list(l[1:])
Inductive step → Add the first element to the sum of the rest of the list
No intermediate variables
def sum_square_even(n):
sum = 0
for x in range(n + 1):
if x % 2 == 0:
sum += x * x
return sum
Introduction 2
def even(x):
return x % 2 == 0
def square(x):
return x * x
def sum_square_even(n):
return sum(map(square, filter(even, range(n + 1))))
No difference between data and instructions, let alone numbers, characters, booleans
Stack, for example, is a sequence but only allows push and pop
Can implement a priority queues using sorted or unsorted lists, or using a heap
Object-Oriented Programming
Functions are invoked through the object rather than passing data to the functions
Object-oriented programming
Imperative, object-oriented
Understand and appreciate why there is a zoo of programming languages out there, lol
Introduction 3
☕
Types
Type 📒 Lecture
Date @December 27, 2021
Lecture # 2
Week # 1
Incorrect assignment
x = 10 — x is of type int
Types 1
An uninitialized name has no type
def factors(n):
factorlist = []
for i in range(1, n + 1):
if n % i == 0:
factorlst = factorlist + [i] # Typo here!
return factorlist
These are synonyms for (float, float) and (float, float, float)
Makes the intent more transparent when writing, reading and maintaining code
Static analysis
Identify errors as early as possible — saves cost & effort
With variable declarations, compilers can detect type errors at compile time - static analysis
Dynamic typing would catch these errors only when the code runs
Executing code also shows down due to simultaneous monitoring for type correctness
Summary
Types have many uses
Types 2
Some languages also support automatic type inference
Deduce the types of variable statically, based on the context in which they are used
If the inferred type is consistent across the program, everything will go fine
Types 3
☕
Memory Management
Type 📒 Lecture
Date @December 27, 2021
Lecture # 3
Week # 1
Scope of a variable
In the following code, the x in f() is not in scope withing call to g()
Lifetime of a variable
Memory stack
Memory Management 1
Each function needs storage for local variables
Call factorial(3)
Scope of a variable
Lifetime of a variable
Updating the value inside the function has not side effect
It can update the contents, but cannot change the reference itself
Memory Management 2
Heap
Function that inserts a value in a linked list
Conceptually, allocate heap storage from “opposite” end with respect to the stack
After deleting a node in a linked list, deleted node is now dead storage, unreachable
Summary
Variables have scope and lifetime
Memory Management 3
Lifetime → whether the storage is still allocated
Memory Management 4
☕
Abstraction and Modularity
Type 📒 Lecture
Date @December 27, 2021
Lecture # 4
Week # 1
Stepwise Refinement
Begin with a high level description of the task
Data refinement
Banking application
Data abstraction
For example, when a stack is implemented as a list, we should not be able to observe or modify the internal
elements
Object-Oriented programming
Summary
Solving a complex task requires breaking it down into manageable components
Lecture # 5
Week # 1
Objects
An object is like an abstract datatype
Abstraction
Subtyping
Dynamic lookup
Inheritance
Challenges
Object-Oriented Programming 1
Queue must be well-types, yet hold all types of events
Abstraction
Objects are similar to abstract datatypes
Public interface
Private implementation
Changing the implementation should not affect interactions with the object
Recall that stepwise refinement could affect both code and data
Refining data representation naturally tied to updating methods that operate on the data
Subtyping
Recall the Simula event queue
Dynamic Lookup
Whether a method can be invoked on an object is a static property — type-checking
How the method acts is a dynamic property of how the object is implemented
Invoke using the same operation, each object “knows" how to render itself
Dynamic lookup
Inheritance
Re-use of implementations
Object-Oriented Programming 2
Employee objects store basic personal data, date of joining
Additional fields and functions: date of promotion, seniority (in current role)
Subtyping vs Inheritance
A deque is a double-ended queue
If v of type Deque points an object of type Stack , cannot invoke insert-rear(), delete-rear()
Summary
Objects are like abstract datatypes
Abstraction
Subtyping
Dynamic lookup
Inheritance
Reuse of implementations
Object-Oriented Programming 3
☕
Classes and Objects
Type 📒 Lecture
Date @December 27, 2021
Lecture # 6
Week # 1
Class
Object
Example: 2D points
A point has coordinates (x, y)
Each point object stores its own internal values x and y — these are called instance variables
class Point:
def __init__(self, a=0, b=0):
self.x = a
self.y = y
d= x2 + y2
Does not update instance variables
r= x2 + y2
θ = tan−1 (y/x)
Distance from origin is just r
import math
class Point:
def __init__(self, a=0, b=0):
self.r = math.sqrt(a*a + b*b)
if a == 0:
self.theta = math.pi/2
else:
self.theta = math.atan(b/a)
def odistance(self):
return self.r
Translation
x = rcosθ, y = rsinθ
Recompute r, θ from (x + Δx, y + Δy)
Abstraction
Users of our code should not know whether Point uses (x, y) or (r, theta)
Python allows direct access to instance variables from outside the class
p = Point(5, 7)
Changing the internal implementation of Point can have impact on other code
class Point:
def __init__(self, a=0, b=0):
self.x=a
self.y=b
class Point:
def __init__(self, a=0, b=0):
self.r = math.sqrt(a*a + b*b)
if a==0:
self.theta = math.pi/2
else:
self.theta = math.atan(b/a)
Different constructor
class Rectangle:
def __init__(self, w=0, h=0):
self.width = w
self.height = h
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Square(Rectangle):
def __init__(self, s=0):
self.width = s
self.height = s
a = s.area()
p = s.perimeter()
self.side
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Square(Rectangle):
def __init__(self, s=0):
self.side = s
a = s.area()
p = s.perimeter()
class Rectangle:
def __init__(self, w=0, h=0):
self.wd = w
self.ht = h
def area(self):
return self.wd * self.ht
def perimeter(self):
return 2 * (self.wd + self.ht)
class Square(Rectangle):
def __init__(self, s=0):
self.width = s
self.height = s
a = s.area()
p = s.perimeter()
How can the constructor for Square set these private variables?
Square does (and should) not know the names of the private instance variables
Summary
A class is a template describing the instance variables and methods for an abstract datatype