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

Programming Language Pragmatics: Michael L. Scott

Uploaded by

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

Programming Language Pragmatics: Michael L. Scott

Uploaded by

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

Chapter 10 ::

Functional Languages

Programming Language Pragmatics


Michael L. Scott

Copyright © 2005 Elsevier


Historical Origins
• The imperative and functional models grew out of
work undertaken Alan Turing, Alonzo Church,
Stephen Kleene, Emil Post, etc. ~1930s
– different formalizations of the notion of an algorithm,
or effective procedure, based on automata, symbolic
manipulation, recursive function definitions, and
combinatorics
• These results led Church to conjecture that any
intuitively appealing model of computing would
be equally powerful as well
– this conjecture is known as Church’s thesis
Copyright © 2005 Elsevier
Historical Origins

• Turing’s model of computing was the Turing


machine a sort of pushdown automaton using
an unbounded storage “tape”
– the Turing machine computes in an imperative
way, by changing the values in cells of its tape –
like variables just as a high level imperative
program computes by changing the values of
variables

Copyright © 2005 Elsevier


Historical Origins
• Church’s model of computing is called the
lambda calculus
– based on the notion of parameterized expressions
(with each parameter introduced by an occurrence of
the letter λ—hence the notation’s name.
– Lambda calculus was the inspiration for functional
programming
– one uses it to compute by substituting parameters
into expressions, just as one computes in a high
level functional program by passing arguments to
functions
Copyright © 2005 Elsevier
Historical Origins
• Mathematicians established a distinction
between
– constructive proof (one that shows how to obtain a
mathematical object with some desired property)
– nonconstructive proof (one that merely shows that
such an object must exist, e.g., by contradiction)
• Logic programming is tied to the notion of
constructive proofs, but at a more abstract level:
– the logic programmer writes a set of axioms that
allow the computer to discover a constructive proof
for each particular set of inputs
Copyright © 2005 Elsevier
Functional Programming Concepts

• Functional languages such as Lisp, Scheme,


FP, ML, Miranda, and Haskell are an
attempt to realize Church's lambda calculus
in practical form as a programming language
• The key idea: do everything by composing
functions
– no mutable state
– no side effects
Copyright © 2005 Elsevier
Functional Programming Concepts
• Necessary features, many of which are
missing in some imperative languages
– 1st class and high-order functions
– serious polymorphism
– powerful list facilities
– recursion
– structured function returns
– fully general aggregates
– garbage collection
Copyright © 2005 Elsevier
Functional Programming Concepts
• So how do you get anything done in a
functional language?
– Recursion (especially tail recursion) takes the
place of iteration
– In general, you can get the effect of a series of
assignments
x := 0 ...
x := expr1 ...
x := expr2 ...
from f3(f2(f1(0))), where each f expects
the value of x as an argument, f1 returns expr1,
and f2 returns expr2
Copyright © 2005 Elsevier
Functional Programming Concepts
• Recursion even does a nifty job of replacing
looping
x := 0; i := 1; j := 100;
while i < j do
x := x + i*j; i := i + 1;
j := j - 1
end while
return x
becomes f(0,1,100), where
f(x,i,j) == if i < j then
f (x+i*j, i+1, j-1) else x
Copyright © 2005 Elsevier
Functional Programming Concepts
• Thinking about recursion as a direct,
mechanical replacement for iteration,
however, is the wrong way to look at things
– One has to get used to thinking in a recursive
style
• Even more important than recursion is the
notion of higher-order functions
– Take a function as argument, or return a function
as a result
– Great for building things
Copyright © 2005 Elsevier
Functional Programming Concepts
• Lisp also has (these are not necessary
present in other functional languages)
– homo-iconography
– self-definition
– read-evaluate-print
• Variants of LISP
– Pure (original) Lisp
– Interlisp, MacLisp, Emacs Lisp
– Common Lisp
– Scheme
Copyright © 2005 Elsevier
Functional Programming Concepts

• Pure Lisp is purely functional; all other Lisps


have imperative features
• All early Lisps dynamically scoped
– Not clear whether this was deliberate or if it
happened by accident
• Scheme and Common Lisp statically scoped
– Common Lisp provides dynamic scope as an option
for explicitly-declared special functions
– Common Lisp now THE standard Lisp
• Very big; complicated (The Ada of functional
programming)
Copyright © 2005 Elsevier
Functional Programming Concepts
• Scheme is a particularly elegant Lisp
• Other functional languages
– ML
– Miranda
– Haskell
– FP
• Haskell is the leading language for research
in functional programming

Copyright © 2005 Elsevier


A Review/Overview of Scheme
• As mentioned, Scheme is a particularly
elegant Lisp
– Interpreter runs a read-eval-print loop
– Things typed into the interpreter are evaluated
(recursively) once
– Anything in parentheses is a function call
(unless quoted)
– Parentheses are NOT just grouping, as they are
in Algol-family languages
• Adding a level of parentheses changes meaning
Copyright © 2005 Elsevier
A Review/Overview of Scheme
• As mentioned earlier, Scheme is a
particularly elegant Lisp
– Interpreter runs a read-eval-print loop
– Things typed into the interpreter are evaluated
(recursively) once
– Anything in parentheses is a function call
(unless quoted)
– Parentheses are NOT just grouping, as they are
in Algol-family languages
• Adding a level of parentheses changes meaning
(+ 3 4)  7
((+ 3 4)))  error
(the ' ' arrow means 'evaluates to‘)
Copyright © 2005 Elsevier
A Review/Overview of Scheme
• Scheme:
– Boolean values #t and #f
– Numbers
– Lambda expressions
– Quoting
(+ 3 4)  7
(quote (+ 3 4))  (+ 3 4)
'(+ 3 4)  (+ 3 4)
– Mechanisms for creating new scopes
(let ((square (lambda (x) (* x x))) (plus +))
(sqrt (plus (square a) (square b))))
let*
Copyright © 2005 Elsevier
letrec
A Review/Overview of Scheme
• Scheme:
– Conditional expressions
(if (< 2 3) 4 5)  4
(cond
((< 3 2) 1)
((< 4 3) 2)
(else 3))  3
– Imperative stuff
• assignments
• sequencing (begin)
• iteration

Copyright © 2005 Elsevier I/O (read, display)
A Review/Overview of Scheme
• Scheme standard functions (this is not a
complete list):
– arithmetic
– boolean operators
– equivalence
– list operators
– symbol?
– number?
– complex?
– real?
– rational?
– integer?
Copyright © 2005 Elsevier
A Review/Overview of Scheme
Example program - Simulation of DFA
• We'll invoke the program by calling a function
called 'simulate', passing it a DFA description and
an input string
– The automaton description is a list of three items:
• start state
• the transition function
• the set of final states
– The transition function is a list of pairs
• the first element of each pair is a pair, whose first element is a
state and whose second element in an input symbol
• if the current state and next input symbol match the
first element of a pair, then the finite automaton enters
the state given by the second element of the pair
Copyright © 2005 Elsevier
A Review/Overview of Scheme
Example program - Simulation of DFA

Copyright © 2005 Elsevier


Evaluation Order Revisited
• Applicative order
– what you're used to in imperative languages
– usually faster
• Normal order
– like call-by-name: don't evaluate arg until you
need it
– sometimes faster
– terminates if anything will (Church-Rosser
theorem)

Copyright © 2005 Elsevier


Evaluation Order Revisited
• In Scheme
– functions use applicative order defined with
lambda
– special forms (aka macros) use normal order
defined with syntax-rules
• A strict language requires all arguments to be
well-defined, so applicative order can be used
• A non-strict language does not require all
arguments to be well-defined; it requires
normal-order evaluation
Copyright © 2005 Elsevier
Evaluation Order Revisited
• Lazy evaluation gives the best of both
worlds
• But not good in the presence of side effects.
– delay and force in Scheme
– delay creates a "promise"

Copyright © 2005 Elsevier


High-Order Functions

• Higher-order functions
– Take a function as argument, or return a function
as a result
– Great for building things
– Currying (after Haskell Curry, the same guy
Haskell is named after)
• For details see Lambda calculus later
• ML, Miranda, and Haskell have especially nice syntax
for curried functions

Copyright © 2005 Elsevier


Theoretical Foundations
Lambda Calculus

• Lambda calculus:
– A notation/model of computation based on
purely syntactic symbol manipulation, in which
everything is a function
– Developed by Alonzo Church in the '30's as a
model for computability
– Church was one of a crowd that also included
Chomsky, Turing, Kleene, and Rosser

Copyright © 2005 Elsevier


Theoretical Foundations
Lambda Calculus

• We can define things like integers in terms


of a distinguished function (like the identity
function) that represents zero, and a
successor function that gives us all the other
numbers
• This makes it easy to define the arithmetic
operators within the notation
– In practice this is kind of a nuisance
• we will just assume the existence of arithmetic and
of distinguished constant functions for numbers
Copyright © 2005 Elsevier
Theoretical Foundations
Lambda Calculus

• Example of lambda expressions


id λx.x
const λx.2
plus λx.λy.x + y
square λx.x * x
hypot λx. λy.sqrt
(plus (square x) (square y))

Copyright © 2005 Elsevier


Theoretical Foundations
Lambda Calculus
• Recursively, a lambda expression is
– (1) a name
– (2) an abstraction consisting of a lambda, a
name, a dot, and a lambda expression
– (3) an application consisting of two adjacent
lambda expressions (juxtaposition means
function application), or
– (4) a parenthesized lambda expression

Copyright © 2005 Elsevier


Theoretical Foundations
Lambda Calculus

• Usually application associates left-to-right, so f A B


is (f A) B, rather than f (A B)
• Also, application has higher precedence than
abstraction, so λx.A B is λx.(A B), rather than
(λx.A) B – e.g., ML
• Parentheses are used for clarity, or to break the rules:
by convention, use them around any abstraction that is
used as a function or an argument:
(λf.f 2) (λx.plus x x)
or around any application as an argument:
double (minus 5 2)
Copyright © 2005 Elsevier
Theoretical Foundations
Lambda Calculus
• These rules mean that the scope of the dot
extends right all the way to the first unmatched
right parentheses, or the end of the whole
expression if there is no such parenthesis
– In (λx. λy. λz.e) a b c, the initial function takes a
single argument and returns a function (of one
argument) that returns a function (of one argument)
– To reduce the expression, you substitute a for any x's
in λy. λz.e, then you substitute b for any y's in what
remains, and then c for any z's in what remains
Copyright © 2005 Elsevier
Theoretical Foundations
Lambda Calculus
• Example:
(λx. λy.x + y) 3 4
λy.(3 + y) 4
(3 + 4)
7
• Free and bound variables: a variable is
bound if it is introduced by a lambda
– For example, in λx. λy.(* x y) we have two
nested lambda expressions
• x is free in the inner one (λy.(* x y)), but bound in
Copyright © 2005 Elsevier the outer
Theoretical Foundations
Lambda Calculus

• Evaluation of lambda expressions through


– (1) substituting in arguments (beta reduction)
(λx.times x x) y => times y y
– (2) renaming variables (alpha conversion)
(often to avoid naming conflicts)
(λx.times x x) y ==(Lz.times z z) y
– (3) simplification "out of order" (eta reduction)
(λx.f x) => f
• This last rule is hard to understand; it is NOT the same as
beta reduction (see next example)
Copyright © 2005 Elsevier
Theoretical Foundations
Lambda Calculus

• (λx.f x) is a function, x is not its argument


– But if we apply the function to, say, y: (λx.f x) y
we get the same result as by applying f to y
• To make things concrete, suppose
f = (λz.times z z) ; squaring, then
(λx.f x) 3 == (λx.(λz.times z z) x) 3
=> beta (λz.times z z) 3 [outer]
=> beta times 3 3.
Using eta reduction, we get the same result
(λx.f x) 3 => eta f 3 == (λz.times z z) 3
=> beta times 3 3
Copyright © 2005 Elsevier
Functional Programming in Perspective
• Advantages of functional languages
– lack of side effects makes programs easier to
understand
– lack of explicit evaluation order (in some
languages) offers possibility of parallel evaluation
(e.g. MultiLisp)
– lack of side effects and explicit evaluation order
simplifies some things for a compiler (provided
you don't blow it in other ways)
– programs are often surprisingly short
– language can be extremely small and yet powerful
Copyright © 2005 Elsevier
Functional Programming in Perspective
• Problems
– difficult (but not impossible!) to implement
efficiently on von Neumann machines
• lots of copying of data through parameters
• (apparent) need to create a whole new array in order to
change one element
• heavy use of pointers (space/time and locality problem)
• frequent procedure calls
• heavy space use for recursion
• requires garbage collection
• requires a different mode of thinking by the programmer
• difficult to integrate I/O into purely functional model
Copyright © 2005 Elsevier

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy