Functional Programming

15.1 Foundation

Based on mathematical functions, while imperative
is based moreso on the Von Neumann Architecture

John Backus formally proposed that Functional
Programming was the most efficient because of the
lack of side effects

Uses in database processing, financial modeling,
statistical analysis, and bioinformatics

15.2 Mathematical functions

Definition: Mapping of members of the domain set
to the range set. In other words, it maps the parameters
to a value(s) in a recursion style fashion

Domain/range sets can be defined explicit
or implicitly. The mapping is described by
expressions or tables. The domain set may
be the cross product of several sets

Always map an element of the domain to same element
of the range. There are no bound parameters

Application: cube(x)≡x*x*x
In this case, x cannot be changed. The final result is however
returned as the range

Nameless functions can be defined with lamda
λ(x) x * x * x
This is equivalent to the cube function, just nameless

Lamda calculus was defined by Church. It
is a formal system for function definition,
function application, and recursion. Can be
typed or untyped

Application of lambda with parameters
(λ(x) x * x * x)(2)

High-order function/functional form takes on functions
as parameters or yields a function

A common variant is function composition
h ≡ (f º g) f(x)≡x+2 and g(x)≡3*x
h ≡ f(g(x))
h ≡ (3*x) + 2

Apply-to-all is another higher-order function
It uses one function to take multiple parameters
α(h, (2, 3, 4)) where h(x) = x*x yields (4,9,16)

15.3 Fundamentals of FPLs

Main objective is to mimic mathematical functions

Avoids using variables and memory locations
(memory locations that need evaluated do not exist in pure mathematics)

Because variable are not used, iteration can not take place.
Must use recursive functions in order to iterate.

Storage of intermediate values may be necessary, but details will be hidden from the programmer.

Definition: Referential Transparency - execution of function always produces same result

FPLs Provide:

set of primitive functions

set of functional forms to construct complex functions

a function application operation

structure(s) to represent data

15.4 The First FPL: LISP

Oldest/Most widely used

Original LIP was typeless

Developed by John McCarthy

15.4.1 S=Data Types / Structures

Atom: Symbols or numeric listerals

List: List elements are pairs that include an atom and a pointer (usually linked list) to an atom, other element, or special value

15.4.2 The first LISP Interpreter

Original intent to be similar to FORTRAN with compiler to translate programs in M-notation into machine code

functions needed to be expressed as list notation

Definition: Cambridge Polish notation: prefix notation
(* X Y) -> X * Y

Functions allowed to be bound to names (not just lambda functions) in order to be referenced.

