159.331 Programming Languages - PowerPoint PPT Presentation

1 / 23
About This Presentation
Title:

159.331 Programming Languages

Description:

Many (most) imperative languages treat variables and functions ... Consider a function cond that is like the ternary operator ? : in C/C . cond b x y = x, if b ... – PowerPoint PPT presentation

Number of Views:49
Avg rating:3.0/5.0
Slides: 24
Provided by: KenHa98
Category:

less

Transcript and Presenter's Notes

Title: 159.331 Programming Languages


1
159.331 Programming Languages Algorithms
  • Lecture 18 - Functional Programming Languages -
    Part 2
  • Higher-Order Functions, Currying, Lazy
    Evaluation, Equations and Pattern Matching

2
Higher-Order Functions
  • Many (most) imperative languages treat variables
    and functions differently (non-orthogonality
    again!)
  • Variables can be manipulated (read, written,
    passed around) but functions are second-class
    citizens and can only be invoked
  • Functional languages usually treat functions as
    first-class objects, which can be passed around
    as arguments, returned as a function result or
    stored in a data structure
  • A function that takes another function as an
    argument is called a higher-order function
  • This idea is a cornerstone of functional
    programming.

3
  • An important higher-order function is map, which
    takes a function and a list as input and returns
    a new list with the function applied to each
    element
  • map triple 1,2,3,4 gt
  • triple 1, triple 2, triple 3, triple 4 gt
  • 3, 6, 9, 12
  • Note we need the capability of passing a
    function (in this case triple) as an argument
    to map
  • We could of course write a special-case function
    such as map_triple, but this has to have a name
    of its own and is no longer general - we want
    our concepts to be reuseable!
  • Having the higher-order function capability a
    language is powerful - useful if it is not the
    ugly and hard-to-remember function-pointer syntax
    that C and Coffer!

4
  • Functional languages usually offer other built
    in higher-order functions
  • Fold-right or foldr is used to compute a single
    result (eg a sum or product) from a list
  • foldr () 0 2, 4, 7 is equal to
  • ( 2 ( 4 ( 7 0 ) ) ) gt 13
  • This is Miranda syntax where if an infix
    operator like is passed as an argument it
    must be in parentheses.
  • foldr () 1 x computes the product of all
    elements in list x
  • foldr () True x computes logical and of all
    the elements in x
  • The built-in higher-order functions are type
    checked

5
Currying
  • Most functional languages support currying or
    partial parameterization (named after the
    logician H.B.Curry)
  • mult a b a b
  • Is a function which if applied to two arguments
    will compute their product
  • In Miranda we can apply it to just one
    argument, and the result is another function
    which takes one argument, so we can define
    triple function as
  • triple mult 3
  • We say that mult has been curried or partially
    parameterised - its need for args has been
    partially met

6
  • We can define a function to sum a list
  • sumlist foldr () 0
  • This has provided 2 out of the 3 arguments
    required by foldr so the result is a function
    that takes one argument (a list) hence
  • sumlist 5, 9, 20 gt 34
  • The type of function mult is
  • mult num -gt ( num -gt num )
  • Which means mult can be regarded as a function
    with one argument that returns another function
    of type num -gt num

7
Lazy Evaluation
  • In evaluating a function the simplest way is to
    first evaluate all the arguments then invoke the
    function.
  • eg in
  • mult ( fac 3 ) ( fac 4 )
  • The function applications (fac 3) and (fac 4)
    would be done first in arbitrary order,
    reducing the expression to
  • mult 6 24
  • Then mult is applied to its two arguments
    resulting in 144
  • This is known as applicative order reduction
  • It starts with the inner-most expressions
  • Sometimes we do not want to do it this way

8
  • In Lazy evaluation we start with the outermost
    expression and work inwards, not evaluating sub
    expressions until we need their results
  • So mult (fac 3) (fac 4) is reduced to
  • (fac 3) (fac 4)
  • and next to 6 24
  • and finally 144
  • Consider a function cond that is like the
    ternary operator ? in C/C
  • cond b x y x, if b
  • cond b x y y, otherwise
  • What happens if we applicatively evaluate the
    three arguments?

