Unit - V PPL
Unit - V PPL
λ(x)x * x * x
Introduction to lambda calculus
● The lambda expression is the function itself, which is nameless.
For example, consider the following lambda expression:
λ(x)x * x * x
λ(x)x * x * x
● Lambda expressions, like other function definitions, can have more than one
parameter.
Fundamentals of functional programming languages
Fundamentals of functional programming languages
● In an imperative language, an expression is evaluated and the result is stored
in a memory location, which is represented as a variable in a program. This is
the purpose of assignment statements.
● A program in an assembly language often must also store the results of partial
evaluations of expressions. For example, to evaluate
(x + y)/(a - b)
the value of (x + y) is computed first. That value must then be stored while (a - b) is
evaluated.
(A B C D)
Fundamentals of functional programming languages
Data Types and Structures (LISP)
● Nested list structures are also specified by parentheses. For example, the list
(A (B C) D (E (F G)))
● is a list of four elements. The first is the atom A; the second is the sublist (B C);
the third is the atom D; the fourth is the sublist (E (F G)), which has as its second
element the sublist (F G)
●
Fundamentals of functional programming languages
The First LISP Interpreter
● The original intent of LISP’s design was to have a notation for programs that
would be as close to Fortran’s as possible, with additions when necessary
● This notation was called M-notation, for meta-notation. There was to be a
compiler that would translate programs written in M-notation into semantically
equivalent machine code programs for the IBM 704.
● The first requirement for the universal LISP function was a notation that allowed
functions to be expressed in the same way data was expressed.
Fundamentals of functional programming languages
The First LISP Interpreter
● Function calls were specified in a prefix list form originally called Cambridge
Polish,2 as in the following:
● For example, if + is a function that takes two or more numeric parameters, the
following two expressions evaluate to 12 and 20, respectively:
(+ 5 7)
(+ 3 4 7 6)
Fundamentals of functional programming languages
The First LISP Interpreter
● Function calls were specified in a prefix list form originally called Cambridge
Polish,2 as in the following:
Expression Value
42 42
(* 3 7) 21
(+ 5 7 8) 20
(− 5 6) −1
(− 15 7 2) 6
(− 24 (* 4 3)) 12
Programming with Scheme
Primitive Numeric Functions
● There are a large number of other numeric functions in Scheme, among them
MODULO, ROUND, MAX, MIN, LOG, SIN, and SQRT.
● SQRT returns the square root of its numeric parameter, if the parameter’s value
is not negative. If the parameter is negative, SQRT yields a complex number.
● In Scheme, note that we use uppercase letters for all reserved words and
predefined functions.
● If a function has a fixed number of parameters, such as SQRT, the number of
parameters in the call must match that number. If not, the interpreter will produce
an error message.
Programming with Scheme
Defining Functions
is a nameless function that returns the square of its given numeric parameter.
Programming with Scheme
Defining Functions
● This function can be applied in the same way that named functions are: by
placing it in the beginning of a list that contains the actual parameters. For
example, the following expression yields 49:
(LAMBDA (a b c x) (+ (* a x x) (* b x) c))
Programming with Scheme
Defining Functions
The Scheme special form function DEFINE serves two fundamental needs of
Scheme programming:
The form of DEFINE that binds a name to a value may make it appear that DEFINE
can be used to create imperative language–style variables.
Programming with Scheme
Defining Functions
● The simplest form of DEFINE is one used to bind a name to the value of an
expression. This form is
● The simplest form of DEFINE is one used to bind a name to the value of an
expression. This form is
For example,
(DEFINE pi 3.14159)
(DEFINE two_pi (* 2 pi))
Programming with Scheme
Defining Functions
● The simplest form of DEFINE is one used to bind a name to the value of an
expression. This form is
● The simplest form of DEFINE is one used to bind a name to the value of an
expression. This form is
● Names in Scheme can consist of letters, digits, and special characters except
parentheses; they are case insensitive and must not begin with a digit
Programming with Scheme
Defining Functions
● The second use of the DEFINE function is to bind a lambda expression to a
name
● In this case, the lambda expression is abbreviated by removing the word
LAMBDA.
● To bind a name to a lambda expression, DEFINE takes two lists as parameters.
● The first parameter is the prototype of a function call, with the function name
followed by the formal parameters, together in a list. The second list contains an
expr.
(DEFINE (function_name parameters)
(expression)
)
Programming with Scheme
Defining Functions
● (DEFINE (function_name parameters)
(expression)
)
● (DEFINE (square number) (* number number))
(square 5)
● (DEFINE (hypotenuse side1 side2)
(SQRT(+(square side1)(square side2)))
)
Programming with Scheme
Output Functions
● Scheme includes a few simple output functions, but when used with the
interactive interpreter, most output from Scheme programs is the normal output
from the interpreter, displaying the results of applying EVAL to top-level
functions.
● Scheme includes a formatted output function, PRINTF, which is similar to the
printf function of C.
● Note that explicit input and output are not part of the pure functional
programming model
Programming with Scheme
Numeric Predicate Functions
● A predicate function is one that returns a Boolean value (some representation of either
true or false). Scheme includes a collection of predicate functions for numeric data.
● Among them are the following:
Function Meaning
= Equal
<> Not equal
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to
EVEN? Is it an even number?
ODD? Is it an odd number?
ZERO? Is it zero?
● Notice that the names for all predefined predicate functions that have words for names
end with question marks
Programming with Scheme
Numeric Predicate Functions
This specifies a function named circumf that takes a floating-point (real in ML)
argument and produces a floating-point result.
The types are inferred from the type of the literal in the expression.
Programming with ML
Function declarations in ML appear in the general form
The function
fun times10(x) = 10 * x;
fun square(x) = x * x;
ML determines the type of both the parameter and the return value from the *
operator in the function definition. Because this is an arithmetic operator, the type of
the parameter and the function are assumed to be numeric. In ML, the default
numeric type is int. So, it is inferred that the type of the parameter and the return
value of square is int.
Programming with ML
Function declarations in ML appear in the general form
fun square(x) = x * x;
square(2.75); it would cause an error, because ML does not coerce real values to int
type
Programming with ML
Function declarations in ML appear in the general form
fun square(x) = x * x;
Because ML does not allow overloaded functions, this version could not coexist
with the earlier int version. The last version defined would be the only one.
Programming with ML
Function declarations in ML appear in the general form
fun square(x) = x * x;
In ML, the particular expression that defines the return value of a function is chosen
by pattern matching against the given parameter.
fun fact(0) = 1
| fact(1) = 1
● Lists are specified in square brackets, with the elements separated by commas,
as in the following list of integers: [5, 7, 9]
● [] is the empty list, which could also be specified with nil
● The Scheme CONS function is implemented as a binary infix operator in ML,
represented as ::. For example, 3 :: [5, 7, 9] returns the following new list: [3, 5,
7, 9].
● ML has functions that correspond to Scheme’s CAR and CDR, named hd (head)
and tl (tail). For example, hd [5, 7, 9] is 5 tl [5, 7, 9] is [7,9]
Programming with ML
ML supports lists and list operations
fun length([]) = 0
| length(h :: t) = 1 + length(t);
Programming with ML
● In ML, names are bound to values with value declaration statements of the form
val new_name = expression;
For example, val distance = time * speed;
Programming with ML
● In ML, names are bound to values with value declaration statements of the form
val new_name = expression;
For example, val distance = time * speed;
● The val statement binds a name to a value, but the name cannot be later
rebound to a new value.
● Actually, if you do rebind a name with a second val statement, it causes a new
entry in the evaluation environment that is not related to the previous version of
the name.
● the old evaluation environment entry (for the previous binding) is no longer
visible
Programming with ML
The normal use of val is in a let expression.
let
val radius = 2.7
val pi = 3.14159
in
pi * radius * radius
end;
Programming with ML
ML supports lists and list operations
● filter returns a function that takes a list as a parameter. It tests each element of
the list with the predicate. Each element on which the predicate returns true is
added to a new list, which is the return value of the function.
filter(fn(x) => x < 100, [25, 1, 50, 711, 100, 150, 27, 161, 3]);
● The process of currying replaces a function with more than one parameter
with a function with one parameter that returns a function that takes the other
parameters of the initial function
● ML functions that take more than one parameter can be defined in curried form
by leaving out the commas between the parameters (and the delimiting
parentheses).For example, we could have the following:
fun add a b = a + b;
add 3 5;
This call to add returns 8,
Programming with ML
ML supports lists and list operations
● Curried functions are interesting and useful because new functions can be
constructed from them by partial evaluation.
● Partial evaluation means that the function is evaluated with actual parameters for
one or more of the leftmost formal parameters.
● For example, we could define a new function as follows:
fun add5 x = add 5 x;
val num = add5 10;
Programming with ML
ML supports lists and list operations
● Curried functions also can be written in Scheme, Haskell, and F#. Consider the
following Scheme function:
(DEFINE (add x y) (+ x y))
● A curried version of this would be as follows:
(DEFINE (add y) (LAMBDA (x) (+ y x)))
● This can be called as follows:
((add 3) 4)
Programming with ML
ML supports lists and list operations
● The last kind of term is called a structure. Structures represent the atomic
propositions of predicate calculus, and their general form is the same:
functor(parameter list)
The functor is any atom and is used to identify the structure. The parameter list can
be any list of atoms, variables, or other structures..
Programming with Prolog
Fact Statements
● The simplest form of headless Horn clause in Prolog is a single structure, which
is interpreted as an unconditional assertion, or fact. Logically, facts are simply
propositions that are assumed to be true.
female(shelley).
male(bill).
female(mary).
male(jake).
father(bill, jake).
father(bill, shelley).
mother(mary, jake).
mother(mary, shelley).
Programming with Prolog
Rule Statements
● The = operator, which is an infix operator, succeeds if its two term operands are
the same. For example, X = Y.
● The not operator, which is a unary operator, reverses its operand, in the sense
that it succeeds if its operand fails.
For example, not(X = Y) succeeds if X is not equal to Y
Programming with Prolog
Goal Statements
● The Prolog statements for logical propositions, which are used to describe both
known facts and rules that describe logical relationships among facts
● These statements are the basis for the theorem-proving model.
● The theorem is in the form of a proposition that we want the system to either
prove or disprove.
● In Prolog, these propositions are called goals, or queries.
● The syntactic form of Prolog goal statements is identical to that of headless Horn
clauses. For example, we could have
man(fred).
to which the system will respond either yes or no.
Programming with Prolog
The Inferencing Process of Prolog
● Queries are called goals.
● When a goal is a compound proposition, each of the facts (structures) is called a
subgoal.
● To prove that a goal is true, the inferencing process must find a chain of
inference rules and/or facts in the database that connect the goal to one or more
facts in the database
● For example, if Q is the goal, then either Q must be found as a fact in the
database or the inferencing process must find a fact P1 and a sequence of
propositions P2, P3, c, Pn such that P2 :- P1
P 3 :- P2
...
Q :- P n
Programming with Prolog
The Inferencing Process of Prolog
● There are two opposite approaches to attempting to match a given goal to a fact
in the database. The system can begin with the facts and rules of the database
and attempt to find a sequence of matches that lead to the goal. This approach
is called bottom-up resolution, or forward chaining.
● The alternative is to begin with the goal and attempt to find a sequence of
matching propositions that lead to some set of original facts in the database. This
approach is called top-down resolution, or backward chaining
Programming with Prolog
The Inferencing Process of Prolog
Chevy_Distance = 2205
Programming with Prolog
List Structures
● Prolog uses the syntax of ML and Haskell to specify lists. The list elements are
separated by commas, and the entire list is delimited by square brackets, as in
[apple, prune, grape, kumquat]
● The notation [] is used to denote the empty list
● Prolog simply uses a special notation.
● [X | Y] denotes a list with head X and tail Y, where head and tail correspond to
CAR and CDR in LISP.
● A list can be created with a simple structure, as in
new_list([apple, prune, grape, kumquat]).
●
Programming with Prolog
List Structures
● The | operator used to dismantle lists can also be used to create lists from given
instantiated head and tail components, as in
[Element_1 | List_2]
● If Element_1 has been instantiated with pickle and List_2 has been instantiated
with [peanut, prune, popcorn], the sample notation will create, for this one
reference, the list [pickle, peanut, prune, popcorn].
Programming with Prolog
List Structures
● The first two parameters to the append operation in the following code are the
two lists to be appended, and the third parameter is the resulting list:
append([], List, List).
append([Head | List_1], List_2, [Head | List_3]) :-
append(List_1, List_2, List_3).
● Suppose we need to be able to determine whether a given symbol is in a given
list. A straightforward Prolog description of this is
member(Element, [Element | _]).
member(Element, [_ | List]) :- member(Element, List).
Programming with Prolog
Deficiencies of Prolog
● Resolution Order Control
● The Closed-World Assumption
● The Negation Problem
● Intrinsic Limitations
– multi-paradigm languages