(function_name (LAMBDA ( param1, ... paramN) expression)

EVAL: a function that could evaluate other functions served as LISP interpreter

Implementation of EVAL

Other implementations copied EVAL and were also interpretive

M-notation never completed - used S-expression (or just expressions) instead

much of original language was forzen and provided odd features

() for empty set and logical false

conditional expression form

Use of dynamic scoping

15.11 Imperative vs Functional

Functional syntax is typically simpler than imperative,
as well as simpler semantics

It is claimed that functional programming produces
only 10-25% as much code needed compared to
imperative programmed counterparts

Execution speed for functional programming is twice
that of imperative programming due to language
characteristics like lazy evaluation

FPL offers a readability advantage

Pure FPL are already independent and significantly
easier to make concurrent as there is no state to
worry about, like in imperative programming

15.5 Intro to Scheme

15.5.1 Origins of Scheme

Is a dialect of LISP developed at MIT in the 70s

Characterized by small size, static scoping, and treatment of functions as first-class objects

15.5.2 The Scheme Interpreter

in interactive mode is a read-evaluate-print loop (REPL)

Interpreted by the function EVAL

Expressions that are calls to primitive functions:

First: each parameter expression is evaluated (in no particular order)

Second: primitive function applied to parameter values

Lastly: result is displayed

15.5.3 Primitive Numeric Functions

Also includes: MODULO, ROUND, MAX, MIN, LOG, SIN, SQRT
Note: Scheme is not case sensative, but some other FPLs
are

if parameter for square root is negative, will return a complex number

Scheme includes +, -, *, /

+ and * can have zero or more parameters

* with no parameters returns 1

+ with no parameters returns 0

(+ 5 7 8) -> 20
(-24 ( * 4 3)) -> 12

15.5.4 Defining Functions

Definition: Lambda Expression: a nameless function (actually includes the word LAMBDA in scheme)

Eg ((LAMBDA (x) (* x x)) 7) -> 49

Definition: Bound Variable: In this expression x is a bound variable -> x cannot change after being bound to an actual parameter value when evaluation begins

Can have multiple parameters

DEFINE keyword binds name to keyword or LAMBDA expression (analogous to declaring final variable in Java)

Used to create more imperative style, but creates named values NOT variables

Naming convention:

Not case sensative

Can have letters, digits, and special characters (except parentheses)

Cannot begin with digit

Binds LAMBDA expression to a name

(DEFINE (function_name parameters) (expression))
Ex: (DEFINE (square num) (* num num))

Ex: (DEFINE pi 3.14159)

15.5.5 Output Functions

explicit input/output not a part of the functional program model: input operations change the state and output operations have side effects

Scheme has some output operations, but when using the interpreter, usually just displayed normally through EVAL function.

15.5.6 Predicate Functions

Included functions = (equality), <> (not equal -> now use NOT with equality operator), <, >, <=, >=, EVEN? (is even?), ODD? (is odd?), ZERO? (is zero?)

All evaluate to true (#t) or false (#f or ())

Non-empty list evaluates to true

15.5.7 Control Flow

3 types

2-way selector: If - then- else

(if predicate then_expression else_expression)

N-way selector

COND keyword (conditional) -> COND <clause1> ... <clause n> [else <expression>

Ex: (cond ((> 3 3) 'greater)
((< 3 3) 'less) (else 'equal))

Recursion *More on this later*

15.5.8 List Functions

Has to evaluate parameters first in case the parameter itself is a function. When a parameter is not a function reference,
it should not be evaluated -> use QUOTE

(QUOTE A) or 'A -> returns A
This is used to ignore evaluation of a parameter
Used because data and code have the same form

CAR '(A B C) returns A -- First element of list

CAR = contents of the address of a register

CDR '(A B C) returns (B C) -- Every element except first

CDR = contents of the decrement part of a register

Can use any combination of D's and A's up to 4

Ex: (CADDAR '((A B (C) ) D) E))
=(CAR (CDR (CDR (CAR '((A B (C) D) E)))))
=(CAR (CDR (CDR '(A B (C) D))))
=(CAR (CDR '(B (C) D)))
=(CAR '((C) D))
=(C)

CONS function combines two lists (Atoms can be used too)
(CONS '(A B) '(C D)) = ((A B) C D)

LIST function can be used for shorthand nested CONS functions as it takes in variable number of parameters and produced a list.

15.5.9 Predicate functions

EQ? function compares addresses (not values)

(EQ? 'A 'A) is true

Use EQV? to compare both numeric and symbolic atoms

(EQV? 3.4 (+ 3 0.4)) -> returns #T

(EQV? 3 3.0) -> returns #F (comparing int with float, which are represented differently)

LIST function determines if list

(LIST? '(X Y)) returns true

Beware, (LIST? '()) returns true

NULL function determines if empty list

(NULL? '()) returns true.

(NULL? '(())) returns false because parameter is a list containing the empty list

15.5.11 LET

LET is a function that creates local scope in which names are temporarily bound to values of expressions
-Actually shorthand for LAMBDA
-Cannot be overwritten once created

The two expressions below are equivalent:
(LET ((alpha 7)) (* 5 alpha))
((LAMBDA (alpha) (* 5 alpha)) 7)

15.5.12 Tail Recursion

Tail recursive is when last operation in a function
is a recursive call

Not Tail Recursive:

(DEFINE (factorial n)
(IF (<= n 1)
1
(* n (factorial (- n 1)))
))

Last operation is multiplication

Tail Recursive:

(DEFINE (facthelper n factpartial)
(IF (<= n 1)
factpartial
(facthelper (- n 1) (* n factpartial))
))
(DEFINE (factorial n)
(facthelper n 1)
)

factpartial maintains the partial factorial

Because it is tail recursive, the calling activation record is no longer necessary, so this function only needs to keep track of 1 activation record.

15.5.13 Functional forms

Functional Composition

Only functional form provided by original LISP

Similar to h(x) = f(g(x))

(DEFINE (g x) (* 3 x))
(DEFINE (f x) (+ 2 x))

can both be defined as:

(DEFINE (h x) (+ 2 (* 3 x)))

(DEFINE (compose f g) (LAMBDA (x) (f (g x))))

Apply-To-All

map function applies function to each element of a given list

(map (LAMBDA (num) (* num num num)) '(3 4 2 6))

This function returns cubes of each input
Return values: (27 64 8 216)