Title: Chapter 15 Functional Programming Languages
1Chapter 15Functional Programming Languages
- CS 350 Programming Language Design
- Indiana University Purdue University Fort Wayne
2Chapter 15 topics
- Introduction
- Mathematical functions
- Fundamentals of functional programming languages
- The first functional programming language LISP
- Introduction to Scheme
- Other functional programming languages
- Applications of functional languages
- Comparison of functional and imperative languages
3Introduction
- The imperative language paradigm is based
directly on the von Neumann architecture - Efficiency is the primary concern, rather than
the suitability of the language for software
development - The functional language paradigm is based on
mathematical functions - This puts functional languages on a solid
theoretical basis that is closer to the user - The architecture of the machines on which
programs will run is largely ignored
4Introduction
- A mathematical function is a mapping of members
of one set, called the domain set, to another
set, called the range set - Although functional languages have acquired
imperative features for execution efficiency, we
will focus on the core functional features
embodied in the Scheme language - Scheme is a small, statically scoped dialect of
LISP
5Mathematical functions . . .
- define a value, instead of specifying a sequence
of operations on variables that produce the value - do not have state
- Local variables in imperative languages maintain
the state of methods during execution - There is no such thing as local variables in
mathematical functions - have evaluation order controlled only by
recursion and conditional expressions - Imperative programming languages also rely on . .
. - sequences of instructions
- iteration
- have no side effects
- Side effects are connected to variables that
model memory locations
6Mathematical functions
- Usually, a mathematical function is expressed
with a name, a list of parameters, and an
expression giving the mapping - Examples
- Given a domain element like 7, the range element
is obtained by substituting into the mapping
expression - No unbound parameters
1 if n 0 f(
n ) n f( n 1 ) if n gt 0
p( x ) 3xx - 5x 17
A polynomial function
The factorial function
7Mathematical functions
- A lambda expression allows the name of the
function to be separated from the function
definition - The result is a nameless function that is
specified only with parameters and the mapping
expression - The function is specified by
the following lambda expression - During evaluation at domain value 3, the
parameter x is bound to 3
cube( x ) xxx
?(x) x x x
( ?(x) x x x )(3) results in range value 27
8Mathematical functions
- A functional form (or higher-order function) is
one that either takes functions as parameters or
yields a function as its result, or both - We consider
- Functional composition
- Function construction
- Apply-to-all
9Function composition
- Functional composition
- Takes two functions as parameters
- Yields a function whose value is the result of
applying the first function to the result of
applying the second function to domain value - The composition of functions f and g yields
function h - Functional composition is written using the
operator - The notation h ? f g means h( x ) ? f ( g ( x )
) - For f(x) ? x x x and g(x) ? x 3, function
h is given by - h( x ) ? (x 3) (x 3) (x 3)
10Function construction
- Function construction is a functional form that
takes a list of functions as parameters and
yields a list of the results obtained by applying
each of the functions to a given domain value - Functional composition is written using brackets
as in f, g - For f(x) ? x x x and g(x) ? x 3,
- f, g (3) yields the list (27, 6)
11Apply-to-all
- Apply-to-all is a functional form that takes a
single function as a parameter and applies the
given function to a list of domain values to
obtain a list of corresponding range values - Apply-to-all is denoted by ?
- For h( x ) ? x x x,
- ?( h, (3, 2, 4) ) yields (27, 8, 64)
12Fundamentals of functional programming languages
(FPLs)
- The objective of the design of a FPL is to mimic
mathematical functions to the greatest extent
possible - The basic process of computation is fundamentally
different in a FPL than in an imperative language - In an imperative language, operations are done
and the results are stored in variables for later
use - Management of variables is a constant concern and
source of complexity for imperative programming
13Fundamentals of FPLs
- In an FPL, variables and assignment statements
are not necessary, as is the case in mathematics - In an FPL, the evaluation of a function always
produces the same result given the same
parameters - This is called referential transparency
14Fundamentals of FPLs
- A functional language provides . . .
- A set of primitive functions
- A set of functional forms to construct complex
functions from primitive functions - An operation to apply a function to data
- Some structure or structures to represent data
15LISP
- Originally, the only LISP data object types were
only atoms and lists - Atoms are either symbols (identifiers) or numeric
literals - The form of a list is a parenthesized collection
of atoms and/or sublists - For example, (A B (C D) E)
- A simple list consists only of atoms
- LISP lists are stored internally as singly-linked
lists
16LISP
- Lambda notation is used to specify functions and
function definitions - Function applications and data have the same form
- If the list (A B C) is interpreted as data it is
a simple list of three atoms, A, B, and C - If it is interpreted as a function application,
it means that the function named A is applied to
the two parameters, B and C - This format used is called Cambridge Polish
notation - ( 7 11 ) results in 18
- ( 7 11 2 5 ) results in 25
17LISP
- An early theoretical LISP goal was to develop a
universal LISP function capable of evaluating any
other LISP function - John McCarthy at MIT developed this universal
function and called it EVAL - It was soon realized that EVAL could serve as a
LISP interpreter - An implementation of EVAL became the first
implementation of LISP
18Introduction to Scheme
- Scheme is a mid-1970s dialect of LISP
- Designed to be a cleaner, more modern, and
simpler version than the contemporary dialects of
LISP - Scheme uses only static scoping
- Functions are first-class entities
- As such, Scheme functions can be . . .
- the values of expressions
- elements of lists
- passed as parameters
- assigned to variables
- Scheme and LISP do have variables to overcome
some awkwardness
19Introduction to Scheme
- A Scheme program is a collection of function
definitions - Evaluation of one function may cause other
functions to be evaluated (as sub-functions) - The Scheme interpreter (also called EVAL) is a
read-evaluate-write loop - Prompts the user for an input expression in the
form of a list - Evaluates the expression
- Displays the resulting value
- Literals evaluate to themselves
20Introduction to Scheme
- Normal expression evaluation process
- Parameters are evaluated, in no particular order
- The values resulting from evaluation are
substituted into the function body - The function body is evaluated
- The resulting value of the last expression in the
body is returned - Special functional forms may use a different
evaluation process
21Introduction to Scheme
- Primitive numeric functions
- , -, , /, ABS, SQRT, REMAINDER, MIN, MAX
- ( - 20 ( 3 4 ) ) results in 8
- ( - 5 11 3 ) results in -9
- Numeric predicate functions
- , ltgt, lt, gt, lt, gt, EVEN?, ODD?, ZERO?
- These return Boolean values
- The Boolean values are T and F
- The empty list ( ) is interpreted as F
- Any non-empty list is interpreted as T
22Defining functions
- Lambda expressions
- Form
- ( LAMBDA ( x ) ( x x x ) )
- Application
- ( ( LAMBDA ( x ) ( x x x ) ) 3 ) results in
27 - The DEFINE function
- DEFINE is a special function for constructing
functions that has two forms - Each form takes two parameters
23DEFINE
- Form of DEFINE for binding a symbol to an
expression - ( DEFINE myPi 3.141593 )
- ( DEFINE twoPi ( 2 myPi ) )
24DEFINE
- Form of DEFINE for binding a name to a lambda
expression - ( DEFINE ( name parameters ) expr expr )
- In this case, the two parameters are
- Prototype of the function call as a list
- The lambda expression that is to be bound to the
name - Note the word LAMBDA does not appear in this
abbreviation - For example, ( DEFINE ( cube x ) ( x x x ) )
- To use cube
- (cube 3) results in 27
25Display functions
- Scheme includes the following output functions
- ( DISPLAY expression )
- ( NEWLINE )
- See example on the next slide
26Display example
- Display the hypotenuse of a right triangle
- Evaluation of the display expression outputs
( define ( square x ) ( x x ) ) ( define
( hypotenuse base height ) ( sqrt ( (
square base ) ( square height ) ) ) ) ( display
( list "The hypotenuse of a triangle with
base " 3 " and height " 4 " is " (hypotenuse 3 4
) ) )
(The hypotenuse of a triangle with base 12 and
height 5 is 13)
27Control flow in Scheme
- Control flow is modeled after mathematical
functions - The special form IF is used for 2-way selection
- The IF format is (IF predicate thenExp elseExp
) - The factorial function can be written as follows
- For readability, this can be reformatted as
( define ( factorial n ) ( if ( n 0 ) 1 (
n ( factorial ( - n 1 ) ) ) ) )
( define ( factorial n ) ( if ( n 0 )
1 ( n ( factorial ( - n
1 ) ) ) ) )
28Control flow in Scheme
- The special form COND is used for multiple
selection - The format of COND is
- (COND
- (predicate_1 expr expr)
- (predicate_2 expr expr)
- ...
- (predicate_n expr expr)
- (ELSE expr expr)
- )
29COND
- COND always returns the value of the last expr in
the first pair whose predicate evaluates to true - Example function using COND
( DEFINE (compare x y ) ( COND
( (gt x y) ( DISPLAY x is greater than y ) )
( (lt x y) ( DISPLAY y is greater than
x ) ) ( ELSE ( DISPLAY x and y are
equal ) ) ) )
30List functions
- We consider the following list processing
functions - QUOTE
- CAR
- CDR
- CONS
31QUOTE
- Function QUOTE
- Takes one parameter
- Returns the parameter without evaluation
- Recall that the Scheme interpreter always
evaluates function parameters before applying the
function - QUOTE is used to avoid parameter evaluation when
it is not appropriate - Perhaps the parameter is a list of atoms
32QUOTE
- QUOTE can be abbreviated with the apostrophe
prefix operator - For example,
- '(A B) is equivalent to (QUOTE (A B) )
- Without the QUOTE, the interpreter would
evaluate (A B) by applying the function A is to
parameter B and returning the result
33CAR
- Function CAR
- Contents of Address Register
- Takes a list parameter
- Returns the first element of that list
- For example
- (CAR '(A B C) ) returns A
- (CAR '( (A B) C D) ) returns (A B)
- (CAR A ) is an error (A is not a list)
- (CAR (A) ) returns A
- (CAR ( ) ) is an error
34CDR
- Function CDR
- Contents of Decrement Register
- Takes a list parameter
- Returns the list after removing its first element
- For example
- (CDR '(A B C) ) yields (B C)
- (CDR '( (A B) C D) ) yields (C D)
- (CDR A ) is an error
- (CDR (A) ) returns ( )
35CONS
- Function CONS
- Takes two parameters
- The first parameter can be either an atom or a
list - The second parameter is a list
- Returns a new list that includes the first
parameter as its first element and the second
parameter as the remainder of the list - For example
- (CONS 'A '(B C) ) returns (A B C)
- (CONS (A B) (C D) ) returns ( (A B) C D )
- (CONS A ( ) ) returns (A)
- (CONS ( ) (A B) ) returns ( ( ) A B )
- (CONS (CAR (A B C) ) (CDR (A B C) ) ) returns
(A B C)
36LIST
- Function LIST constructs a list from a variable
number of parameters - Takes any number of parameters
- Returns a list with the parameters as elements
- For example
- (LIST A B C D E) returns (A B C D E)
37Predicate functions for atoms and lists
- Recall T represents true and ( ) or F
represents false - Predicate function EQ?
- Takes two symbolic parameters for atoms
- Returns T if both parameters are atoms and the
two atoms are the same - For example
- (EQ? 'A 'A) returns T
- (EQ? A B) returns F or ( )
- (EQ? A '(A B) ) returns F or ( )
- (EQ? (A B) (A B) ) may return F or may
return T - The effect with list parameters depends on the
implementation - EQ? does not work for numeric atoms
- Note DrScheme does work with numeric atoms
38Predicate functions for atoms and lists
- Predicate function LIST?
- Takes one parameter
- Returns T if the parameter is a list
- Otherwise returns F
- Examples
- (LIST? (A B) ) returns T
- (LIST? A ) returns F
- (LIST? ( ) ) returns T
39Predicate functions for atoms and lists
- Predicate function NULL?
- Takes one parameter
- Returns T if the parameter is the empty list
- Otherwise returns F
- Examples
- (NULL? (A B) ) returns F
- (NULL? ( ) ) returns T
- (NULL? A) returns F
- (NULL? ( ( ) ) ) returns F
40Examples of Scheme functions
- Develop a membership function named member that
determines if a given atom is member of a given
simple list - The function . . .
- takes an atom and a simple list
- A simple list has no sublists
- returns T if the atom is in the list
- returns F otherwise
41Membership function
- Three cases must be considered
- Empty input list
- A match between the atom with the CAR of the list
- A mismatch between the atom with the CAR of the
list - Note that NULL? Must preceed EQ?
( DEFINE ( member2 atm lis ) ( COND
( ( NULL? lis ) F
) (
( EQ? atm ( CAR lis ) ) T
) ( ELSE
(member2 atm ( CDR lis )
) ) ) )
42Examples of Scheme functions
- Develop a function named equalSimple that . . .
- Takes two simple lists as parameters
- Returns T if the two simple lists are equal
- Otherwise returns F
( DEFINE ( equalsimp lis1 lis2 ) ( COND
( ( NULL? lis1 )
( NULL? lis2 )
) ( ( NULL? lis2 )
F
) ( ( EQ? (
CAR lis1 ) ( CAR lis2 ) ) ( equalsimp ( CDR
lis1 ) ( CDR lis2 ) ) ) ( ELSE
F
) ) )
43Examples of Scheme functions
- Develop a function named equal that . . .
- Takes two general lists as parameters
- Returns T if the two lists are equal
- Otherwise returns F
DEFINE ( equal lis1 lis2 ) (COND (
( NOT ( LIST? lis1 ) ) ( EQ?
lis1 lis2 ) )
( ( NOT ( LIST? lis2 ) )
F
) ( ( NULL? lis1 )
( NULL? lis2 )
) ( ( NULL? lis2 )
F
) ( ( equal (
CAR lis1 ) ( CAR lis2 ) ) (equal ( CDR lis1 ) (
CDR lis2 ) ) ) ( ELSE
F
) ) )
44Examples of Scheme functions
- Develop a function named append that . . .
- Takes two lists as parameters
- Returns the first parameter list with the
elements of the second parameter list appended at
the end
( DEFINE ( append lis1 lis2 ) ( COND
( ( NULL? lis1 ) lis2
) ( ELSE ( CONS ( CAR
lis1 ) ( append ( CDR lis1 ) lis2 ) ) ) ) )
45Examples of Scheme functions
- Develop a function named intersection that . . .
- Takes two simple lists as parameters
- Returns a simple list that contains the common
elements of the two parameters
( DEFINE ( intersection lis1 lis2 ) ( COND
( ( NULL? lis1 ) ( )
) ( ( member
( CAR lis1 ) lis2 ) ( CONS ( CAR lis1 ) (
intersection ( CDR lis1 ) lis2 ) ) ) (
ELSE (
intersection ( CDR lis1 ) lis2 )
) ) )
46Another Scheme function
- The LET function allows names to be temporarily
bound to values of subexpressions - Like defining named constants
- The names may only be used within the scope of
LET - The format of LET is . . .
- Semantics of LET
- LET first evaluates all expressions, then binds
the values to names, and finally evaluates the
body
( LET ( ( name1 expression1 ) (
name2 expression2 ) ... ( nameN
expressionN ) ) expr )
47Example using LET
- This function outputs both quadratic roots of the
quadratic equation a bx cx2 0
( DEFINE ( quadraticRoots a b c ) ( LET (
( rootPartOver2a ( / ( SQRT ( - (
b b ) ( 4 a c ) ) ) ( 2 a ) ) ) (
minus_bOver2a ( / ( - 0 b ) ( 2 a ) )
) )
( LIST ( DISPLAY (
minus_bOver2a rootPartOver2a ) )
( NEWLINE ) ( DISPLAY ( -
minus_bOver2a rootPartOver2a ) ) )
) )
48Example of a functional form
- The functional form mapcar below implements
Apply-to-All - Takes a function and and a list as parameters
- Applies the function to each item in the list
- Returns a list of the results
( DEFINE ( mapcar fun lis ) ( COND
( ( NULL? lis )
'( ) ) ( ELSE ( CONS ( fun ( CAR lis
) ) ( mapcar fun ( CDR lis ) ) ) ) ) )
49Example of a function that builds code
- Recall that the Scheme interpreter is a function
named EVAL - The Scheme system applies EVAL to any expression
typed at the Scheme prompt - It is possible in Scheme for a program to build
Scheme code and then execute that code - Scheme functions have the same structure as
Scheme data - The Scheme interpreter EVAL can be called by any
program - Therefore a Scheme program can create an
expression for a function and then call EVAL to
evaluate it
50Example of a function that builds code
- Example
- Given a list of numbers lis, create a function
that calculates and returns the sum - ( lis ) doesnt work, since works only on
numerical parameters, not on a list of numbers - Of course, recursion could be used as indicated
below
( DEFINE ( adder lis ) ( COND ( (
NULL? lis ) 0 ) ( ELSE ( ( CAR lis
) ( adder ( CDR lis ) ) ) ) ) )
51Example of a function that builds code
- But there is another way
- Build a call to with the proper parameters
- Then use EVAL to calculate the sum
- If lis is ( 1 2 3 4 ) then ( CONS ' lis ) is (
1 2 3 4 )
( DEFINE ( adder lis ) ( COND ( (
NULL? lis ) 0 ) ( ELSE ( EVAL (
CONS ' lis ) ) ) ) )
52A quick look at other FPLs
53Common LISP
- Common LISP is a combination of many of the
features of the popular dialects of LISP around
in the early 1980s - It s a large and complex language
- The opposite of Scheme
- Common LISP includes
- records
- arrays
- complex numbers
- character strings
- powerful I/O capabilities
- packages with access control
- imperative features like those of Scheme
- iterative control statements
54ML
- A static-scoped functional language with syntax
that is closer to Pascal than to LISP - Uses type declarations, but also does type
inferencing to determine the types of undeclared
variables - It is strongly typed and has no type coercions
- Scheme is essentially typeless
- Includes exception handling and a module facility
for implementing abstract data types
55ML
- Includes lists and list operations
- Lists have the form 1, 2, 3, 4, 5
- The function declaration format is . . .
- For example . . .
fun name ( formalParameters )
bodyExpression
fun cube ( x int ) x x x
56Haskell
- Haskell is similar to ML
- Syntax
- Statically scoped
- Strongly typed
- Type inferencing
- It is different from ML in that it is purely
functional - No variables
- No assignment statements
- No side effects of any kind
- This makes Haskell different from most other
functional languages
57Haskell
- Haskell example the Fibonacci function
- Most important features
- Uses lazy evaluation
- No subexpression is evaluated until the value is
needed - This allows Haskell to deal with infinite lists
- Has list comprehensions
- Allows sets to be defined using syntax similar to
mathematical notation
fib 0 1 fib 1 1 fib ( n 2 ) fib (n 1)
fib n
58Haskell
- List comprehensions examples
- Compute a list of the squares of the first 100
positive integers - A function that computes a list of all the
factors of the given integer parameter
nn n ? 1 .. 100
factors n i i ? 1 .. n div 2 , n mod i
0
59Haskell example
- The quicksort algorithm in Haskell may be written
. . . - The notation ht represents a list parameter with
CAR h and CDR t - The operator is list catenation
sort sort ( ht ) sort b b ? t, b
lt h h sort b b ? t b gt h
60Haskell lazy evaluation example
- Check if an integer is a perfect square
- First define the infinite set of squares of
positive integers (which are represented in
ascending order) - Then define a membership function member which
makes use of the ascending order - Finally see if 91 is a perfect square
squares nn n ? 1 ..
member ( ht ) n h lt n member
t n h n True
otherwise False
The indicates a guard
member squares 91
61Applications of functional languages
- APL is used for throw-away programs
- LISP is used for artificial intelligence
- Knowledge representation
- Machine learning
- Natural language processing
- Modeling of speech and vision
- Scheme is used to teach introductory programming
at a significant number of universities
62Comparing functional imperative languages
- Imperative Languages
- Efficient execution
- Complex semantics
- Complex syntax
- Concurrency is programmer designed
- Functional Languages
- Inefficient execution
- Simple semantics
- Simple syntax
- Programs can automatically be made concurrent