9
  • One of the args is evaluated needlessly (makes
    code slower)
  • If the arg that is evaluated needlessly never
    terminates, then the whole expression never
    terminates
  • Often we use this construct to guard against
    some non-terminating or incorrect condition
  • In functional languages we might want to define
    the factorial function
  • fac n cond (n0) 1 (n fac (n -1)
    )
  • If the third argument is always evaluated this
    will never terminate (fac 1 invokes fac 0
    which invokes fac -1 .
  • These problems have led to the concept of lazy
    evaluation

10
  • Lazy evaluation uses normal order reduction and
    is where the arguments of a function are only
    evaluated when their values are needed
  • Contrast this with applicative order reduction
    which is also known as eager evaluation
  • Using lazy evaluation, the following figure shows
    how the expression is reduced

11
(No Transcript)
12
Strict Semantics
  • A language based on eager evaluation is said to
    have strict semantics because it always evaluates
    the arguments of functions
  • A language using lazy evaluation is said to have
    non-strict semantics
  • Miranda has non-strict semantics so fac in the
    example evaluates correctly

13
  • Lazy evaluation is also useful for defining and
    manipulating (potentially) infinite data
    structures like open-ended lists or sets and
    sequences (as compared with an array which is
    finitely bounded)
  • In Miranda 1.. denotes the (infinite) list
    of all positive integers, and can be manipulated
  • hd 1.. gt 1 1st element
  • hd ( tl 1.. ) gt 2 2nd element
  • hd ( tl ( map triple 1.. )) gt 6 2nd
    element of tripled list
  • This works because Miranda will only build the
    finite part of the list that is actually needed.
    Only if we (foolishly) request the whole list
    will the system run out of memory or never
    terminate eg sumlist 1.. or 1..

14
I/O in Functional Languages
  • I/O is a problem as it is not referentially
    transparent in functional languages
  • Address this problem by modeling I/O with lazy
    evaluation
  • A functional program takes a list of responses
    from the operating system (OS) as input
  • It produces a list of requests to the OS where
    the nth response answers the nth request
  • Reading and writing files can be modeled as data
    requests and confirmation exchanges with the
    OS
  • With lazy semantics the program can look at the
    OS responses when it wants to
  • Request and response lists are just streams of
    messages

15
  • Lazy evaluation semantics are costly to implement
    (surprise, NOT!)
  • Normal order reduction may evaluate an
    expression more than once
  • Applicative order evaluates expressions exactly
    once
  • double x x x
  • Normal order evaluates double 23 45 as
  • double 23 45 gt 23 45 2345 gt 10352345
    gt
  • 1035 1035 gt 2070
  • Whereas applicative order evaluates more
    efficiently as
  • double 23 45 gt double 1035 1035 1035 gt
    2070

16
Graph Reduction
  • Graph reduction is a technique for solving this
    inefficiency problem of lazy evaluation of
    expressions
  • It allows us to specify we want expressions
    evaluates zero or one times but not multiple
    times - adds some complexity to the compiler
  • There is also a small overhead in postponing
    evaluation but this can be optimised out by
    the compiler
  • Not all languages provide lazy evaluation
  • Languages that do not will have some feature
    that does provide lazy semantics eg the
    if-statement and its variants in imperative
    languages - recall also the short-cut logical
    operators in C/C

17
Equations and Pattern Matching
  • Modern functional languages like Miranda or
    Haskell have a capability for specifying
    equational functions (or just equations)
  • We have seen examples like if xgt0otherwise
  • This idea generalises to allow choices based on
    patterns with syntax like
  • ltpatterngt ltexpressiongt, condition
  • Where the condition part is optional
  • The pattern can use formal parameters etc
  • If a function is invoked the system tries to
    find a match

18
  • In Miranda (and most cases of this) it is
    the first textually occuring match that succeeds
    that will be chosen
  • Our cond example becomes the set of equations
  • cond True x y x
  • cond False x y y
  • And fac can be written as
  • fac 0 1
  • fac (n1) (n1) fac n
  • 1st pattern matches if the argument is equal to
    zero and more subtly the second pattern matches
    only if the argument is greater than or equal to 1

19
  • In general a numerical expression appearing ina
    pattern may have the form v c where v is a
    variable and c is a literal constant
  • The pattern only matches if v can be set to a
    non-negative value
  • More general numerical expressions are disallowed
    (to prevent ambiguities)
  • For example f(nm) n m is ambiguous and
    hence illegal - a call like f 9 could result in
    18 or 27 or other combinations

20
  • Patterns can also contain lists
  • We can implement the length (of a list)
    function
  • length 0
  • length ( a b) 1 (length b)
  • Pattern in 1st equation specifies an empty list,
    second will only match if argument is a non-empty
    list, and then makes a recursive call passing
    the tail of the list as the new argument
  • Recall is cons operator inserts element onto
    front of a list

21
  • Function uniq accepts a sorted list and
    eliminates all but the first occurrence of each
    item
  • uniq escape hatch empty list
  • uniq ( a ( a x) ) uniq ( a x ) matches
    eg 3,3,
  • uniq ( a x ) a uniq x matches all
    other lists
  • 2nd equation uses an advanced feature - that of
    specifying the same variable (a) twice in the
    same pattern so this matches eg 3,3,4 but not
    3,4,5
  • If 2nd succeeds a recursive call is made with
    same list as argument but with head omitted
  • If first two fail third is used also with
    recursive call but head element intact

22
  • Note that textual order of equations is
    significant
  • (in uniq example 2nd and 3rd can succeed
    simultaneously)
  • May be preferable to add some condition to the
    third pattern requiring its first two elements to
    be different - matter of programming style
  • Note also that uniq is polymorphic
  • uniq 3, 3, 4, 6, 6, 6, 6, 7 gt 3, 4, 6,
    7
  • uniq a, b, b, c gt a, b, c
  • This approach is typical of functional
    programming.

23
Summary
  • Higher-Order functions
  • Currying
  • Strict semantics
  • Equations and pattern matching
  • See Bal Grune Chapter 4, Sebesta Chapter 15
  • Next - application examples, and examples of
    functional languages and summary.
Write a Comment
User Comments (0)
About PowerShow.com