0% found this document useful (0 votes)
3 views

ch15-Functional Programming

The document provides an overview of functional programming languages, focusing on their mathematical foundations and differences from imperative languages. It covers key concepts such as lambda expressions, higher-order functions, and specific languages like Lisp and Scheme, detailing their syntax and functionalities. Additionally, it discusses the implications of functional programming on software development and variable management.

Uploaded by

fekeh92177
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

ch15-Functional Programming

The document provides an overview of functional programming languages, focusing on their mathematical foundations and differences from imperative languages. It covers key concepts such as lambda expressions, higher-order functions, and specific languages like Lisp and Scheme, detailing their syntax and functionalities. Additionally, it discusses the implications of functional programming on software development and variable management.

Uploaded by

fekeh92177
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 88

Functional

Programming
Languages

ISBN 0-321-49362-1
Chapter 15 Topics
• Introduction
• Mathematical Functions
• Fundamentals of Functional Programming Languages
• The First Functional Programming Language: Lisp
• Introduction to Scheme
• Haskell
• Support for Functional Programming in Primarily Imperative
Languages
• Comparison of Functional and Imperative Languages

Copyright © 2015 Pearson. All rights reserved. 1-2


Introduction

• The design of the imperative languages is based


directly on the von Neumann architecture

– Efficiency is the primary concern, rather than the


suitability of the language for software development

• The design of the functional languages is based on


mathematical functions

– A solid theoretical basis that is also closer to the user, but


relatively unconcerned with the architecture of the
machines on which programs will run

Copyright © 2015 Pearson. All rights reserved. 1-3


Fundamentals of Functional
Programming Languages
• In an imperative language, operations are done
and the results are stored in variables for later use

• Variables represent the state of the program which


changes throughout execution

• Management of variables is a constant concern and


source of complexity for imperative programming

Copyright © 2015 Pearson. All rights reserved. 1-4


Fundamentals of Functional
Programming Languages…
• 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 FPL, variables are not necessary, as is the case in


mathematics

• Referential Transparency - In an FPL, the evaluation of a


function always produces the same result given the same
parameters

Copyright © 2015 Pearson. All rights reserved. 1-5


Mathematical Functions

• A mathematical function is a mapping of members


of one set, called the domain set, to another set,
called the range set

• A lambda expression specifies the parameter(s)


and the mapping of a function in the following
form
(x) x * x * x
for the function cube(x) = x * x * x

Copyright © 2015 Pearson. All rights reserved. 1-6


Lambda Expressions…

• Lambda expressions describe nameless functions

• Lambda expressions are applied to parameter(s) by


placing the parameter(s) after the expression
e.g., ((x) x * x * x)(2))
which evaluates to 8

Copyright © 2015 Pearson. All rights reserved. 1-7


Functional Forms

• A higher-order function, or functional form, is one


that either takes functions as parameters or yields
a function as its result, or both

Copyright © 2015 Pearson. All rights reserved. 1-8


Function Composition

• A functional form that takes two functions as


parameters and yields a function whose value is
the first actual parameter function applied to the
application of the second
Form: h  f ° g
which means h (x)  f ( g ( x))
For f (x)  x + 2 and g (x)  3 * x,
h  f ° g yields (3 * x)+ 2

Copyright © 2015 Pearson. All rights reserved. 1-9


Apply-to-all

• A functional form that takes a single function as a


parameter and yields a list of values obtained by
applying the given function to each element of a
list of parameters
Form: 
For h(x)  x * x
(h, (2, 3, 4)) yields (4, 9, 16)

Copyright © 2015 Pearson. All rights reserved. 1-10


Lisp: Data Types and Structures

Lisp is the oldest and most widely used FPL


• Data object types: originally only atoms and lists

• List form: parenthesized collections of sublists


and/or atoms
e.g., (A B (C D) E)

• Originally, Lisp was a typeless language

• Lisp lists are stored internally as single-linked lists

Copyright © 2015 Pearson. All rights reserved. 1-11


Lisp Data Types and Structures…

Copyright © 2015 Pearson. All rights reserved. 1-12


Lisp Interpretation…

