Notes Week 1-5
Notes Week 1-5
Notes Week 1-5
Contents
1 Overview 3
1.1 What is a Programming Language? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Why Different Languages? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Language Paradigms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.1 Imperative Paradigm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2 Object-Oriented Paradigm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.3 Functional Paradigm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.4 Logic Paradigm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Language Choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1
2.16 Partial Function Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.17 Algebraic Data Types/Immutable Data Structures . . . . . . . . . . . . . . . . . . . . . 13
3 Scripting (Python) 13
3.1 Program Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.4 Parameter Passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.5 List/Set/Dictionary Comprehension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4 Data 14
4.1 Variables and Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.2 Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.3 Static and Dynamic Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.3.1 Static Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.3.2 Dynamic Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3.3 Duck Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3.4 Gradual Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4 Strong and Weak Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4.1 Strong Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.4.2 Weak Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5 Conversions, Casts, Coercion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.1 Type Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.2 Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.3 Casts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.4 Widening and Narrowing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.5 Explicit and Implicit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2
1 Overview
1.1 What is a Programming Language?
A programming language is a structured system of communication designed to express computations
in an abstract manner.
(i) Javascript is the most popular language for anything related to web development. There are many
frameworks for vanilla Javascript (e.g. React) as well as derivative languages (e.g. Typescript).
(ii) C/++ is a popular language for programs that require high performance (e.g. Linux).
(iii) C# is most commonly used for programs that are in Microsoft’s .NET ecosystem.
(iv) Python is a popular language used in the field of artificial intelligence.
(v) ba/z/sh is a scripting language for UNIX-based operating systems.
(vi) R is a popular language among statiticians (not sure why).
(vii) Lisp is a functional language used in the field of artificial intelligence and was used to write
Emacs.
(viii) SQL and its variants are a set of querying languages used to communicate with databases.
(iii) Functional
(iv) Logic
3
1.3.4 Logic Paradigm
Logic programming the most abstract and is a type of declarative programming. A set of facts and
rules are defined within the scope of the program. Common examples of logic languages are Prolog
and ASP.
2.1 Overview
Haskell is a statically typed language that uses type inference. All functions must have the
following properties:
(i) Functions must take in an argument
(ii) Functions must return a value
(iii) Be pure (does not change the state of the program (Note: This includes I/O!)
(iv) In functions, all variables are immutable
(v) Functions are first-class citizens, so they are treated as data
2.3 Syntax
Haskell syntax for defining a function is as follows:
function_name params = function_body
4
2.3.1 Indentation
In Haskell, any part of an expression must be indented further than the beginning of the function. e.g.
mult x y =
x * y
Operations
Arithmetic operations include +, -, *, /, ^ ‘div‘, ‘mod‘.
Note: Parentheses are required for the unary - (e.g. (-3) represents -3)
Note: Airthmetic operators can also be called using prefixed notation (e.g. (+) a b is equivalent
to a + b)
2.5.1 Tuples
Tuples have two built-in functions: fst, snd which retrieve the first and second elements respectively.
Consequently, accessing any element after the second requires a user-defined function.
2.5.2 Lists
Lists are not arrays, and are structured internally like linked-lists. Therefore, most operations are
O(n) in time complexity.
head :: [a] -> a
head LIST Returns the head of the list.
5
tail LIST Returns the tail of the list.
2.5.3 Strings
Strings are just a list of characters. Therefore, we can concatenate strings and perform list operations:
str :: String
str = "some"
other_str :: String
other_str = " string"
combined_str :: String
combined_str = str ++ other_string
will return "some string". Moreover,
"same" == [’s’, ’a’, ’m’, ’e’]
will return True
1 (a , bi ) where ai ∈ LIST 1, bi ∈ LIST 2, 0 ≤ i ≤ (min (length LIST 1) (length LIST 2))
i
6
2.6 List Processing
2.6.1 Creating Lists (Concatenation and Cons)
Lists can be created directly or indirectly via concatenation or consing:
Direct Creation
some_list = [1, 2, 3]
Concatenation
some_list = [1, 2, 3]
new_list = some_list ++ [4, 5, 6]
Here, new list is [1, 2, 3, 4, 5, 6]
Consing
some_list = [1, 2, 3]
new_list = 0 : some_list
Here, new list is [0, 1, 2, 3]
2.6.2 Ranges
Ranges are inclusive from both sides. By default, they are incremented by 1.
Incremented by 1
one_to_ten = [1..10]
Here, one to ten is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Incremented by X (= 2)
odds = [1, 3..10]
Here, odds is [1, 3, 5, 7, 9]
Infinite Lists
infty = [1..]
Here, infty is [1, 2, ...]
Cyclic Lists
cyclic = cycle [1, 2, 3]
Here, cyclic is [1, 2, 3, 1, 2, 3, ...]
7
Example with Numbers
squares = [x^2 | x <- [1..3]
some_function =
if *condition* then
*statements*
else
*statements*
2.8.1 Constants
To pattern match functions with constants, we define multiple versions of the same functions that all
have the same number and types of arguments. Then, we define unique parameters. Note that order
matters. Haskell will try to match top to bottom. The syntax is as follows:
8
2.8.2 Tuples
Pattern matching with tuples is similar, but we can decompose the tuple. The syntax is as follows:
exp :: (Int, Int) -> Int
exp (_, 0) = 1
exp (a, b) = a ^ b
2.8.3 Lists
Pattern matching lists are similar to pattern matching tuples. Note that we can decompose a list
multiple different ways:
(i) (x:xs) where x is the head and xs is the rest of the list (excluding x).
(ii) x:...:xs) where ... represents the second to ith element of a list.
(iii) [a, b, c] where a, b, c correspond to the first, second, and third elements of the list respec-
tively.
2.9.1 let
some_function arg =
let
x = 10 + arg
*statements*
in
if x == 10 then
*something*
else
*something else*
2.9.2 where
some_function arg =
if x == 10 then
*something*
else
*something else*
where
x = 10 + arg
*statements*
9
2.11 Functions
Functions are left-associative by default. That is,
a b c ⇐⇒ ((a b) c). Additionally, they get called before operators. Below are equivalences
between mathematical functions and Haskell’s function-calling syntax
f (x) ⇐⇒ f x
f (x, y) ⇐⇒ f x y
f (g(x)) ⇐⇒ f (g x)
f (x, g(y)) ⇐⇒ f x (g y)
f (x)g(y) ⇐⇒ (f x) * (g y) ⇐⇒ f x * g y
Higher order functions are functions that accept another function as an argument or return another
function as its return value.
Functions as Arguments
Int -> (Int -> Int) -> Int indicates a function that takes in an Int and a function that takes
in and returns an Int and returns an Int.
Returning a function
Int -> (Int -> Int) indicates a function that takes in an Int and returns a function that takes in
an Int and returns an Int.
10
2.12.1 map
To implement map, we do
map :: (a -> b) -> [a] -> [b]
map func [] = []
map func (x:xs) =
(func x) : (map func xs)
An example of map:
cube :: Double -> Double
cube x = x^3
2.12.2 filter
To implement filter, we do
filter :: (a -> Bool) -> [a] -> [a]
filter predicate [] = []
filter predicate (x:xs) =
| (predicate x) = x : (filter predicate xs)
| otherwise = filter predicate xs
An example of filter:
even :: Int -> Bool
even n =
n ‘mod‘ 2 == 0
2.12.3 reduce
There are two ways to reduce: foldl, foldr to force associativity of functions. foldl is left-
associative; that is, foldl calls f(f...f(accum, x1 )..., xn ) whereas foldr is right-associative;
that is, foldr calls f(x1 , f(x2 , ... f(xn , accum)...)) To implement foldl, we do:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl func accum [] = accum
foldl f accum (x:xs) =
foldl f new_accum xs
where new_accum = (f accum x)
To implement foldr, we do:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr func accum [] = accum
foldr func accum (x:xs) =
func x (foldr func accum xs)
An example of foldl:
sub :: Int -> Int -> Int
sub x y = y -x
11
2.13 Lambda Functions
A lambda function is a function without a name attached to it. They are most often thought of as
throwaway functions (e.g. cube x = x ^3 ⇐⇒ \x -> x ^3).
2.14 Closures
A closure is a combination of a lambda expression and all captured variables. For example, consider
result = two_x_plus_one 9
Here, result is 19. When we define two x plus one, it is assigned (\x -> 2 * x + b) Therefore,
calling two x plus one 9 passes in 9 to x, which then evaluates the lambda expression \(x = 9) ->
2 * (x = 9) + 1 =⇒ 19, hence, result is 19.
A closure captures all free variables and its lambda’s bounded parameters. That is, m, b are free
while x is bounded to the lambda expression (from the example above). Both of these make up its
closure.
2.15 Currying
Currying is the process of transforming a single function with multiple parameters into multiple func-
tions with a single parameter.3 For example,
12
Here, result is 5. f1 is defined as
\(x = 2) -> (\y -> (\z -> (x = 2) * y * z
and f2 is defined as
\(x = 2) -> (\(y = 3) -> (\z -> (x = 2) * (y = 3) * z.
So, when we call f2 5, we get
\(x = 2) -> (\(y = 3) -> (\(z = 5) -> (x = 2) * (y = 3) * (z = 5) =⇒ 30, hence, result
is 30.
Note that Algebraic Data Type fields are positional, and the pipe operator | distinguishes variants.
3 Scripting (Python)
Python is a dynamically typed scripting language that executes statements top-down (excluding control
flow).
3.2 Classes
In Python, the self keyword is explicit. By default, all attributes are public. To make them private,
we do var and to make them protected, we do var.
Destructors ( del ()) are rarely used in Python since Python has automatic garbage collection.
3.3 Objects
In Python, all variables are object references (similar to pointers); that is, everything is allocated on
the heap. Some objects include:
(i) Strings: Immutable
(ii) Lists: Mutable, but assignment (=) creates a new list
(iii) Tuples: Immutable
To get the object id of an object, we do id(var).
13
3.4 Parameter Passing
In Python, since everything is an object reference, we also pass everything by object reference.
4 Data
This section covers how languages internally manage data (including types, variables, and values).
14
4.2 Types
Variables need not be typed, but values must have a type associated with them. We can infer about
a value (given its type):
(i) The set of legal values
(iii) Char
(iv) Enum
(v) Boolean
(vi) Pointer
(iii) Union
(iv) Array
(v) Container
(vi) Struct
Note: Statically typed languages must have a fixed type bound to each variable at the time of
definition.
Statically typed languages are inherently conservative; that is, they may disallow valid programs
that don’t violate typing rules.
15
Pros
(i) Produces faster run-time code
(ii) Earlier type-related bug detection
(iii) No custom type checking
Cons
(i) Conservative (and therefore may not compile even when the program is correct)
(ii) Slower compile-time since it has to type check
Pros
(i) Increased flexibility
(ii) Easier to implement generics that operate on different types of data
Cons
(i) We detect errors much later
Note: Downcasting (in C++) allows for runtime checking in an otherwise statically typed language
Note: Duck typing can be done (to an extent) in statically typed languages via templates (in C++).
16
4.4.1 Strong Typing
A strongly typed language guarantees that we never get undefined behavior at runtime due to type
issues. This implies that there is no possibility of an unchecked runtime type error. The minimum
requirements to be strongly typed are:
(i) The language is type-safe: Prevent operations on a variable if it’s incompatible.
(ii) The language is memory-safe: Prevents invalid memory access, has bounds checking, no dangling
pointers.
These can be enforced either statically or dynamically. To implement strong typing, we need to
(i) Validate before evaluation
(ii) Check all conversions
(iii) Assign all pointers to either null or a valid object
As a consequence, we have that strongly typed =⇒ memory safe.
4.5.2 Conversions
Values will get copied from TA → TB . Conversions will occupy a new memory location with a different
bit encoding and will now have TB . Conversions most often happen between primitives (e.g. float →
int).
4.5.3 Casts
Values do not get copied, but rather treats the value of TA as if it were of TB ; that is, no conversion
takes place. Casts are typically used with objects.
17