Recursion and Induction: Lexical Issues; Recursive Programming Greg - PowerPoint PPT Presentation
Recursion and Induction: Lexical Issues; Recursive Programming Greg Plaxton Theory in Programming Practice, Spring 2004 Department of Computer Science University of Texas at Austin Lexical Issues Program layout Function parameters and
Recursion and Induction: Lexical Issues; Recursive Programming Greg Plaxton Theory in Programming Practice, Spring 2004 Department of Computer Science University of Texas at Austin
Lexical Issues • Program layout • Function parameters and binding • The where clause • Pattern matching Theory in Programming Practice, Plaxton, Spring 2004
Program Layout • Unlike many programming languages, white space is significant in Haskell • Line indentation is used to delineate the scope of definitions – A definition with initial indentation k is implicitly ended before the first subsequent line with indentation at most k • For example, the following three lines represent a single definition chCase c -- change case | upper c = uplow c | otherwise = lowup c Theory in Programming Practice, Plaxton, Spring 2004
Program Layout: Example • The following (unorthodox) indentation leads to the same definition for the chCase function chCase c -- change case | upper c = uplow c | otherwise = lowup c • The following indentation leads to an error, since the last line is not considered part of the definition of chCase chCase c -- change case | upper c = uplow c | otherwise = lowup c Theory in Programming Practice, Plaxton, Spring 2004
Function Parameters and Binding • Consider the following expression, where f is a function of one argument f 1+1 • In normal mathematics, this will be an invalid expression, and if forced, you will interpret it as f(1+1) • In Haskell, this is a valid expression and it stands for (f 1)+1 Theory in Programming Practice, Plaxton, Spring 2004
Function Parameters and Binding • To apply a function to a sequence of arguments, simply write the function name followed by its arguments; no parentheses are needed unless the arguments are themselves expressions • Some examples involving a function g of two arguments – The expression g x y z stands for (g x y) z – If you write g f x y , it will be interpreted as (g f x) y , so, if you have in mind the expression g(f(x),y) , write it as g (f x) y – You can’t write g(f(x),y) , because (f(x),y) will be interpreted as a pair, which is a single item Theory in Programming Practice, Plaxton, Spring 2004
Function Parameters and Binding • Note that unary minus often requires parentheses • For example, the following expression results in an error inc -2 • It is interpreted as (inc -) 2 , which yields a type error Theory in Programming Practice, Plaxton, Spring 2004
The where Clause • The following function has three arguments, x , y and z , and it determines if x 2 + y 2 = z 2 pythagoras x y z = (x*x) + (y*y) == (z*z) • The definition would be simpler to read in the following form pythagoras x y z = sqx + sqy == sqz where sqx = x*x sqy = y*y sqz = z*z Theory in Programming Practice, Plaxton, Spring 2004
The where Clause • The following alternative also works pythagoras x y z = sq x + sq y == sq z where sq p = p*p Theory in Programming Practice, Plaxton, Spring 2004
Pattern Matching • Previously we defined function imply as follows imply p q = not p || q • We can instead use pattern matching to define it as imply False q = True imply True q = q Theory in Programming Practice, Plaxton, Spring 2004
Pattern Matching • We can also define the function imply as follows imply False False = True imply False True = True imply True False = False imply True True = True • Pattern matching can also involve certain sufficiently simple arithmetic expressions suc 0 = 1 suc (n+1) = (suc n)+1 Theory in Programming Practice, Plaxton, Spring 2004
Pattern Matching • Unfortunately, a definition such as the following is not permitted since multiplication is not allowed with the pattern count 2*t = count t count 2*t + 1 = (count t) + 1 Theory in Programming Practice, Plaxton, Spring 2004
Recursive Programming • Computing powers of 2 • Counting the 1s in a binary expansion • Multiplication via addition • Fibonacci numbers • Greatest common divisor Theory in Programming Practice, Plaxton, Spring 2004
Computing Powers of 2 • Here is the definition of a recursive function that computes nonnegative integer powers of two power2 0 = 1 power2 (n+1) = 2 * (power2 n) • What is the running time of power2 ? Theory in Programming Practice, Plaxton, Spring 2004
Counting the 1s in a Binary Expansion • Here is the definition of a recursive function that computes the number of 1’s in the binary representation of its argument, where we assume that the argument is a natural number count 0 = 0 count n | even n = count (n ‘div‘ 2) | odd n = count (n ‘div‘ 2) + 1 Theory in Programming Practice, Plaxton, Spring 2004
Multiplication via Addition • Here is a simple recursive algorithm for performing multiplication via addition mlt x 0 = 0 mlt x (y+1) = (mlt x y) + x • For what integer arguments does the above approach work? • What is the running time of mlt ? Theory in Programming Practice, Plaxton, Spring 2004
Multiplication via Addition: A Faster Approach • Consider the more general problem of computing x*y + z over three given arguments x , y , and z • The recursive function quickMlt , defined below, performs this task using only addition quickMlt x 0 z = z quickMlt x y z | even y = quickMlt (2 * x ) (y ‘div‘ 2) z | odd y = quickMlt (2 * x ) (y ‘div‘ 2) (x + z) • For what integer arguments does the above approach work? • What is the running time of quickMlt ? Theory in Programming Practice, Plaxton, Spring 2004
Fibonacci Numbers • Here is a recursive algorithm for computing the Fibonacci numbers fib 0 = 0 fib 1 = 1 fib (n + 2) = (fib n) + (fib (n+1)) • What is the running time of fib ? • We will see a faster algorithm in a later lecture Theory in Programming Practice, Plaxton, Spring 2004
Greatest Common Divisor • The greatest common divisor (gcd) of two positive integers is the largest positive integer that divides them both • Here is a recursive function corresponding to (the simple version of) Euclid’s gcd algorithm gcd m n | m == n = m | m > n = gcd (m - n) n | n > m = gcd m (n - m) Theory in Programming Practice, Plaxton, Spring 2004
Greatest Common Divisor: Efficient Version • Here is a more efficient version of Euclid’s gcd algorithm egcd m n | m == 0 = n | n == 0 = m | m == n = m | m > n = egcd (m ‘rem‘ n) n | n > m = egcd m (n ‘rem‘ m) • The running time of this algorithm is bounded by the number of bits in the input – An exponential improvement over the simple version in terms of worst-case running time Theory in Programming Practice, Plaxton, Spring 2004
Greatest Common Divisor: Binary Version • Here is a an efficient “binary version” of the gcd algorithm that requires only addition and bit shift operations – Note that ‘div‘ can be implemented using a right shift bgcd m n | m == n = m | (even m) && (even n) = 2 * (bgcd s t) | (even m) && (odd n) = bgcd s n | (odd m) && (even n) = bgcd m t | m > n = bgcd (m-n) n | n > m = bgcd m (n-m) where s = m ‘div‘ 2 t = n ‘div‘ 2 • The running time of this algorithm is bounded by the number of bits in the input Theory in Programming Practice, Plaxton, Spring 2004
Recommend
More recommend
Explore More Topics
Stay informed with curated content and fresh updates.