• Lambda notation is used to specify functions and function


definitions.
• Function applications and data have the same form.
e.g.,
- 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

• The first Lisp interpreter appeared only as a demonstration of


the universality of the computational capabilities of the notation

Copyright © 2015 Pearson. All rights reserved. 1-13


Lisp Interpretation…

• Function calls specified in prefix list form


(function_name parameter1 … parametern)
Example: (+ 1 2)
(- 10 2 3 4)

• Modified lambda notation to allow binding of functions to


names
(function_name (LAMBDA (parameter1 … parametern) expression)

Copyright © 2015 Pearson. All rights reserved. 1-14


Origins of Scheme

• A mid-1970s dialect of Lisp, designed to be a


cleaner, more modern, and simpler version than
the contemporary dialects of Lisp

• Uses only static scoping

• Functions are first-class entities


– They can be the values of expressions and elements of
lists
– They can be assigned to variables, passed as parameters,
and returned from functions

Copyright © 2015 Pearson. All rights reserved. 1-15


The Scheme…

The Scheme Interpreter


• In interactive mode, the Scheme interpreter is an
infinite read-evaluate-print loop (REPL)
– This form of interpreter is also used by Python and Ruby
• Scheme programs that are stored in files can be
loaded and interpreted.
– Expressions are interpreted by the function EVAL
– Literals evaluate to themselves (if you type a number to
the interpreter, it simply displays the number)
– Comments in Scheme are any text following a semicolon
on any line.

Copyright © 2015 Pearson. All rights reserved. 1-16


Primitive Function Evaluation…

• Expressions that are calls to primitive functions


are evaluated in the following way:
– Parameters are evaluated, in no particular order
– The values of the parameters are substituted into the
function body
– The function body is evaluated
– The value of the last expression in the body is the value
of the function

Copyright © 2015 Pearson. All rights reserved. 1-17


Primitive Functions…

• Primitive Arithmetic Functions: +, -, *, /, ABS, SQRT,


REMAINDER, MIN, MAX

e.g., (+ 5 2) yields 7
(- 10 5 2 6) yields -3
(* 2 3 5) yields 30
(/ 30 2) yields 15
(ABS -5) yields 5
(SQRT 64) yields 8
(REMAINDER 5 2) yields 1
(MIN 5 2) yields 2
(MAX 5 2) yields 5

Copyright © 2015 Pearson. All rights reserved. 1-18


LAMBDA Expressions…

• Lambda Expressions
– Form is based on  notation
e.g., (LAMBDA (x) (* x x))
x is called a bound variable

• Lambda expressions can be applied to parameters


e.g., ((LAMBDA (x) (* x x)) 7)

• LAMBDA expressions can have any number of parameters


(LAMBDA (a b x) (+ (* a x x) (* b x)))

Copyright © 2015 Pearson. All rights reserved. 1-19


Special Form Function: DEFINE
• DEFINE - Two forms:
1. To bind a symbol to an expression

(DEFINE symbol expression)

e.g., (DEFINE pi 3.141593)


Example use: (DEFINE two_pi (* 2 pi))
These symbols are not variables – they are like the names
bound by Java’s final declarations

Copyright © 2015 Pearson. All rights reserved. 1-20


Special Form Function: DEFINE
• DEFINE - Two forms:

2. To bind names to lambda expressions (LAMBDA is


implicit)

(DEFINE (function_name parameters) (expression))

e.g., (DEFINE (square x) (* x x))


equivalent to
(DEFINE square (LAMBDA (x) (* x x)))
Example use: (square 5)

Copyright © 2015 Pearson. All rights reserved. 1-21


Output Functions

• Usually not needed, because the interpreter always


displays the result of a function evaluated at the
top level (not nested)

• Scheme has PRINTF, which is similar to the printf


function of C

• Note: explicit input and output are not part of the


pure functional programming model, because
input operations change the state of the program
and output operations are side effects

Copyright © 2015 Pearson. All rights reserved. 1-22


Numeric Predicate Functions

• #T (or #t) is true and #F (or #f) is false (sometimes


() is used for false)

• =, <>, >, <, >=, <=


