Files

609 lines
23 KiB
TeX

%! TeX program = lualatex
\documentclass[a4paper,11pt]{article}
% packages
\usepackage{fontspec}
\setmainfont{EB Garamond}
% for tironian et fallback
% % \directlua{luaotfload.add_fallback
% % ("emojifallback",
% % {"Noto Serif:mode=harf"}
% % )}
% % \setmainfont{EB Garamond}[RawFeature={fallback=emojifallback}]
\setmonofont[Scale=MatchLowercase]{Deja Vu Sans Mono}
\usepackage[a4paper,left=2cm,right=2cm,top=\dimexpr15mm+1.5\baselineskip,bottom=2cm]{geometry}
\setlength{\parindent}{0pt}
\usepackage{fancyhdr} % Headers and footers
\fancyhead[R]{\normalfont \leftmark}
\fancyhead[L]{}
\pagestyle{fancy}
\usepackage{multicol}
\usepackage{microtype} % Slightly tweak font spacing for aesthetics
\usepackage[english]{babel} % Language hyphenation and typographical rules
\usepackage[final, colorlinks = true, urlcolor = blue, linkcolor = black]{hyperref}
\usepackage{changepage} % adjust margins on the fly
\usepackage{minted}
\usemintedstyle{algol_nu}
\usepackage{xcolor}
\usepackage{pgfplots}
\pgfplotsset{width=\textwidth,compat=1.9}
\usepackage{caption}
\newenvironment{code}{\captionsetup{type=listing}}{}
\usepackage[yyyymmdd]{datetime}
\renewcommand{\dateseparator}{-}
\usepackage{titlesec}
\begin{document}
\begin{titlepage}
\begin{center}
\hrule
\vspace*{0.6cm}
\huge \textbf{CT331}
\vspace*{0.6cm}
\hrule
\LARGE
\vspace{0.5cm}
PROGRAMMING PARADIGMS
\vspace{0.5cm}
\hrule
\vfill
\includegraphics[width=0.8\textwidth]{images/lambda.png}
\vfill
\Large
\vspace{0.5cm}
\hrule
\vspace{0.5cm}
\textbf{Andreas Ó hAoḋa}
% \vspace{0.5cm}
% \hrule
% \vspace{0.5cm}
\normalsize
University of Galway
\today
\vspace{0.5cm}
\hrule
\end{center}
\end{titlepage}
\pagenumbering{roman}
\newpage
\tableofcontents
\newpage
\setcounter{page}{1}
\pagenumbering{arabic}
\section{Introduction}
\subsection{Lecturer Contact Information}
\begin{itemize}
\item Finlay Smith, School of Computer Science.
\item \href{mailto://finlay.smith@universityofgalway.ie}{\texttt{finlay.smith@universityofgalway.ie}}
\end{itemize}
\subsection{Syllabus}
This module introduces three different programming paradigms: Procedural, Functional \& Logical.
This will involve 3 programming languages: C (mostly function pointers - knowledge of C is assumed), LISP
(a functional language) and Prolog (a logical language).
Both LISP and Prolog will both be introduced but neither will be fully covered in this module.
There are no books required or recommended for this course.
\subsubsection{Marking}
30\% of the marks for this module will be for the three assignments (one for each paradigm).
The remaining 70\% of the marks will be for the written exam.
\subsection{Programming Paradigms}
A \textbf{paradigm} is a typical example or pattern of something; a pattern or model.
A \textbf{programming paradigm} is a pattern or model of programming.
Various types of programming languages are better suited to solving particular problems.
Programming language implementations differ on semantics \& syntax:
\begin{itemize}
\item \textbf{Syntax} refers to the rules of the language; it allows us to form valid expressions \& statements.
\item \textbf{Semantics} refers to the meaning of those expressions \& statements.
\end{itemize}
Programming languages can be classified according to the features that they have with respect to both the conceptual \& implementation
level.
An alternative definition for a \textbf{programming paradigm} is a collection of abstract features that categorise a group of
languages.
``\textit{The popularity of a paradigm is due to one community deciding which problems are important to solve and then supporting the
most promising paradigm for attacking these problems.}'' -- Thomas Kuhn.
\subsection{Influences on Paradigms}
\begin{itemize}
\item Computer Capabilities.
\item Applications.
\item Programming Methods: Language designs have evolved to reflect changing understanding of good methods for writing
large \& complex programs.
\item Implementation Methods: Early compilers to optimised compilers; structured engineering to software engineering; data
abstraction to OO.
\item Theoretical Studies: Formal maths methods have deepened our understanding of strengths \& weaknesses of language
features and thus influenced the choice \& inclusion of those features.
\item Standardisation (has proved to be a strong conservative influence on the evolution of programming language design).
\end{itemize}
\subsection{Why Learn Different Paradigms?}
\begin{itemize}
\item Different paradigms make different trade-offs; What's tricky in one paradigm is ``baked in'' in another.
\item Changing paradigms forces you to ``change gears''.
\item It will prepare you for learning languages that you've never heard of or that may not exist yet.
\item Helps you to decide what the best tool for the job is.
\item Helps you to understand languages at a deeper level.
\end{itemize}
\subsubsection{Why Learn Functional Programming?}
\begin{itemize}
\item It's one of the oldest paradigm (Lisp: 1958, still widely used today).
\item Heavily based on mathematical concepts (proofs, lambda calculations).
\item Elegant solutions (recursion).
\item Other paradigms can be interpreted in terms of functional programming.
\end{itemize}
\subsubsection{Why Learn Logical Programming?}
\begin{itemize}
\item Long history.
\item ALlows implementation of things that are difficult in other paradigms.
\item \emph{Very} different
\item Helps to conceptualise logical problems.
\end{itemize}
\subsubsection{Why Learn Imperative Programming?}
\begin{itemize}
\item The oldest paradigm -- goes back as far as punch cards \& magnetic loops.
\item Much closer representation of how the machine actually works, i.e. ``closer to the metal''.
\item Can help to recognise optimisation issues / computational bottlenecks.
\item Contextualises many other systems (UNIX, Linux, etc.).
\end{itemize}
\subsubsection{Why Learn Object-Oriented Programming?}
\begin{itemize}
\item Tries to represent the real world.
\item Abstraction \& inheritance.
\item Object-Oriented is everywhere.
\end{itemize}
\section{Overview of Object-Oriented Programming}
Object-Oriented languages include:
\begin{multicols}{2}
\begin{itemize}
\item Java.
\item C\#.
\item VB.NET.
\item Scala.
\item JavaScript.
\item Python.
\item PHP.
\item Smalltalk.
\item Ruby.
\end{itemize}
\end{multicols}
\subsection{Fundamentals of Object-Oriented Programming}
\begin{itemize}
\item Everything is an object.
\item Computation is performed by message-passing.
\item Every \textbf{object} is an \textbf{instance} of a \textbf{class} which is a grouping of similar objects.
\item \textbf{Inheritance} describes the relationships between classes.
\end{itemize}
Object-Oriented Programming focuses on the objects that the program represents and allows them to exhibit ``behaviour''.
\subsection{Four Major Principles of OOP}
\subsubsection{Encapsulation}
Data is hidden as if \textbf{encapsulated} within the object.
Direct access to the data is restricted, instead we use methods to get, set, \& manipulate data.
Manipulation of data is hidden.
The object caller doesn't need to know what's actually going on behind the scenes.
We can be (fairly) sure that nobody else is fiddling with our data.
\subsubsection{Abstraction}
Functionality can be defined without actually being implemented.
High-level interfaces provide method types/names without implementation.
This allows case-specific implementation, allows one person to define the functionality \& another to implement, and
allows the representation to be changed without affecting ``public'' view of the class.
This is helpful when designing large systems.
\subsubsection{Inheritance}
Classes can \textbf{inherit} functionality without re-implementing.
This prevents the duplication of code.
This is also helpful when designing large systems; it encourages a well-structured codebase.
\subsubsection{Polymorphism}
Objects of one class can be treated like objects of other classes.
\section{Imperative \& Procedural Programming}
\subsection{Imperative Programming}
\textbf{Imperative programming} involves telling the computer to perform a set of actions, one after the other.
Most programming languages have imperative aspects.
Imperative programming consists of a list of instructions, \verb|GOTO| statements, and little or no structure.
E.g., Assembly.
\subsection{Procedural Progamming}
\textbf{Procedural progamming} splits actions into \textbf{procedures} or tasks.
Procedures can be made up of other procedures (composition, recursion).
The code is structured, uses ``functions'' or procedures, encourages code re-use, and encourages encapsulation \&
composition.
Note that procedural functions are not to be confused with Functional Programming.
\subsubsection{Structured Programming}
Examples of structured programming languages include basically everything except Assembly.
\begin{itemize}
\item Code is structured.
\item \verb|while|, \verb|for|, \verb|if|, \verb|else,| \verb|switch|, \verb|class|, \verb|function|, etc.
\item Less emphasis on \verb|GOTO| statements.
\item Creating a structure to manage instructions.
\item Allows more complex programs to be built.
\item Easier to understand.
\item Helps to avoid \verb|GOTO| bugs \& spaghetti code.
\end{itemize}
\subsection{The C Programming Language}
\textbf{C} is a procedural, imperative, structured ``systems language''.
It came into being around 1969-1973 in parallel with the development of the UNIX operating system.
Basic Compiled Programming Language (BCPL) \rightarrow B \rightarrow C...
C has had an ANSI standard since the 1980s.
Now one of the most popular \& powerful languages in use today.
\begin{code}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
// header inclusion: functionally defined in stdio.h is added into the program by the compiler, specifically the Linker step of the compiler
// "stdio" is short for "Standard Input / Output"
#include <stdio.h>
// function prototype: tells the compiler that the function exists before it has been implemented
// allows the compiler to handle recursion, or functions calling each other
void sayHello();
// function definition: implements the function
// note: data type, arguments, return
void sayHello() {
// calling a function: printf takes a char* argument
printf("Hello World!\n");
}
// main function: the entry point to the progam
// returns int
// takes two arguments: argc (the number of command-line arguments) & argv (an array of the arguments)
int main(int argc, char* argv[]) {
// calling a function: sayhello takes no argument. nothing is returned
sayHello();
return 0;
}
\end{minted}
\caption{Example C Program: \texttt{helloWorld.c}}
\end{code}
\begin{code}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
#include <stdio.h>
int add(int a, int b);
int add(int a, int b) {
return a+b;
}
int main(int argc, char* argv[]) {
printf("Let's add some numbers...\n");
int first = 8;
int second = 4;
printf("The first number is %d\n", first);
printf("The second number is %d\n", second);
// "add" is a function that returns an int
// the returned int is stored in the "result" variable - they must have the same data type
int result = add(first, second);
// "%d" is for ints - strictly decimal ints
// "%i" is any int including octal and hexadecimal
printf("When we add them together we get: %d\n", result);
return 0;
}
\end{minted}
\caption{Example C Program: \texttt{addNumbers.c}}
\end{code}
\subsubsection{Pointers}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
int* p; // variable p is a pointer to an integer value
int i; // integer value
\end{minted}
You can \textbf{dereference} a pointer into a value with \verb|*|.
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
// ineger i2 is assigned the integer value that the pointer p is pointing to
int i2 = *p;
\end{minted}
You can get a pointer to a value with \verb|&|.
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
// pointer p2 points to the address of integer i
int* p2 = &i;
\end{minted}
A function effectively breaking the convention that arguments are not changed in a function is a \textbf{side effect}.
This is done by passing addresses.
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
#include<stdio.h>
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main(int argc, char* arv[]) {
int a = 8;
int b = 4;
swap(&a, &b); // this should make a=4 & b=8
}
\end{minted}
\subsubsection{Arrays \& Pointers}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
int intArr[5]; // an integer array of size 5
// intArr is a pointer to the 0th element of the array - the same as &intArr[0]
intArr[2] = 3; // same as *(intArr+2) = 3;
// (intArr + 2) is of type (int*) while intArr[2] is of type int
// in the latter case, the pointer is dereferenced
// (intArr + 2) is the same as (&(intArr[2]))
// note that the + operator here is not simple addition - it moves the pointer by the size of the type
\end{minted}
\subsubsection{Generic Swap function?}
What about a swap function that works on any data type?
\begin{code}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
void swap(void* x, void* y) {
void temp = *x; // won't work!
// we don't know what size data *x points to, so void temp can't work
// it is impossible to have a variable of type void for this reason
// but we can have a pointer of type void*
*x = *y;
*y = temp;
}
\end{minted}
\caption{(Non-functional) Attempt at a Generic \texttt{swap} Function}
\end{code}
\mintinline{c}{void*} is a specific pointer type which points to some location in memory.
It has no specific type and therefore no specific size.
\\\\
\mintinline{c}{sizeof(<type>)} returns the size in bytes of the object representation of \verb|<type>|.
\verb|sizeof()| is built-in to the C langauge.
\\\\
\mintinline{c}{void* memcpy(void* to, const void* from, size_t size)}.
The \verb|memcpy()| function copies \verb|size| number of bytes from the object beginning at location \verb|from| into
the object beginning at location \verb|to|.
The value returned by \verb|memcpy()| is the value of \verb|to|.
The \verb|memcpy()| function is defined in \verb|string.h|.
\begin{code}
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
#include <string.h>
void generic_swap(void* vp1, void* vp2, int size) {
char temp_buff[size]; // need malloc?
memcpy(temp_buff, vp1, size);
memcpy(vp1, vp2, size);
memcpy(vp2, temp_buff, size);
}
\end{minted}
\caption{Generic Swap Function}
\end{code}
\subsection{Stacks vs Heaps}
A \textbf{stack} is a LIFO data structure of limited size \& limited access.
It supports only two operations: PUSH \& POP.
Stacks are very fast.
The limited size of stacks can result in stack overflow, and you cannot free memory in a stack except by POPping.
To continue the \verb|swap()| function from above:
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
// first, a, b, & c are pushed onto the stack
char a = 'a';
int b = 100;
int c = 50;
// when swap() is called, x, y, & temp are pushed onto the stack
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
// when swap returns, x, y, & temp are popped from the stack and \textbf{their memory is no longer in use}
}
swap(b, c);
\end{minted}
But what if we want to keep track of \verb|temp| and use it later?
\\\\
A \textbf{heap} is an unordered data structure of (theoretically) unlimited size and global access.
The heap operations are allocate \& free.
Heaps are slower than stacks.
Heaps are also harder to manage than stacks as they can get memory leaks.
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{c}
// first, b & c are pushed onto the stack
int b = 100;
int c = 50;
// when swap() is called, x, y, & temp are pushed onto the stack
void* swap(int* x, int* y) {
int temp = *x;
// we allocate space in memory to perm using malloc
int* perm = malloc(int);
perm = &temp;
x = y;
y = *perm;
// when swap returns, x, y, & temp are popped from the stack
// the memory allocated to perm is still in use
return perm;
}
void* p = swap(b, c);
free(p);
\end{minted}
Why not just return \verb|temp| in the same way?
\begin{itemize}
\item Even when this function terminates, another function can access perm using that pointer.
\item If we need to store a large or undeterminable amount of data, we can safely use the heap as there is no risk
of stack overflow and no risk of losing reference or accidental de-allocation of memory.
\end{itemize}
\section{Dynamic Memory}
FINISH OFF
\section{Functional Programming}
Given the same problem to solve, a program for said problem in any programming language can be considered
equivalent to any other at the machine level in that the programs will result in changes to values contained in
memory cells.
However, there can be quite significant differences at both the conceptual \& implementation level.
\subsection{Lisp, Racket, \& Scheme}
\textbf{LISP} (more commonly referred to as \textbf{Lisp}) is a contraction of \textbf{List Processing}.
\textbf{Scheme} is a dialect of Lisp, and \textbf{Racket} is an implementation of Scheme.
Lisp uses prefix (Polish) notation, e.g.: \verb|(+ 3 4)|, \verb|(* 5 6)|, \verb|(- 4 (* 5 6))|, etc.
\subsubsection{Function vs Literal}
Parentheses are used to represent a \textbf{function}:
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{lisp}
(+ 3 4) ; = 7
(* 5 6) ; = 30
(- 4 (* 5 6)) ; = -26
\end{minted}
A single quote is used to represent a \textbf{literal}:
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{lisp}
(+ 3 4) ; = 7
'(+ 3 4) ; = '(+ 3 4)
\end{minted}
Rather than considering \verb|+| as the name of a function, the quote means to take everything literally, i.e.
``\verb|+|'' is just a word.
Nothing is evaluated.
\subsubsection{S-Expressions}
Both code \& data are structured as nested lists in Lisp.
\textbf{Symbolic Expressions} or s-expressions, sexprs, or sexps are a notation for nested list structures.
They are defined with a very simple recursive grammar, but produce a very flexible framework for computing.
An s-expression is defined as:
\begin{enumerate}
\item An \textbf{atom}.
Atoms are considered to be ``indivisible''.
Primitive data types like numbers, strings, booleans, etc. are atoms.
Lists \& pairs (s-expressions) are not.
\item An expression in the form \verb|(X . Y)|, where \verb|X| \& \verb|Y| are s-expressions.
\end{enumerate}
A \textbf{pair} is two pieces of data together.
They are created by the \verb|cons| function, which is short for ``construct'', e.g. \verb|(cons 1 2)|.
The two values joined with \verb|cons| are printed between parentheses interspaced by a \verb|.| (a period):
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (cons "banana" "split")
'("banana" . "split")'
\end{minted}
\subsection{Lists}
A \textbf{list} is an ordered group of data.
List elements are separated by a space.
The list syntax is a shorthand for an s-expression.
Lists are displayed between parentheses using the \verb|'| (single quote character).
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
'(1 2 3) ; list of numbers
'("this" "that" "the other") ; list of strings
'(1 2 "three" 4) ; list of mixed data types
\end{minted}
Lisp uses nested lists (which are essentially linked lists).
We can access the first element of a list using the \verb|car| function:
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (car '(1 2 3))
1
\end{minted}
We can access the rest of the list using the \verb|cdr| function:
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (cdr '(1 2 3))
'(2 3)
\end{minted}
\verb|cdr| is analogous to \verb|element->rest| in our C linked list.
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (car (cdr '(1 2 3)))
2
\end{minted}
There is a shorthand for a combination of \verb|car|s \& \verb|cdr|s (up to 4 operations usually but it depends
on the Scheme environment), where \verb|*| is \verb|a| or \verb|d| or a combination (if supported).
For example, write a sequence of \verb|car|s \& \verb|cdr|s to extract: ``\verb|d|'' from list
\verb|(a b c d e f)| named \verb|lis|:
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{lisp}
;;;; these two are equivalent
(car (cdr (cdr (cdr lis))))
cadddr(lis)
\end{minted}
Lists are really just \verb|cons| pairs where these second element is another list or \verb|empty|;
\verb|empty| is a special word, similar to \verb|NULL| in other languages.
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (cons 2 empty)
'(2)
> (cons 1 (cons 2 empty))
'(1 2)
\end{minted}
The built-in functions \verb|list| \& \verb|append| provide a more convenient way to create lists.
\subsubsection{\texttt{define}}
\textbf{\texttt{define}} binds a variable to some data.
Its format is \mintinline{lisp}{(define variable value)}.
\verb|define| is used for user-defined functions.
Note that user-defined functions can be used within other use defined functions as long as the functions are
defined before they are invoked.
\begin{minted}[texcl, mathescape, linenos, breaklines, frame=single]{lisp}
(define (function_name parameter-list)
Function-body
)
;;; calculates the absolute addition of two numbers where the function abs returns the absolute value of a number
(define (sumabs num1 num2)
(+ (abs num1) (abs num2))
)
\end{minted}
\begin{minted}[texcl, mathescape, breaklines, frame=single]{lisp}
> (sumabs 2 -3)
5
\end{minted}
\subsubsection{\texttt{list} \& \texttt{append}}
The \verb|list| function constructs a list from components.
It takes the form \mintinline{lisp}{(list el-1 el-2 el-n)}.
These components can be symbols, numbers, or lists.
\\\\
\verb|append| collects components from several lists into one list.
Its arguments must be lists.
\verb|append| takes the form \mintinline{lisp}{(append list1 list2 listn)}.
\end{document}