Download Structure of Programming Languages – Lecture 6

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Lisp (programming language) wikipedia , lookup

Curry–Howard correspondence wikipedia , lookup

Tail call wikipedia , lookup

Scala (programming language) wikipedia , lookup

Common Lisp wikipedia , lookup

Combinatory logic wikipedia , lookup

Intuitionistic type theory wikipedia , lookup

Currying wikipedia , lookup

Lambda calculus wikipedia , lookup

Closure (computer programming) wikipedia , lookup

Anonymous function wikipedia , lookup

Lambda calculus definition wikipedia , lookup

Lambda lifting wikipedia , lookup

Falcon (programming language) wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Standard ML wikipedia , lookup

Transcript
Structure of Programming Languages – Lecture 6
CSCI 6636 – 4536
October 20, 2014
CSCI 6636 – 4536
Lecture 6. . .
1/41
October 20, 2014
1 / 41
Outline
1
Names and Objects
One object–one name?
Symbols and Symbol Tables
2
Functional Programming
Functional Programming
Overview of Syntax
Scheme Types
Special Forms
Scheme Functions
3
Defining gcd in Scheme
4
Higher-order Functions.
5
Homework
CSCI 6636 – 4536
Lecture 6. . .
2/41
October 20, 2014
2 / 41
Names and Objects
Names and Objects
A many:many relationship
Binding a name to an object
Lifetimes
CSCI 6636 – 4536
Lecture 6. . .
3/41
October 20, 2014
3 / 41
Names and Objects
One object–one name?
Names and Objects: A many:many relationship
In an simple world, each object might have one name, and each name one
object. Programming languages are far from simple.
(Examples are given in the context of C.)
An object can have NO name (the result of a call on malloc).
An object can have one name: a local integer variable.
An object can have two names: an array has a name, and when
passed as a parameter, the parameter name becomes a synonym.
A name can be bound to NO objects (#define UNIX)
A name can be bound to exactly one object: a global variable name
that is not redeclared elsewhere in the program.
A name can be bound to multiple objects simultaneously: a
parameter name in a recursive function, after several recursions.
CSCI 6636 – 4536
Lecture 6. . .
4/41
October 20, 2014
4 / 41
Names and Objects
One object–one name?
Ambiguous Names
There are several good reasons why the same program might have two
definitions of the same name with different meanings:
In OO languages, there are often many methods for the same
function, with different signatures.
In a multi-person team project, programmers working separately will
be likely to use names in conflicting ways.
When you import a package written by others, you will probably find
that you have used some of the same identifiers.
Programmers often reuse their own names. It is undesirable to invent
a new name every variable in a large program.
For all of these reasons, a useful language must allow the same name to
have multiple meanings, and must provide a way to resolve ambiguities.
CSCI 6636 – 4536
Lecture 6. . .
5/41
October 20, 2014
5 / 41
Names and Objects
One object–one name?
Resolving Ambiguous Names
Ambiguous names are resolved in various ways in different languages:
Use block-structured scoping and local names.
Use the run-time stack to resolve recursive names.
Apply default rules about the meaning of a name in an ambiguous
context.
Use a prefix (namespace name, package name, or class name) before
the name of an object.
Use the static modifier in C or a package in Java to restrict the
scope of a name to its defining module.
Define namespaces to keep each major package separate from others.
A class encloses all functions and data related to it.
CSCI 6636 – 4536
Lecture 6. . .
6/41
October 20, 2014
6 / 41
Names and Objects
One object–one name?
How much do names matter?
Style matters. What does this simple C function do?
typedef struct XX { char next; struct XX* prior; } myType;
typedef myType* xType;
xType storeIt (xType temp, char jxq)
{
xType jqx, first;
first = temp; jqx = temp->prior;
while (jqx != NULL) {
if( jqx->next == jxq) jqx = NULL; else {
first = jqx;
jqx = jqx->prior; }
}
return first;
}
CSCI 6636 – 4536
Lecture 6. . .
7/41
October 20, 2014
7 / 41
Names and Objects
Symbols and Symbol Tables
Names and Objects
Common to all languages is that an object has
a name
a type
a body or meaning
How these things are related, however, varies greatly. There are three
major approaches:
Static typing: C, FORTH,
Dynamic typing: Scheme, scripting languages
OO typing: C++, Java
CSCI 6636 – 4536
Lecture 6. . .
8/41
October 20, 2014
8 / 41
Names and Objects
Symbols and Symbol Tables
Static Typing
An object is created by a declaration or by calling new.
Space is allocated for it according to the specified type and it may be
initialized.
The name, type, and memory location are recorded in the symbol
table at compile time. This information may be supplied to a
debugger.
At run time, the name and type no longer exist. Names have been
translated into positive and negative offsets from the stack pointer.
Types have been checked and discarded.
Symbol Table
type
name
Runtime Memory
binding storage object
double weight
int[4]
CSCI 6636 – 4536
ages
Lecture 6. . .
9/41
October 20, 2014
9 / 41
Names and Objects
Symbols and Symbol Tables
Dynamic Typing
Objects are created by writing literals, by taking input, or by explicit
calls on constructors.
Names (global or local) are bound to these objects at run time by
executing a binding command.
The type of the object is part of the object at run time and is used by
primitive functions for type checking.
A name can be rebound at any time to a different object of possibly a
different type.
Symbol Table
name
Runtime Memory
binding storage object : type tag
weight
32.5
mylist
CSCI 6636 – 4536
: list
17
Lecture 6. . .
: real
10/41
October 20, 2014
10 / 41
Names and Objects
Symbols and Symbol Tables
OO Typing
This is a mixture of the two simpler typing mechanisms:
An object is created by a declaration or by calling new.
Space is allocated and initialized according to the specified type.
The name, type, and memory location are recorded in the symbol
table at compile time and possibly supplied to a debugger.
An object has a declared type and also inherits the type(s) of its base
class(es).
If the class is polymorphic, every instance will carry its type tag at run
time and function methods will be dispatched based on that type tag.
Symbol Table
Pet
Cat
Bird
CSCI 6636 – 4536
type
name
double
Cat
Pet*
weight
c1
pp
Runtime Memory
binding most objects
Lecture 6. . .
polymorphic objects
137
Cat
11/41
Callie
F 10
October 20, 2014
11 / 41
Names and Objects
Symbols and Symbol Tables
Implications of the Typing System
With static typing, many errors are caught at compile time, when the
programmer is actively working on the project and best able to clarify
his semantic intent. This is certainly the easiest and most sure way to
catch a broad class of program errors.
With dynamic typing, type errors are not caught until run time. This
problem is ameliorated by using automated testing during the
development process. The programmer writes his code and also writes
a separate unit-test program to test each part of the code. Random
tests are generated and their results compared to the expected results.
Of course, automated testing could (should?) also be used with
statically typed languages, but then it is a secondary defense, not the
only defense.
OO typing achieves the run-time flexibility of dynamic typing while
maintaining the advantage of static type checking for most objects.
CSCI 6636 – 4536
Lecture 6. . .
12/41
October 20, 2014
12 / 41
Functional Programming
Hello Scheme!
Functional Programming
Introduction to Scheme
CSCI 6636 – 4536
Lecture 6. . .
13/41
October 20, 2014
13 / 41
Functional Programming
Functional Programming
LISP, Scheme, and Functional Languages
The Functional idea: no sequences, no assignment.
LISP: early 1960’s: List processing language. Small and simple, but
powerful
Scheme: A lexically-scoped LISP.
1
Common Lisp: A collection of all the parts people have ever attached
to a LISP system, including non-functional loops, assignments, and
sequences.
Miranda, ML, Haskell: Updated in both syntax (all those parentheses)
and semantics (tuples). More purely functional than Common Lisp
and Scheme.
1
Current versions of Scheme support a vector type. like a C array, its elements can
be both read and written. In this class, we will work within the pure functional part of
Scheme – that is, we will not use vectors.
CSCI 6636 – 4536
Lecture 6. . .
14/41
October 20, 2014
14 / 41
Functional Programming
Functional Programming
The Scheme Language
SLIB
portable libraries
Parsing
Formatted I/O (stdio),printing
Bit-Twiddling
Arguments, getopt
Time and date
HTML Forms, Tables, parsing
XML
Arithmetic: modular, irrational
Prime and random numbers
Matrix algebra
Fourier transform
Graphing, solid modeling
Color
Database
Arrays
Sorting & Searching
more ...
6. A Scheme System
5. Files, Folders, Devices
4. Lexical Structure, Comments
3. Syntax
2. Semantic Interpretation
1. Scheme Interpreter OR .. native code compiler
Operating System and Hardware Platform
CSCI 6636 – 4536
Lecture 6. . .
15/41
October 20, 2014
15 / 41
Functional Programming
Overview of Syntax
Workspaces and Overview
Like Forth and Python, a Scheme application consists of a set of
function definitions in a workspace. Workspaces can be saved.
In Scheme, everything is written in prefix notation.
Fundamental syntactic elements are:
Objects: symbols, literals, pairs, vectors, functions, ports, eof, and null.
Expressions.
Lists of expressions, enclosed in parentheses.
Function definitions.
Function calls.
Special forms.
CSCI 6636 – 4536
Lecture 6. . .
16/41
October 20, 2014
16 / 41
Functional Programming
Overview of Syntax
Lexical Structure
Not case-sensitive
Delimiters: ( ) and whitespace
Comments start with ; and go to the end of the line.
Strings are enclosed in "double quotes".
Identifiers:
May be any length
Cannot begin with a digit
May contain letters and digits.
May contain ! $ % & * + - . / : < = > ? @ _ ~ ^
Numbers: 12345
CSCI 6636 – 4536
123.45
123.4e5
Lecture 6. . .
1/2 1+2i
17/41
0+-2i
October 20, 2014
17 / 41
Functional Programming
Scheme Types
Objects and Types in Scheme
Numbers: only the first type, below, is required.
Integers, no maximum value, exact.
Rational numbers, exact
Real numbers, not exact, like double in the local C implementation.
Complex numbers, not exact.
Boolean: #f and #t
Symbols: ’red ’green
Pairs: records with two untyped fields, used to build list structures.
Constructor is cons. Selectors are car and cdr.
Characters: #\A
Strings: as in C, ”Hello”
Vectors: 1-D arrays of objects (heterogeneous)
Procedures (functions) are objects.
Ports and the eof-object.
null: The empty list.
CSCI 6636 – 4536
Lecture 6. . .
18/41
October 20, 2014
18 / 41
Functional Programming
Scheme Types
Types have Constructors, Selectors, Predicates, Literals
Constructors are needed for non-atomic types:
A pair or a list is constructed by using cons
A procedure is constructed using define and lambda.
Selectors are needed for non-atomic types. They are use for run-time
type testing:
The selectors for the first and second parts of a pair are: car and cdr.
An element of a vector is selected using vector-ref and a 0-based
subscript.
Predicates exist for all types:
null? , pair? , boolean?, string? , procedure?
Literals are defined for all primitive types:
null, (3 4) , #f and #t, #\A, "Hello"
CSCI 6636 – 4536
Lecture 6. . .
19/41
October 20, 2014
19 / 41
Functional Programming
Scheme Types
Literals and Type-Testing
On the left are Scheme expressions. Following the arrow is the result of
each expression:
(number?
12.2) ⇒ #t
(symbol?
’yellow ) ⇒ #t
#t ) ⇒ #t
(boolean?
(procedure?
+) ⇒ #t
(null?
’()) ⇒ #t
(pair?
(pair?
’(0 1)) ⇒ #t
’null) ⇒ #f
(string?
(pair? ’(1)) ⇒ #t
(pair? ’(a b c)) ⇒ #t
"Hello") ⇒ #t
(char-upper-case? #\s) ⇒ #f
(char-lower-case? #\s) ⇒ #t
(char->integer #\A) ⇒ 65
CSCI 6636 – 4536
Lecture 6. . .
20/41
October 20, 2014
20 / 41
Functional Programming
Scheme Types
Type Conversions
Note the difference between a type predicate and the corresponding type
conversion:
(char-upcase #\s) ⇒ #\S
(char-downcase #\S) ⇒ #\s
(integer->char 97) ⇒ #\a
CSCI 6636 – 4536
Lecture 6. . .
21/41
October 20, 2014
21 / 41
Functional Programming
Scheme Types
List Structures
Four ways to define a list of two lists.
1. Constant: (define s3 '((1 2 ) (4 7)) )
2. Basic notation: (define s3 '((1 . (2 . ())) . ((4 . (7 . ())) . () )))
3. Construct it: (define s3
(cons (cons 1 (cons 2 ()) )
(cons (cons 4 (cons 7 ()) ))
))
4. Use variables: (define a (list 1 2) ) (define b (list 4 7) )
(define s3 (list a b))
S3
1
CSCI 6636 – 4536
2
4
Lecture 6. . .
22/41
7
October 20, 2014
22 / 41
Functional Programming
Special Forms
Special Forms
A special form is a syntactic representation of a semantic construct.
Special forms are needed for semantics that cannot be implemented in the
form of normal functions.
In scheme, this includes:
Control statements
Definition forms.
Two functions for which we need lazy evaluation.
CSCI 6636 – 4536
Lecture 6. . .
23/41
October 20, 2014
23 / 41
Functional Programming
Special Forms
Strict vs. Lazy Evaluation
In strict evaluation, all of the arguments to a function are evaluated before
calling the function. Normally, in Scheme (as in C) strict evaluation is
used for function calls.
In lazy evaluation, the function is called with un-evaluated argument
expressions. An argument expression is not evaluated until its result is
needed. If not needed, it is not evaluated.
Although not essential for programming, cleaner and more efficient
programs can be built if lazy evaluation is used for logical-and and
logical-or. In Scheme, as in C, these functions use lazy evaluation:
and
; Used like a function name, but performs lazy evaluation.
or
; Used like a function name, but performs lazy evaluation.
CSCI 6636 – 4536
Lecture 6. . .
24/41
October 20, 2014
24 / 41
Functional Programming
Special Forms
Special Forms for Definitions
(define <name> <expr>) ; introduce a global name
(let (<name-value-pair-sequence>) <expr-sequence>) ;
introduce local names, bound to values.
(define (<name> <parameter-sequence>) <expr-sequence>) ;
define a global name for a function
(lambda (<param-list>) <expr-sequence>) ; a function
(lambda <name> <expr-sequence>) ; a vararg function
Note: Unless the capacity for defining new vararg functions is part of the
semantic basis of a language, functions such as printf() cannot be
defined.
CSCI 6636 – 4536
Lecture 6. . .
25/41
October 20, 2014
25 / 41
Functional Programming
Special Forms
Special Forms for Control
(if <test> <true-expr> <false-expr>) ; Like C and FORTH
(cond <test> <true-expr> <false-expr>) ; Same as old LISP
(begin <expr-sequence>) ; a block of statements
Recursion: a function can call itself.
Scheme supports other control structures, but they can be defined as
ordinary functions.
CSCI 6636 – 4536
Lecture 6. . .
26/41
October 20, 2014
26 / 41
Functional Programming
Scheme Functions
Example: Procedure Definitions and Calls
Function application (function call): (fname par1 par2...)
(+ 3 5)
(sqrt 25)
(* 2 5 7)
(char->integer #\A)
lambda: a nameless function-object, with parameters.
(lambda (x y) (+ (* x x) y))
define: bind a global name to an object.
(define squarePlus (lambda (x y) (+ (* x x) y)))
A short form of define for functions:
(define (squarePlus x y) (+ (* x x) y))
Apply the nameless function to arguments 17 and 4.
((lambda (a b) (squarePlus (1+ b) a)) 17 4 )
Short and coherent form, using let.
(let ( (a 17) (b 4) ) (squarePlus (1+ b) a) )
CSCI 6636 – 4536
Lecture 6. . .
27/41
October 20, 2014
27 / 41
Functional Programming
Scheme Functions
A statement sequence.
A lambda expression allows a sequence of expressions in the body of the function.
The value of the last expression is the return value. This is useful for output.
(define run (lambda ()
(display "Countdown: ")
(display (countdown 5))
(newline)
()
))
Here is the short form, without the explicit lambda:
(define (run)
(display "Countdown: ")
(display (countdown 5))
(newline)
()
)
A sequence can also be defined with (begin ...)
CSCI 6636 – 4536
Lecture 6. . .
28/41
October 20, 2014
28 / 41
Functional Programming
Scheme Functions
If and cond.
The test-expression is followed by the true-part and the false-part.
(define (factorial k)
(if (= k 1) 1 (* k (factorial (- k 1)) ) )
)
Starting with the first pair, the expression on the left is evaluated. If #t, the
expression on its right is evaluated and the answer becomes the value of the
cond. Otherwise, control goes to the next test-pair. The last clause (which lacks
a test) is the default clause.
(define (score n) ; cond is a multi-branch conditional.
(cond
((< n 0) "No!")
((= n 0) "Work harder.")
((= n 1) "Better.")
(
"Nice.")
)
)
CSCI 6636 – 4536
Lecture 6. . .
29/41
October 20, 2014
29 / 41
Functional Programming
Scheme Functions
Recurse rather than loop.
;;; Countdown from n to 0
(define (countdown k)
(if (= k 0)
’(0)
(cons k (countdown (- k 1)) )
)
)
(countdown 5) ⇒ (5 4 3 2 1 0)
;;; Do it with a tail recursion (same result).
(define (counttail k s)
(if (< k 0)
(reverse s)
(counttail (- k 1) (cons k s) )
)
)
CSCI 6636 – 4536
Lecture 6. . .
30/41
October 20, 2014
30 / 41
Defining gcd in Scheme
gcd in Scheme
We will use a subset of Scheme that is close to pure functional
programming.
Recursion, not loops.
Binding, not assignment.
Lexically scoped semantics.
Our single escape from functional usage is that we will use sequences of
statements. Please ask questions about Scheme.
CSCI 6636 – 4536
Lecture 6. . .
31/41
October 20, 2014
31 / 41
Defining gcd in Scheme
Part 2
Slide
Slide
Slide
Slide
Slide
33:
33:
34:
34:
35:
run (The top-level function, like main.)
loop (A tail-recursive function that implements repetition.)
mygcd (Recursive definition using cond.)
gcdprint (Produces formatted output.)
The results of calling (run).
CSCI 6636 – 4536
Lecture 6. . .
32/41
October 20, 2014
32 / 41
Defining gcd in Scheme
Scheme implementation of GCD
;;; --------------------------------------------- Top-level
(define (run)
(display "Greatest Common Divisor")
(newline)
(loop)
)
;;; -------------------------------- Recurse rather than loop.
(define (loop)
(display "Enter two integers (0 0 to end): " )
(newline)
(let ((n1 (read))
; bind name to meaning.
(n2 (read))
; scope is the let-block.
)
(cond ((= n1 0)
)
((gcdprint n1 n2) (loop)))
))
CSCI 6636 – 4536
Lecture 6. . .
33/41
October 20, 2014
33 / 41
Defining gcd in Scheme
Scheme implementation of GCD
;;; -------------------------------------- The gcd computation
(define (mygcd x y)
(cond ( (or (< x 0) (< y 0)) (mygcd (abs x) (abs y)) )
((< x y)
(mygcd y x)
)
((= y 0)
x
)
(
(mygcd y (remainder x y))
)
) )
;;; --------------------------------------------- Calling gcd
(define (gcdprint a b)
(let (
(f (list "The gcd of " a " and " b " is " (mygcd a b)))
)
(for-each display f)
(newline)
) )
CSCI 6636 – 4536
Lecture 6. . .
34/41
October 20, 2014
34 / 41
Defining gcd in Scheme
Scheme implementation of GCD
(run) ;;; ---------------------------------------- Calling gcd
Greatest Common Divisor
Enter two integers (0 0 to end):
21 98
The gcd of 98 and 21 is 7
Enter two integers (0 0 to end):
0 0
;Value: #t
CSCI 6636 – 4536
Lecture 6. . .
35/41
October 20, 2014
35 / 41
Higher-order Functions.
Higher-order Functions.
In Scheme, functions are first-class objects.
That is, they can be used in the same ways and the same contexts as
other objects such as numbers and lists.
A higher-order function is one that takes a function as its parameter
or returns a function as its result. Some of these are built into
scheme, others can be defined.
apply returns the result of applying its first argument to its second
argument.
map returns a list which is the result of applying its first argument to
each element of its second argument.
for-each is a built-in higher-order function. It maps a function down
a list to cause side-effects, and is often used for I/O.
A reduce operation applies a procedure to each element of a list.
CSCI 6636 – 4536
Lecture 6. . .
36/41
October 20, 2014
36 / 41
Higher-order Functions.
Higher-order Functions.
for-each is a built-in higher-order function. It maps a function down a
list to cause side-effects. It is often used for I/O.
(define (gcdprint j k)
(let (
(f (list "The gcd of " j " and " k " is " (gcd j k)))
)
(for-each display f)
(newline)
#t
)
)
1 ]=> ( gcdprint 15 3)
The gcd of 15 and 3 is 3
;Value: #t
CSCI 6636 – 4536
Lecture 6. . .
37/41
October 20, 2014
37 / 41
Higher-order Functions.
Mapping down a List.
map: Apply a function to a list, collect results, return.
(map 1+ ’(1 3 7 15)) ⇒ (2 4 8 16)
1 ]=> (map 1+ ’(1 3 7 15))
;Value 2: (2 4 8 16)
1 ]=> ( map square (list 17 15 13))
;Value 12: (289 225 169)
1 ]=> (define (half x) (* x .5) )
1 ]=> (define (half2 x) (/ x 2) )
1 ]=> (map half (list 16 15 14))
;Value 13: (8. 7.5 7.)
1 ]=> (map half2 (list 16 15 14))
;Value 14: (8 15/2 7)
CSCI 6636 – 4536
Lecture 6. . .
38/41
October 20, 2014
38 / 41
Higher-order Functions.
Reduce
A reduce operation applies a procedure to each element of a list.
It calculates and returns a non-list answer.
::: proc is the function to apply
;;; base is an value for the null list.
;;; ls is the list to reduce.
(define (reduce proc base ls)
(if (null? ls)
base
(proc (car ls) (reduce proc base (cdr ls)))
))
(reduce * 1 ’(2 3 4 5)) ⇒ 120
(reduce + 0 ’(2 3 4 5)) ⇒ 14
(reduce + 10 ’() ) ⇒ 10
CSCI 6636 – 4536
Lecture 6. . .
39/41
October 20, 2014
39 / 41
Higher-order Functions.
Map-reduce
(define (map-reduce f1 f2 base ls)
(if (null? ls)
base
(f2 (f1 (car ls)) (map-reduce f1 f2
(define (odd x)
(define (andy p
(map-reduce odd
(map-reduce odd
CSCI 6636 – 4536
base (cdr ls))) ))
(= 1 (modulo x 2)) )
q) (and p q))
andy #t ’(1 3 5 7 9)) ⇒ #t
andy #t ’(1 3 4 5 7 9)) ⇒ #f
Lecture 6. . .
40/41
October 20, 2014
40 / 41
Homework
Homework: Read Chapters 6 and 7
1. Compare my implementations of gcd in Scheme and in Lisp. Identify
the differences and comment on them. Run the scheme gcd program
and turn in the evidence.
2. Give as regular expression, or set of them, that defines Scheme
rational literals.
3. Draw a finite state machine that accepts Scheme real numbers.
Assume that a number CAN to start or end with a decimal point and
must have a decimal point somewhere in it.
4. What is a type tag? Explain in your own words why objects in Python
and Scheme need type tags.
5. Write a function in Scheme to take as parameters the base and
altitude of a right triangle. Print a formatted message that echoes
the inputs and prints the area of the triangle. Use rational arithmetic.
6. Write a function in Scheme to take as parameters the diameter and
height of a cylinder. Returns the volume of the cylinder. Use real
arithmetic.
CSCI 6636 – 4536
Lecture 6. . .
41/41
October 20, 2014
41 / 41