Example: (> 5 4)
• EVEN?, ODD?, ZERO?, NEGATIVE?
Example: (zero? (remainder 6 2))
• The NOT function inverts the logic of a Boolean
expression
Example: (not (zero? (remainder 6 2)))

Copyright © 2015 Pearson. All rights reserved. 1-23


Control Flow
• Selection- the special form, IF
(IF predicate then_exp)
(IF (<> count 0)
(/ sum count)
)
(IF predicate then_exp else_exp)
Example: factorial function
(define (fact n)
(if (= n 1) 1
(* n (fact (- n 1))))
)
(fact 5)

Copyright © 2015 Pearson. All rights reserved. 1-24


Control Flow…
• Multiple selection of Scheme: The COND function:

( COND
(predicate_1 clause_1)
(predicate_2 clause_2)

(predicate_n clause_n)
(else clause_else))

Copyright © 2015 Pearson. All rights reserved. 1-25


Control Flow…
• Example (The COND function):

(DEFINE (leap? year)


(COND
((ZERO? (MODULO year 400)) #T)
((ZERO? (MODULO year 100)) #F)
(ELSE (ZERO? (MODULO year 4)))
))

Copyright © 2015 Pearson. All rights reserved. 1-26


List Functions
• QUOTE - takes one parameter; returns the
parameter without evaluation
– QUOTE is required because the Scheme interpreter,
named EVAL, always evaluates parameters to function
applications before applying the function. QUOTE is
used to avoid parameter evaluation when it is not
appropriate

– QUOTE can be abbreviated with the apostrophe prefix


operator
'(A B) is equivalent to (QUOTE (A B))

• Recall that CAR, CDR, and CONS were covered in


Chapter 6

Copyright © 2015 Pearson. All rights reserved. 1-27


List Functions (continued)

• Examples:
(CAR ′((A B) C D)) returns (A B)
(CAR ′A) is an error
(CDR ′((A B) C D)) returns (C D)
(CDR ′A) is an error
(CDR ′(A)) returns ()
(CONS ′A ′(B C)) returns (A B C)
(CONS ′() ′(A B)) returns (() A B)
(CONS ′(A B) ′(C D)) returns ((A B) C D)
(CONS ′A ′B) returns (A . B) (a dotted pair - a cell
has two atoms)
Copyright © 2015 Pearson. All rights reserved. 1-28
List Functions (continued)

• LIST is a function for building a list from any


number of parameters
(LIST ′apple ′orange ′grape) returns

(apple orange grape)

Copyright © 2015 Pearson. All rights reserved. 1-29


Predicate Function: EQ?

• EQ? takes two expressions as parameters (usually


two atoms); it returns #T if both parameters have
the same pointer value; otherwise #F
(EQ? 'A 'A) yields #T
(EQ? 'A 'B) yields #F
(EQ? 'A '(A B)) yields #F
(EQ? '(A B) '(A B)) yields #T or #F
(EQ? 3.4 (+ 3 0.4))) yields #T or #F

Copyright © 2015 Pearson. All rights reserved. 1-30


Predicate Function: EQV?

• EQV? is like EQ?, except that it works for both


symbolic and numeric atoms; it is a value
comparison, not a pointer comparison
(EQV? 3 3) yields #T
(EQV? 'A 3) yields #F
(EQV 3.4 (+ 3 0.4)) yields #T
(EQV? 3.0 3) yields #F (floats and integers are
different)

Copyright © 2015 Pearson. All rights reserved. 1-31


Predicate Functions: LIST? and NULL?

• LIST? takes one parameter; it returns #T if the


parameter is a list; otherwise #F
(LIST? '()) yields #T

• NULL? takes one parameter; it returns #T if the


parameter is the empty list; otherwise #F
(NULL? '(())) yields #F

Copyright © 2015 Pearson. All rights reserved. 1-32


Example Scheme Function: member

• member takes an atom and a simple list;


returns #T if the atom is in the list; #F
otherwise

(define (member atm a_list)


(cond
((null? a_list) #F)
((eq? atm (CAR a_list)) #T)
((else (member atm (CDR a_list)))
))

Copyright © 2015 Pearson. All rights reserved. 1-33


Example Scheme Function: equalsimp

• equalsimp takes two simple lists as parameters;


returns #T if the two simple lists are equal; #F
otherwise

(DEFINE (equalsimp list1 list2)


(COND
((NULL? list1) (NULL? list2))
((NULL? list2) #F)
((EQ? (CAR list1) (CAR list2))
(equalsimp(CDR list1)(CDR list2)))
(ELSE #F)
))
Copyright © 2015 Pearson. All rights reserved. 1-34
Example Scheme Function: equal
• equal takes two general lists as parameters;
returns #T if the two lists are equal; #F otherwise
(DEFINE (equal list1 list2)
(COND
((NOT (LIST? list1))(EQ? list1 list2))
((NOT (LIST? list2)) #F)
((NULL? list1) (NULL? list2))
((NULL? list2) #F)
((equal (CAR list1) (CAR list2))
(equal (CDR list1) (CDR list2)))
(ELSE #F)
))

Copyright © 2015 Pearson. All rights reserved. 1-35


Example Scheme Function: append

• append takes two lists as parameters; returns the


first parameter list with the elements of the second
parameter list appended at the end

(DEFINE (append list1 list2)


(COND
((NULL? list1) list2)
(ELSE (CONS (CAR list1)
(append (CDR list1) list2)))
))

Copyright © 2015 Pearson. All rights reserved. 1-36


What does the following function
do?
(DEFINE (guess list1 list2)
(COND
((NULL? list1) '())
((member (CAR list1) list2)
(CONS (CAR list1) (guess (CDR list1)
list2)))
(ELSE (guess (CDR list1) list2))
))

Copyright © 2015 Pearson. All rights reserved. 1-37


Example Scheme Function: LET

• Recall that LET was discussed in Chapter 5


– LET is a function that creates a local scope in which names
are temporarily bound to the values of expressions.
(LET binds body)
[binds] -> ((p1 v1)(p2 v2)…(pn vn))

• LET is actually shorthand for a LAMBDA expression


applied to a parameter
(LET ((alpha 7))(* 5 alpha))
is the same as:
((LAMBDA (alpha) (* 5 alpha)) 7)

Copyright © 2015 Pearson. All rights reserved. 1-38


LET Example

(DEFINE (quadratic_roots a b c)
(LET (
(root_part_over_2a
(/ (SQRT (- (* b b) (* 4 a c)))(* 2 a)))
(minus_b_over_2a (/ (- 0 b) (* 2 a)))
(LIST (+ minus_b_over_2a root_part_over_2a))
(- minus_b_over_2a root_part_over_2a))
))

Copyright © 2015 Pearson. All rights reserved. 1-39


Tail Recursion in Scheme
• Definition: A function is tail recursive if its
recursive call is the last operation in the function
define (member atm a_list)
(cond
((null? a_list) #F)
((eq? atm (CAR a_list)) #T)
((else (member atm (CDR a_list)))
))
• A tail recursive function can be automatically
converted by a compiler to use iteration, making it
faster
• Scheme language definition requires that Scheme
language systems convert all tail recursive
functions to use iteration
Copyright © 2015 Pearson. All rights reserved. 1-40
Tail Recursion in Scheme - continued

• Example of rewriting a function to make it


tail recursive, using helper a function

Original: (DEFINE (factorial n)


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

Copyright © 2015 Pearson. All rights reserved. 1-41


Tail Recursion in Scheme - continued

• Example of rewriting a function to make it


tail recursive, using helper a function

Tail recursive:
(DEFINE (facthelper n factpartial)
(IF (<= n 0)
factpartial
(facthelper(- n 1) (* n factpartial)))
))
(DEFINE (factorial n)
(facthelper n 1))

Copyright © 2015 Pearson. All rights reserved. 1-42


What does the following function
do?
(define (guess ls)
(if (null? ls) '()
(guessh (car ls) (cdr ls))
)
)

(define (guessh cm ls)


(cond
((null? ls) cm)
((> cm (car ls)) (guessh cm (cdr ls)))
(else (guessh (car ls) (cdr ls)))
)
)

Copyright © 2015 Pearson. All rights reserved. 1-43


Functional Form - Composition

• Composition
– If h is the composition of f and g, h(x) = f(g(x))
(DEFINE (g x) (* 3 x))
(DEFINE (f x) (+ 2 x))
(DEFINE h x) (+ 2 (* 3 x))) (The composition)

Copyright © 2015 Pearson. All rights reserved. 1-44


Functional Form – Composition…

– In Scheme, the functional composition function compose


can be written:
(DEFINE (compose f g) (LAMBDA (x) (f (g x))))

Examples:
((compose CAR CDR) '((a b) c d)) yields c [ CADR]

((compose CDR CAR) '((a b) c d)) yields b [ CDAR]

(DEFINE (third a_list)


((compose CAR (compose CDR CDR)) a_list))
[is equivalent to CADDR]

Copyright © 2015 Pearson. All rights reserved. 1-45


(map null? '(3 () () 5)) => (() T T ())

Functional Form – Apply-to-All

• Apply to All - one form in Scheme is map


– Applies the given function to all elements of the given list;
(DEFINE (map fun a_list)
(COND
((NULL? a_list) '())
(ELSE (CONS (fun (CAR a_list))
(map fun (CDR a_list))))
))
• Map is a built in Scheme function that takes a function and a
list as an argument, and returns the list that results by
applying that function to every element of the list.
• Ex 1: (map null? '(3 () () 5)) => (() T T ())
• Ex 2: (map (LAMBDA (num) (* num num num)) '(3 4 2 6))
yields (27 64 8 216)
Copyright © 2015 Pearson. All rights reserved. 1-46
Functions That Build Code

• It is possible in Scheme to define a function that


builds Scheme code and requests its interpretation

• This is possible because the interpreter is a user-


available function, EVAL

Copyright © 2015 Pearson. All rights reserved. 1-47


Adding a List of Numbers

(DEFINE (adder a_list)


(COND
((NULL? a_list) 0)
(ELSE (EVAL (CONS '+ a_list)))
))

• The parameter is a list of numbers to be added;


adder inserts a + operator and evaluates the
resulting list
– Use CONS to insert the atom + into the list of numbers.
– Be sure that + is quoted to prevent evaluation
– Submit the new list to EVAL for evaluation

Copyright © 2015 Pearson. All rights reserved.


1-48
Question #1

• What best distinguishes a purely functional programming


language from an imperative one?

a) There are no variables and hence no assignment operation in a


purely functional language.

b) A purely functional language lacks the “go to” statement, but an


imperative language always has such a command.

c) All subprograms must be declared with the keyword function in a


purely functional language.

d) There is no real difference, only a difference in the recommended


coding style.

Copyright © 2015 Pearson. All rights reserved. 1-49


Question #2

• Below are given s-expressions we would like to construct.


Write the simplest expression using only cons function.
Eg. (a) => (cons ‘a ‘())

1) (a b)
2) ((a))
3) (a ((b) c))

Copyright © 2015 Pearson. All rights reserved. 1-50


Question #3

• Below are given s-expressions we would like to construct.


Write the simplest expression using only cons function.
Eg. (a) => (cons ‘a ‘())

1) (a b) => (cons 'a (cons 'b '()))


2) ((a)) => (cons (cons 'a '()) '())
3) (a ((b) c)) => (cons 'a (cons (cons (cons 'b '()) (cons 'c '())) '()))

Copyright © 2015 Pearson. All rights reserved. 1-51


Question #4

• Below are given s-expressions we would like to construct.


Write the simplest expression using only list function. Do not
use quoted list (like ‘(a b))
Eg. (a) => (cons ‘a ‘())

1) (a b)
2) ((a))
3) (a ((b) c))

Copyright © 2015 Pearson. All rights reserved. 1-52


Question #4

• Below are given s-expressions we would like to construct.


Write the simplest expression using only list function. Do not
use quoted list (like ‘(a b))
Eg. (a) => (cons ‘a ‘())

1) (a b) => (list 'a 'b)


2) ((a)) => (list (list 'a))
3) (a ((b) c)) => (list 'a (list (list 'b) 'c))

Copyright © 2015 Pearson. All rights reserved. 1-53


Question #5

• Given the following s-expressions write an expression that


when evaluated returns the atom x. Use only cdr and car
functions and a single instance of variable s.
• Eg: (define s ‘(x)) => (car s)

1) (a b x)
2) (((x)))
3) (a (b (c x)))
4) (a (b (c)) x)

Copyright © 2015 Pearson. All rights reserved. 1-54


Question #5

• Given the following s-expressions write an expression that


when evaluated returns the atom x. Use only cdr and car
functions and a single instance of variable s.
• Ex: (define s ‘(x)) => (car s)

1) (a b x) => (car (cdr (cdr s)))


2) (((x))) => (car (car (car s)))
3) (a (b (c x))) => (car(cdr(car(cdr(car(cdr s))))))
4) (a (b (c)) x) => (car(cdr(cdr s)))

Copyright © 2015 Pearson. All rights reserved. 1-55


Question #6

• Write a recursive Scheme function countAtoms that


takes a list and returns the number on non-nil
atoms in the list
Eg. (countAtoms ‘((a b)((c)) (((e))) e)) => 5

Copyright © 2015 Pearson. All rights reserved. 1-56


Question #6

• Write a recursive Scheme function countAtoms that


takes a list and returns the number on non-nil
atoms in the list

(define (countAtoms ls)


( cond ((not (list? ls)) 1)
((null? ls) 0)
(else (+ (countAtoms (car ls))
(countAtoms (cdr ls)) ))
))

Copyright © 2015 Pearson. All rights reserved. 1-57


Question #7

• What is tail recursion?

• Why it is important to define functions that use


recursion to specify repetition to be tail recursive?

Copyright © 2015 Pearson. All rights reserved. 1-58


Question #8

• The code below is a simple way to compute the


length of a proper list in scheme:
(define (length ls)
(if (null? ls) 0
(+ 1 (length (cdr ls)))
) )

Write a tail-recursive version using the following


template

(define (length l) (length-tr ... ))


(define (length-tr ... ) ... )

Copyright © 2015 Pearson. All rights reserved. 1-59


Question #8

(define (length ls) (length_tr ls 0))

(define (length_tr ls n)
( if (null? ls) n
(length_tr (cdr ls) (+ 1 n))
))

Copyright © 2015 Pearson. All rights reserved. 1-60


Question #9

We wanted to write a function named third that


returns the third element of a list using functional
composition of CAR and CDR:

Copyright © 2015 Pearson. All rights reserved. 1-61


Question #9

We wanted to write a function named third that


returns the third element of a list using functional
composition of CAR and CDR:

(DEFINE (third a_list)


((compose CAR (compose CDR CDR)) a_list))

Copyright © 2015 Pearson. All rights reserved. 1-62


Question #10

We wanted to map the double function as defined


below,
(define (double x) (* 2 x))

What will be the output of following?


(map double '(3 4 5))

Copyright © 2015 Pearson. All rights reserved. 1-63


Question #10

We wanted to map the double function as defined


below,
(define (double x) (* 2 x))

What will be the output of following?


(map double '(3 4 5)) => (6 8 10)

Copyright © 2015 Pearson. All rights reserved. 1-64


Haskell

• The most popular purely functional, lazy programming


language
– A program is a collection of mathematical functions

• Pure - All variables refer to immutable, persistent values


– New values can be created, existing ones cannot be modified
– No side effects

• Lazy – Expressions are evaluated by need

• Static scoped, strongly typed, type inferencing, pattern


matching

Copyright © 2015 Pearson. All rights reserved. 1-65


Predefined Types in Haskell

Copyright © 2015 Pearson. All rights reserved. 1-66


Haskell Functions

• May have no arguments, or one or more


arguments
• Each function has single result
• Two parts:
– Function declaration – name and input output types
• Eg. increment:: Int->Int
• Eg. and1 :: Bool -> Bool -> Bool

– Function definition
• Eg. increment x=x+1
• Eg. and1 a b = if a == b then a else False

Copyright © 2015 Pearson. All rights reserved. 1-67


Haskell Examples

• Pattern matching is used on the parameters

• fact 0 = 1
fact 1 = 1
fact n = n * fact (n – 1)

• fib 0 = 1
fib 1 = 1
fib (n + 2) = fib (n + 1) + fib n

Copyright © 2015 Pearson. All rights reserved. 1-68


Factorial illustration

fact 6 ==> 6 * fact 5


==> 6 * (5 * fact 4)
==> 6 * (5 * (4 * fact 3))
==> 6 * (5 * (4 * (3 * fact 2)))
==> 6 * (5 * (4 * (3 * (2 * fact 1))))
==> 6 * (5 * (4 * (3 * (2 * (1 * fact 0)))))
==> 6 * (5 * (4 * (3 * (2 * (1 * 1)))))
==> 6 * (5 * (4 * (3 * (2 * 1))))
==> 6 * (5 * (4 * (3 * 2)))
==> 6 * (5 * (4 * 6))
==> 6 * (5 * 24)
==> 6 * 120
==> 720

Copyright © 2015 Pearson. All rights reserved. 1-69


Function Definitions with Different
Parameter Ranges
Guards can be added to lines of a function definition to specify
the circumstances under which the definition can be applied.
fact n
| n == 0 = 1
| n == 1 = 1
| n > 0 = n * fact(n – 1)

sub n
| n < 10 = 0
| n > 100 = 2
| otherwise = 1

Copyright © 2015 Pearson. All rights reserved. 1-70


Haskell Example…

• Because Haskell support polymorphism, this works for any


numeric type of x

square x = x * x

Copyright © 2015 Pearson. All rights reserved. 1-71


Roots of Quadratic Equation
Haskell includes a let construct

Copyright © 2015 Pearson. All rights reserved. 1-72


Roots of Quadratic Equation

roots2 (a,b,c)=
let e= -b/(2*a)
d= (sqrt (b*b -4*a*c))/(2*a)
in (e+d,e-d)

main= do
print(roots2 (1, 5, 6)) (-2.0, -3.0)

Copyright © 2015 Pearson. All rights reserved. 1-73


Question #1

• What is the value of the following Haskell


expression?
let x=3
y=2
z=1
in
x+y+z

Copyright © 2015 Pearson. All rights reserved. 1-74


Haskell Lists

• One- dimensional set of elements of the same


type

• [] ... empty list


• [l, 2] ... list with elements of type integer
• [True,False] ... list with elements of type Boolean
• [(1, 2), (2, 3)] ... list of tuples of Integers
• [[1, 2], [2, 3, 4]] ... list of Integer-lists

Copyright © 2015 Pearson. All rights reserved. 1-75


Haskell Lists

• List notation: Put elements in brackets


e.g., directions = ["north", "south", "east", "west"]

• Arithmetic series with the .. operator


e.g., [2, 4..10] is [2, 4, 6, 8, 10]

• Catenation is with ++
e.g., [1, 3] ++ [5, 7] results in [1, 3, 5, 7]

• CAR, CONS via the colon operator


e.g., 1:[3, 5, 7] results in [1, 3, 5, 7]

Copyright © 2015 Pearson. All rights reserved. 1-76


Haskell (continued)

• Pattern Parameters
Using : (as CAR) and pattern matching, we can define a
simple function to compute the product of a given list of
numbers

product [] = 1
product (a:x) = a * product x

– Factorial:
fact n = product [1..n]

– Length:

len [] = 0
len (a:x) = len(x) + 1

Copyright © 2015 Pearson. All rights reserved. 1-77


Haskell (continued)

• List Comprehensions
[n * n * n | n <- [1..50]]

The qualifier in this example has the form of a


generator. It could be in the form of a test

factors n = [i | i <- [1..n `div` 2], n `mod` i == 0]

The backticks (backward apostrophes) specify the


function is used as a binary operator

Copyright © 2015 Pearson. All rights reserved. 1-78


Quicksort

The set of list elements that are smaller or equal to the list head
are sorted and catenated with the head element, then the set
of elements that are greater than the list head are sorted and
catenated onto the previous result.

sort [] = []
sort (h:t) =
sort [b | b <- t, b <= h]
++ [h] ++
sort [b | b <- t, b > h]

Illustrates the concision of Haskell

Copyright © 2015 Pearson. All rights reserved. 1-79


Lazy Evaluation

• A language is strict if it requires all actual parameters to be


fully evaluated

• A language is nonstrict if it does not have the strict


requirement

• Nonstrict languages are more efficient and allow some


interesting capabilities – infinite lists

• Lazy evaluation - Only compute those values that are


necessary
– Actual parameter is evaluated only when its value is necessary to
evaluate the function

Copyright © 2015 Pearson. All rights reserved. 1-80


Lazy Evaluation…

• Positive numbers
positives = [0..]
evens=[2,4..]

• Determining if 16 is a square number (here squares is a set


and || is or operator)

member [] b = False
member(a:x) b = (a == b)||member x b

squares = [n * n | n ← [0..]]
member squares 16

Copyright © 2015 Pearson. All rights reserved. 1-81


Member Revisited

• The member function could also be written as:


member b [] = False
member b (a:x)=(a == b) || member b x

• However, this would only work if the parameter to


squares was a perfect square; if not, it will keep
generating them forever. The following version will
always work:
member2 n (m:x)
| m < n = member2 n x
| m == n = True
| otherwise = False

Copyright © 2015 Pearson. All rights reserved. 1-82


Support for Functional Programming in
Primarily Imperative Languages
• Support for functional programming is increasingly
creeping into imperative languages

– Anonymous functions (lambda expressions)


• JavaScript: leave the name out of a function definition
• Eg. var add=(x,y) => {return x+y}
console.log(add (13,56));

• C#: i => (i % 2) == 0 (returns true or false depending on


whether the parameter is even or odd)

• Python: lambda a, b : 2 * a - b

Copyright © 2015 Pearson. All rights reserved. 1-83


Support for Functional Programming in
Primarily Imperative Languages (continued)
• Python supports the higher-order functions filter and map
(often use lambda expressions as their first parameters)
map(lambda x : x ** 3, [2, 4, 6, 8])
Returns [8, 64, 216, 512]

• Python supports partial function applications


from operator import add
add5 = partial (add, 5)

(the first line imports add as a function)


Use: add5(15)
(This call returns 20.)

Copyright © 2015 Pearson. All rights reserved. 1-84


Example: Python
add=lambda x,y:x+y
11
add(6,5)

fun=lambda x,f:x+f(x)
h=lambda x: x*x 30
fun(5,h)
def map1(ls, f):
sq=[]
for x in ls:
sq.append(f(x))
return sq

map1([1,2,3,4,5,6,7], lambda x: x*x)


1,4,9,16,25,36,49
Copyright © 2015 Pearson. All rights reserved. 1-85
Support for Functional Programming in
Primarily Imperative Languages (continued)

• Ruby Blocks
– Are effectively subprograms that are sent to methods,
which makes the method a higher-order subprogram
– A block can be converted to a subprogram object with
lambda
times = lambda {|a, b| a * b}
Use: x = times.(3, 4) (sets x to 12)

– Times can be curried with


times5 = times.curry.(5)
Use: x5 = times5.(3) (sets x5 to 15)

Copyright © 2015 Pearson. All rights reserved. 1-86


Comparing Functional and Imperative
Languages
• Imperative Languages:
– Efficient execution
– Complex semantics
– Complex syntax
– Concurrency is programmer designed

• Functional Languages:
– Simple semantics
– Simple syntax
– Less efficient execution
– Programs can automatically be made concurrent

Copyright © 2015 Pearson. All rights reserved. 1-87


Imperative vs Functional PL
Functional languages have a potential advantage in
readability.
• Sum of cube function in C and Haskell
int sum_cubes(int n){
int sum=0;
for(int i=1;i<=n;i++)
sum+=i*i*i;
return sum;}

sumCubes n=sum(map (^3) [1..n])

Copyright © 2015 Pearson. All rights reserved. 1-88

You might also like