Anda di halaman 1dari 8

A. What is a programming language?

-----------------------------------------PROGRAMMING LANGUAGE
def: a *programming language* is
a language that is capable of expressing all
computations.
Idea of Turing Machine what is meant to be
capable?
def: a *general-purpose language*
is one that is not tailored to some
particular application area.
Not designed for any particular domain
Examples: Java, C, C++, Python
def: a *special-purpose language*
is a language that is designed to
support some particular application.
is designed for some special domain purpose
Examples: SQL, Javascript, Visual Basic, MATLAB,
COBOL, Fortan, bash, sh, zsh
B. objectives
What are your objectives for this course?
How do you want this course to help you in 5
years?
-----------------------------------------COURSE OBJECTIVES
Quickly Learn new programming languages
Master them, and effectively use them
Evaluate what combination of features as models
are best for a problem
-----------------------------------------C. outcomes
-----------------------------------------LEARNING OUTCOMES

-----------------------------------------1. computational models


-----------------------------------------COMPUTATION MODELS
def: A *computational model* is a very
small programming language that provides
primitives necessary for computation.
C or Assemly kernal of some idea or way to
program
Properties of computation models (Abelson et al)
data (operations, means of computation),
structuring mechanisms (means of combination),
abstraction mechanisms (means of abstraction)
Examples:RISC, lambda-calculus, objective-calculus
-----------------------------------------2. programming models
-----------------------------------------PROGRAMMING MODELS
def: A *programming model* (or *paradigm*)
is a programming language together with:
a way to design, code , test/verify/reason a way
to approach problems and design a way to organize
programs (style)
a set of questions: on how to evaluate what makes
a program (or design) good?
Examples:
object-oriented
functional: i.e. Haskell, Erlang (no type system)
Both are important for future programming of
parallel processing, also avoid side effects with
data usage in parallel code
actor-based: Scalla (i.e. Twitter)
logic: Prolog
-----------------------------------------2. syntax
-----------------------------------------HOW COMPILERS WORK

Concepts understand, use and apply concepts and


terms
Use Models effectively program
character stream from the file
Evaluate Models say which model of programming is
|
best for which problems
|"public static void ..."
Map To Languages explain concepts in terms of
_______v____________
known languages
| Lexical Analysis |
|___regular grammar__|
-----------------------------------------|
"void"
D. plan for the course
token stream "static"
-----------------------------------------|
"public"
PLAN FOR THE COURSE
_______v___________
|
Parser
|
Broad outline:
|__context free grammar_|
parse tree
- overview
|
CompilationUnit
- functional programming
abstract syntax
|
\
- parallel or concurrent programming
tree

ClassDecl
- distributed or relational programming
InterfaceDecl
|
|
|
We will use "real" languages to help you
_______v___________ MethodDecl
evaluate them and learn about learning them
| Static Checker
|
|
V
|___________________|
i.e. symbol table

|
annotated AST
|
_______v___________
| Code Generation |
|___________________|
|
v
object code
-----------------------------------------a. lexical grammar
-----------------------------------------LEXICAL (REGULAR) GRAMMAR EXAMPLE
nonterminals ::= can be
<Id> ::= <NonUpper_Letter> { <NameChar> }
<VIdent> ::= <UpperLetter_> { <NameChar> }
<NonUpper_Letter> ::= a | b | c | d | ... | z
<UpperLetter_> ::= _ | A | B | C | D | ... | Z
<NameChar> ::= <NonUpper_Letter> | <UpperLetter_>
| <Digit> | + | <Digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
-----------------------------------------What are examples of <Id>s? a
What are examples of <VIdent>s? A
-----------------------------------------CONVENTIONS AND EXTENSIONS (EBNF)
defining the symbols
{ <X> } ::= <Empty> | <X> { <X> }
<X>*
::= <Empty> | <X> <X>*
<X>+
::= <X> | <X> <X>+
[ <X> ] ::= <Empty> | <X>
[ <X> ]... ::= <Empty> | <X> [ <X> ]...
<Empty> ::=
-----------------------------------------b. syntax and context-free grammars
-----------------------------------------BNF (CONTEXT-FREE GRAMMAR) EXAMPLE
<Term> ::= <Term> <TypedCIdent>
|
<TypedCIdent> <Term>
|
<Term> <Term>
|
<TypedId> \ <Term>
|
'[' ']'
|
'[' TermList ']'
|
'[' TermList '|' Term ']'
|
<TypedCIdent>
|
<TypedVar>
|
<TypedId>
|
( <Term> )
<TermList> ::= <Term>
|
<Term> , <TermList>
<TypedCIdent> ::= <Id>
|
<Id> : <Type>
|
( <TypedCIdent> )
<TypedId> ::= <Id>
|
<Id> : <Type>
|
( <TypedId> )
<TypedVar> ::= <VIdent>
|
<VIdent> : <Type>
|
( <TypedVar> )
-----------------------------------------What are examples of <Term>s?
II. Example: learning lambda Prolog

A. motivation
-----------------------------------------MOTIVATIONS FOR LOGIC PROGRAMMING

- (ordered L2) or (empty L2)


not a unique outcome: ; (semi-colon)
Effectively describe a relationship?

1. write programs efficiently


2. execute specifications
prototyping (want to make sure its what the user
wants
3. separate directions about control
and data structures
How would you specify a sort routine?
sort(L) = L
where ordered (L)
and permutation of (L,L)
what we mean by ordered
Items in the original list are items of the sorted
list
-----------------------------------------How can we then use this specification to
sort some list L?
constructive: features that allow automation of
proofs (top level logic programming)
How could such a theorem be proved?
by construction
B. programming model
-----------------------------------------ABSTRACTING FROM THE EXAMPLE

- (sorted L1 L2) if :((ordered L2), (permutation L1 L2))


- (less X Y) if not (greater X Y)
Does "not" give an effective computation?
problematic: because its hard to figure out the
relationships
-----------------------------------------What about universal quantification? Existential
quantification?
-----------------------------------------CONNECTIVES FOR EFFECTIVE QUERYING
Effectively ask for L2?
- (ordered L2) and (permutation L1 L2)
- (ordered L2) or (empty L2)

-----------------------------------------E. means of abstraction (usually naming)


1. facts and rules
-----------------------------------------FACTS AND RULES
% file facts_rules.sig
Model: programs are modeled as relations between the sig facts_rules.
outputs
kind entity type.
Specification of a problem:
a problem to be solved is (1) predicate that defines
a relation that we want (2) and, existential query
L :: L = sort(L)
Answer to a problem: the value needed to make the
relation true (i.e. search)
-----------------------------------------Why is the programming model important?
C. Basic elements of a language
1. Data (means of computation)
-----------------------------------------WHAT DATA?

type flower entity.


type spock entity.
type good entity -> o.
type logical entity -> o.
% file facts_rules.mod
% fact
good flower.
logical spock.

% rule
good X :- logical X.
For logic programming use:
-----------------------------------------data
syntax
a. compound terms in LambdaProlog
- named entities
<Id>,<Numeric Literal
logic: anything that is not found true, by
- unknown entities <VIdent> i.e. X,Y,Z
default it is false
- relationships
<Id>,<Term>
-----------------------------------------(term is application of one onto another i.e. sorted COMPOUND TERMS
lst)
Items are treated symbolically
(tree Subtree1 Root Subtree2)
-----------------------------------------(((tree Subtree1) Root) Subtree2)
D. means of combination
describe relations between things
%lists:
-----------------------------------------a::b::nil
CONNECTIVES FOR EFFECTIVE SPECIFICATION
(sentence (np (n ron))
Effectively describe L2?
(vp (v gave)
unique things specified by that
(np (art a) (n paper))
- (ordered L2) and (permutation L1 L2)
(compls (prep to)
unique outcome: , (coma)
(np (n sue)))))

-----------------------------------------b. scope of variables


-----------------------------------------SCOPE OF VARIABLES
(understand L X) :- (know terms L X),
(know syntax L X),
(know semantics L X).
(grandparent K L) :(parent K P), (parent P L).
-----------------------------------------Which L's should mean the same person?
So what does that mean the scope of a
variable is in lambda Prolog?
2. kinds and types
-----------------------------------------KINDS AND TYPES
% declaration of a type
kind event type.
kind person type.
% declaration of type of a name
type actor event -> person -> o.
-----------------------------------------3. Examples
a. assertions
-----------------------------------------% A SEMANTIC NETWORK
sig semantic_net.
kind
kind
kind
kind

event type.
person type.
thing type.
verb type.

type
type
type
type
type
type
type
type

event1 event.
paper thing.
sue person.
ron person.
gave verb.
event2 event.
football thing.
swen person.

type object event -> thing -> o.


type recipient event -> person -> o.
type actor event -> person -> o.
type action event -> verb -> o.
above four lines are a grammar that we are making
up
defining how we must interpret the argument
----------------------------------------------------------------------------------module semantic_net.
% a semantic network
object event1 paper.
recipient event1 sue.
actor event1 ron.
action event1 gave.
Ron gave the paper to Sue

-----------------------------------------b. queries
what is the result of the query:
recipient event1 Who. ?
how would you add the fact that in event2,
sue gave the football to swen?
4. Lists
-----------------------------------------% LISTS
sig list.
% this is all built in to lambda Prolog
% but this shows how it would be done.

-----------------------------------------a. declarative
b. Procedural reading (programming language)
6. tracing queries
7. variation on addtoend
-----------------------------------------% VARIATION ON ADDTOEND

kind list type -> type.

module addtoend2.

type nil (list T).


type '::'
T -> (list T) -> (list T).
infixr '::'
5.
----------------------------------------------------------------------------------LIST NOTATION ISN'T SPECIAL

equals (addtoend nil X) (X::nil).


equals (addtoend (Y::L) X) (Y::M)
:- equals (addtoend L X) M.
-----------------------------------------can you trace this?
8. reverse
can you write append of type
(list T) -> (list T) -> (list T) -> o ?

% signature file
sig lisp_lists.
kind lisp_list

type -> type.

sig addtoend2.
type equals T -> T -> o.
type addtoend (list T) -> T -> (list T).

I. Introduction to Haskell
A. What's interesting about Haskell?
-----------------------------------------FUNCTIONAL PROGRAMMING

type the_empty_list
(lisp_list T).
type cons T -> (lisp_list T) -> (lisp_list T).
t ~ element, lisp_list ~ list, ~ return the - Models computations as expressions
list
- All changing arguments passed explicitly
type to_list
(lisp_list T) -> (list T) ->
(no implicit global state)
o.
- Functions as data allows better abstraction
end
HASKELL FEATURES COMMON TO FUNCTIONAL LANGUAGES
% the module
module lisp_lists.
- Data is treated abstractly (as terms)[1,2,3]
- Powerful pattern matching
% an inductive definition
- All functions take just one argument
to_list the_empty_list nil.
(use tuples to group multiple arguments as one)
to_list (cons Head Tail) (Head::PL) :- to_list Tail - Powerful library
PL.
- Order of definition doesn't matter
end
-----------------------------------------UNIQUE FEATURES OF HASKELL
what are these type decls like in Haskell?
a. example using lists
- Type-based separation of
-----------------------------------------computations with effects from
sig addtoend1.
pure expressions
- I/O actions are data
type addtoend
- Type classes for static overloading
(list T) -> T -> (list T) -> o.
- Lazy evaluation is the default
module addtoend1.
only if its needed will the value be returned
addtoend
- Type expressions resemble values
-----------------------------------------What's the difference between an expression and a
How would we write this?
statement?
5. Interpretations of clauses
expressions have values but statements dont
-----------------------------------------INTERPRETATIONS OF CLAUSES
-----------------------------------------B. Haskell platform mechanics
(h X) :- (b1 Y), (b2 Z), (b3 W).
1. getting in and out
declarative interpretation:
-----------------------------------------procedural interpretation:

HASKELL PLATFORM BASICS


Get GHC from www.haskell.org/platform
$ ghcii
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :?
for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>
-----------------------------------------2. working with files
-----------------------------------------WORKING WITH FILES
Prelude> :load "Fact.hs"
[1 of 1] Compiling Fact
interpreted )
Ok, modules loaded: Fact.
*Fact> fact

( Fact.hs,

II.Fact> fact
<interactive>:3:1:
No instance for (Show (Integer -> Integer))
arising from a use of `print'
Possible fix:
add an instance declaration for (Show (Integer
-> Integer))
In a stmt of an interactive GHCi command: print
it
*Fact>
*Fact> :type fact
fact :: fact :: (Enum a, Num a) => a -> a
*Fact> :set +t
*Fact> fact 4
24
it :: Integer
*Fact> fact 100
9332621544394415268169923885626670049071596826438162
1468592963895217599993229915
6089414639761565182862536979208272237582511852109168
64000000000000000000000000
it :: Integer
*Fact> :edit Fact.hs
*Fact> :reload
*Fact> :type fact
fact :: Integer -> Integer
*Fact> fact 100
9332621544394415268169923885626670049...
Fact>
Fact> :q
Leaving GHCi
-----------------------------------------$ ghci Fact.hs
[...]
[1 of 1] Compiling Fact
( Fact.hs,
interpreted )
Ok, modules loaded: Fact.
*Fact> fact 8
40320

-----------------------------------------How do we get out of the interpreter again?


1. literate programs
-----------------------------------------LITERATE SCRIPTS
file Hello.lhs:
==============================
HELLO WORLD

let x = 3
y = 4
in x + y
==>
let {x = 3
;y = 4
}in x + y

This is the hello world program


> -- part of a Haskell prog
> main = putStrLn "Hello, world!"
The blank lines surrounding
the program are mandatory.

-----------------------------------------B. identifiers and operators (Thompson 1.7, Davie


2.14.2)
-----------------------------------------IDENTIFIERS (NOT INFIX)
can use letters, digits, primes and underscores (_)

This file should have a .lhs


suffix.
==============================
$ ghc Hello.lhs
[1 of 1] Compiling Main
Hello.o )
Linking Hello.exe ...
$ ./Hello
Hello, world!

Example:

CASE MATTERS
varids:
( Hello.lhs,

start with a-z


examples
_, pythag, fac, x, y', x3'n_, aGoodId

conids:
$ ghcii Hello.lhs
start with A-Z
...
Ok, modules loaded: Main.
Examples:
Prelude Main> :type main
Stack, Rational, Typ'_3
main :: IO ()
-----------------------------------------Prelude Main> main
OPERATORS
Hello, world!
Prelude Main> :quit
Examples:
-----------------------------------------+, -, !!, ++, ==, /=
III. lexical matters in Haskell (Thompson 3.7, Davie :, :#
2.14, appendix C.2-3)
A. important and unusual lexical conventions
Notes:
-----------------------------------------IMPORTANT AND UNUSUAL LEXICAL CONVENTIONS
1. Drawn from: !#$%&*+./<=>?@\^|-~:
and unicode symbols and punctuation
<varid> ::= <small> { <idchar> }
<conid> ::= <large> { <idchar> }
2. An operator is a constructor
<idchar> ::= <small> | <large> | <digit> | '
if it starts with :
<small> ::= <ascSmall> | _
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
3. All operators are infix
<large> ::= <ascLarge>
except unary negation (-)
<ascLarge> ::= A | B | C | D | ... | Z
<ascSmall> ::= a | b | c | d | ... | z
4. Any identifer can be made into
an infix operator using backquotes
- Case matters
3 `div` 4 or mod
identifiers: fact, x y
constructors: Rational, Stack
5. An infix operator can be used as
an identifier when put in parentheses
- Layout (white space) matters:
(if omit braces and semicolons,
(+) 3 4 == 3+4
following "where", "let", "do", and "of")
-----------------------------------------IV. Built-in types of Haskell
A. Fundamental classification of objects

1. simple (atomic) types (Thompson 3.1-2, 3.5-6,


Davie 2.7)
-----------------------------------------HASKELL BOOLEANS
data Bool = True/False ; where by default everything
is false if it is not found true, hence we must
always have an else statement after an if-then
statement
Bool
Values:
+ abstract values: true and false
+ printed: True, False
Operations:
+ constructors: True, False
+ functions: &&, ||, not, ==, /=
+ syntax: if _ then _ else _
HASKELL CHARACTERS
Char
Values:
+ abstract values: a, b, c, d, ...
+ printed: 'a', 'b', 'c', ...
Operations:
+ constructors: 'a', 'b', ...,
'\n', (toEnum 10), ...
+ functions: fromEnum, toEnum, ...
==, /=, <, <=, ...
----------------------------------------------------------------------------------HASKELL INTEGERS
static: before runtime i.e. haskell
dynamic: at runtime (in general) i.e. Java
Integer
Values:
+ abstract values: 0, 1, -1, ...
+ printed: 0, 1, -1, ...
Operations:
+ constructors: 0, 1, -1, 2, -2, 3, ...
+ functions: +, -, *, negate,
abs, signum,
quot, rem, div, mod,
==, /=, <, <=, ...
-----------------------------------------a. Type Classes in the Prelude
-----------------------------------------TYPE CLASSES IN THE PRELUDE
a collection of functions that apply to a certain
type
can define a function that will work (uniformly in
that TYPE CLASS)
Eq (==, /=)
Ord (compare, <, <=, >=, >, min, max)
subclass of Eq
Enum (succ, pred, toEnum, fromEnum,
enumFrom, enumFromThen, ...)
Used for mapping making data connected - because
haskell knows at compile time what the TYPE is (due
to pre-defining the TYPE)
Bounded (minBound, maxBound)
Read (readsPrec, readList)
Show (showsPrec, show, showList)

Num (+, -, *, negate, abs, signum, fromInteger)


Real (toRational)
Integral (quot, rem, div, mod, quotRem,
divMod, toInteger)
Fractional (/, recip, fromRational)
Floating (pi, exp, log, sqrt, **, logBase,
sin, cos, tan, asin, Double, ...)
RealFrac (properFraction, truncate, round,
ceiling, floor)
RealFloat (floatRadix, floatDigits, ...)
----------------------------------------------------------------------------------PRIMITIVE TYPES IN TYPE CLASSES
Bool is in Eq, Ord, Enum, Read, Show, Bounded
Char is in Eq, Ord, Enum, Bounded
Int is in Eq, Ord, Num, Real, Integral, Enum,
Bounded
Integer is in Eq, Ord, Num, Real, Integral, Enum
Float is in Eq, Ord, Num, Real, Fractional,
Floating,
RealFrac, RealFloat, Enum
Double is in Eq, Ord, Num, Real, Fractional,
Floating,
RealFrac, RealFloat, Enum
-----------------------------------------2. structured types (Thompson 5, Davie 2.8, 3.11,
2.10)
-----------------------------------------STRUCTURED TYPES
(a):: a b (a,b)
type
| constructors (or syntax)
==========================================
(a,b)
(_,_) (True,3)::(Bool,Integer)
(a,b,c)..
(_,_,_).. (a,3.14,False)::
(Char,Double,Bool)
()
() EMPTY TUPLE
[a]
[a]: 1:[] list containing [1]
(a,b)
(_,_) (True,3)::(Bool,Integer)
stack
user-defined
how to do this: data a = Empty 1 push a (Stack a)
-----------------------------------------a. pairs, tuples, and unit (Thompson 5.2, Davie
2.10)
-----------------------------------------TUPLES IN HASKELL
(a,b), (a,b,c), ..., and ()
Values:
+ abstract values: pairs of a & b,
triples of a & b & c, ...
an empty tuple
+ printed: (1,True), (3, 4, 5), ()
Operations:
+ constructor (,), (,,), ...
+ fst, snd
work on pairs (normally not used)
EXAMPLE FUNCTIONS OVER TUPLES
> fst :: (a,b) -> a
> fst (a,_) = a
pattern: declare variable a , where underlined

value doesnt matter - i.e. the compiler wont


care
> snd :: (a,b) -> b
> snd (_,b) = b

-----------------------------------------What's the general rule for this kind of pattern


matching?
-----------------------------------------PATTERNS IN FUNCTION DEFINITION

-----------------------------------------Why are single-element tuples like (3+4) not


in Haskell?
Suppose we define
-----------------------------------------CONSTRUCTING TUPLES
> yodaize (subject, verb, adjective) =
>
(adjective, subject, verb)
Examples:
(1,True)
Examples
(1,2,3)
Tuple
(1,(2,3))::(Integer,(Integer, Integer))
yodaize ("food", "is", "good")
(1,(True,2.8))
((1,True),2.8)
yodaize ("study", "you", "will")
()
("zero tuple:",())::([Char],())
Another example:
-----------------------------------------What is the type of each?
b. functions (Thompson 10)
-----------------------------------------FUNCTIONS
a -> b
Values:
+ abstract values:
partial functions from a to b
Operations:
+ constructor: \ var -> expression
+ syntax:
f x y = expression
means roughly
f = (\x -> (\y -> expession))
+ functions: (.), flip,
curry, uncurry
Examples:
id :: a -> a
id = \x -> x
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
-----------------------------------------B. binding, pattern matching, simple functions
-----------------------------------------PATTERN MATCHING AND BINDING
Examples:
let
let
let
let
let

(x,y,z) = (1,2,3) in x
(x,y,z) = (1,2,3) in z
(_,y,_) = (1,2,3) in y
(a:as) = 1:2:3:[] in a
(a:as) = [1,2,3] in as

Problem: write a function


max3 :: Ord a => (a, a, a) -> a
to take the maximum of 3 arguments
-----------------------------------------FOR YOU TO DO
1. Define functions
fst3 :: (a, b, c) -> a
snd3 :: (a, b, c) -> b
thd3 :: (a, b, c) -> c
such that for all t :: (a, b, c)
t = (fst3 t, snd3 t, thd3 t)
2. Define a function
average :: (Float, Float) -> Float
such that, for example
average (1.0, 3.0) = 2.0
average (3.0, 50.0) = 26.5
-----------------------------------------V. lists (Thompson 5, Davie 2.8, 3.11)
-----------------------------------------LISTS IN HASKELL
[a] -- homogeneous lists of a
Values:
+ abstract values: sequences of a's
+ printed: [], [True], [1,2,3,...]
Operations:
+ constructors: :, []
(:) :: a -> [a] -> [a]
[] :: [a]
+ functions: head, tail,
last, init, null, ++,
length, !!, map, take,

drop, reverse, all, any, ...


+ syntax:
[1,2,3] = 1:(2:(3:[])) = 1:2:3:[]
[1 ..] = enumFrom 1
[1,3 ..] = enumFromThen 1 3
[1 .. 8] = enumFromTo 1 10
[1,3 ..8] = enumFromThenTo 1 3 8
[e | e <- [1 ..], even e]
= do e <- [1 ..]
guard (even e)
return e
-----------------------------------------e.g. [Integer] is a list of integers
[String] is a list of strings, etc.
Note: String = [Char] lists are homogeneous, and
not necessarily finite.
-----------------------------------------PRAGMATICS OF LISTS
Lists are represented as Haskell terms
1:(2:(3:[]))
is
:
/ \
1
:
/ \
2 :
/ \
3
[]
Consequences:
- in pattern matching,
can only get at head and rest
let (a:as) = lst
- when building a list,
can only add elements at the head
0:lst
Pragmatics
- (:) executes in constant time and space
- pattern matching using (:) is fast
-----------------------------------------PRAGMATICS OF ++
++ concatenates lists
Definition:
(++) :: [a] -> [a] -> [a]
[] ++ bs = bs
(a:as) ++ bs = a:(as ++ bs)
Time is
Space is
-----------------------------------------which is more efficient: 0:[1,2,3] or [0]+
+[1,2,3]?

A. Haskell list features as a DSL


1. sugars
-----------------------------------------LIST SUGARS
data [] a = [] | a : [a]

.. SUGARS FOR INFINITE LISTS


[n ..] = [n,n+1,n+2,...
Note: Haskell will keep evaluating the list forever
until you interrupt it using Ctrl-C

[1] desugars to 1:[]

[n, p ..] = [n, p, p+(p-n), p+2(p-n),...

[1,2] desugars to 1:2:[]

-----------------------------------------c. list comprehensions


i. mapping
-----------------------------------------MAPPING WITH LIST COMPREHENSIONS

Note: lists are NOT sets:


can have repeats [1,2,1,3]
order matters [1,1,2,3] /= [1,2,1,3]
-----------------------------------------What does [4,0,2,0] desugar to? 4:0:2:0:[]
a. dot dot (..) notation
-----------------------------------------.. SUGARS IN HASKELL
1:[] = [1]
1:2:[] = (1:(2:[])) = 1:[2] = [1,2]
[1,2,1,3] can have repeats
[1,1,2,3] order matters
[n .. m] = [n, n+1, n+2, ..., m] if n <= m
[]
otherwise
e.g., [3 .. 7] = [3, 4, 5, 6, 7]
[3 .. 3] = [3]
[3 .. 2] = []
[n, p .. m] = [n, n + (p-n), ..., m]
e.g., [3, 5
[3, 5
[5, 3
['a',
[2, 2

.. 11] = [3, 5, 7, 9, 11]


.. 12] = [3, 5, 7, 9, 11]
.. 0] = [5, 3, 1]
'b' .. 'e'] = "abcde"
.. 2] = [2,2,2,2,2, ...]

As with sets in math: {2*n | n <- ex}


> ex = [2, 4, 7, 3, 2]
> integers = [ 1 .. ]
[ 2 * n | n <- ex]
= [2,8,14,6,4]
Write:
product_by:: [Int] -> Int -> [Int]
map :: (a -> b) -> [a] -> [b]
using list comprehensions
product_by :: [Int] -> Int -> [Int]
product_by [] _ = []
product_by x a = [ y*a | y <- x]
--RECURSIVE SOLUTION
--product_by x a = map (*a) x
-----------------------------------------iii. using patterns
-----------------------------------------USING PATTERNS

Write
The general rule (Report, section 3.10) is that
addPairs :: [(Integer, Integer)] -> [Integer]
[e1,e2 .. e3] gives a list of values starting at e1,
which takes a list of pairs
with increment e2-e1 of values not greater than e3
and produces a list of their sums
(assuming e2-e1 is positive)
addPairs[(3,4),(0,5)] == [7,5]
addPairs lst = [i+j | (i,j) lst]
for infinite lists
addPairs :: [(Integer,Integer)] -> [Integer]
[n ..] = [n, n+1, n+2, ...]
addPairs x = [ fst n + snd n | n<-x ]
e.g., [1 .. ] = [1, 2, 3, 4, ...]
-----------------------------------------[7 .. ] = [7, 8, ...]
iv. nested maps
-----------------------------------------[n, p ..] = [n, n + (p-n), ...]
NESTED MAPS
e.g., [2, 4 ..] = [2, 4, 6, 8, ...]
[(a,b) | a <- ex, b <- [1,2]] =
[n .. m] = [n,n+1,n+2,...,m-1,m]
[(2,1), (2,2), (4,1), (4,2), (7,1), (7,2),
(3,1), (3,2), (2,1), (2,2)]
[n, p .. m] = [n, p, p+(p-n), p+2(p-n),...]
last element is less than or equal to m:
-----------------------------------------observe:
2. built-in functions, standard Prelude (go quickly
[1,2..10] -> [1,3,5,7,9]
or skip)
[0,2..10] -> [0,2,4,6,8,10]
a. zip and unzip
b. ++, !!, concat, length, head, last, tail, init
-----------------------------------------c. take, drop
b. .. for infinite lists!
B. explicit recursions.
-----------------------------------------------------------------------------------

STEPS FOR WRITING EXPLICIT RECURSIONS


1.
a.
b.
c.
d.

Understand the problem


What does it do?
What's the type?
What are the grammars for the arguments?
What are examples for each case
in the interesting grammars?
e. What are related simpler examples?
2. Write an outline that follows the grammar
3. Fill in the outline using the examples
- generalize from the examples
- create new examples if needed
4. Use one function per nonterminal
5. Debug by testing larger and
larger expressions
-----------------------------------------1. more practice
2. recursion over flat lists
-----------------------------------------RECURSION OVER FLAT LISTS

length:: [a] Int


length [] == 0
length [3,4,5] == 3
length (x:xs) = 1 + (length xs)
Write a function
all :: (a -> Bool) -> [a] -> Bool
so that:
all even [] = True
all even [1,2,3] = False
all odd [5,3,1,1,7,13] = True
all' :: (a -> Bool) -> [a] -> Bool
all' _ [] = True
all' f (x:xs) = f x && all' f xs

base case: all pred [] = True


rec case : all pred (x:xs) = (pred x) && all pred xs
OR, for the sugared syntax
all pred lst = case lst of
[] True
(x:xs) (pred x) && all pred xs
-----------------------------------------what is the base case?
insertWhen :: (a -> Bool) -> a -> [a] -> [a]
take the above example for the inductive case.
insertWhen _ _ [] = []
what do we want? what are we given? how do you
insertWhen f a (x:xs) = if f x
get that?
then a:x:insertWhen f a xs so what are the equations?
else x:insertWhen f a xs
C. tail recursion: no pending computation on
Example:
recursive calls (Davie 3.9)
predicate , elem to insert, list
1. example
insertWhen :: (a -> Bool) -> a -> [a] -> [a]
-----------------------------------------such that
FULL vs. TAIL RECURSION
(insertWhen (== "Fred") "Mr."
Full Recursion: A recursive approach where
["Robin","Redbreast","Fred","Follies"])
calculations are done after every recursive call is
== ["
done.
Robin","Redbreast","Mr.","Fred","Follies"]
(insertWhen (== "Victoria") "Queen"
Tail Recursion: A recursive approach where
["Victoria","Victoria","Station"])
calculations are before every recursive call is
==
done; such approaches use an accumulator to keep
["Queen","Victoria","Queen","Victoria","Station"]
track of a value being manipulated. This approach is
(insertWhen (== "Victoria") "Queen" []) == []
also known as an iterative approach.
-----------------------------------------So what will the cases be?
how do we get
Fully recursive
"Queen":"Victoria":"Queen":"Victoria":"Station":[]
+ 1 is a pending computation; waits to add 1
from
until the end of the call uses up stack space
"Queen":"Victoria":"Station":[]?
> len [] = 0
3. practice
> len (x:xs) = 1 + (len xs)
---------------------------------------------------STACK SIZE------------->
FOR YOU TO DO
len [5,7,9] == 1 + (len [7,9])
Write a function
x:xs
== 1 + (1 + (len [9]))
(++) :: [a] -> [a] -> [a]
|
== 1 + (1 + (1 + (len [])))
so that:
|
== 1 + (1 + (1 + (0)))
[1,2,3] ++ [4,5] == [1,2,3,4,5]
time |
== 1 + 1 + 1
[] ++ [7,8] == [7,8]
V
== 1 + 2
I used blob in place of (++)
== 3
blob :: [a] -> [a] -> [a]
-----------------------------------------blob a [] = a
-----------------------------------------blob [] a = a
WRITING TAIL RECURSIONS
blob a b = blob (init a) ((last a):b)

1. Make a helping function with an extra argument


an accumulator (maybe not
2. Using examples, draw a table
for how you want the arguments to vary
3. Generalize from examples
----------------------------------------------------------------------------------TAIL RECURSION
def: code for a function f is *tail recursive*
(or *iterative*)
if on each branch, the last action is the
recursive call.
def: a *pending computation* is a computation that
requires waiting on one of its operands to be
evaluated before operating on it.
-----------------------------------------2. practice
-----------------------------------------FOR YOU TO DO
reverse([1,2,3]) =
=
=
=
=
Write

reverse_iter([1,2,3], [])
reverse_iter([2,3], [1])
reverse_iter([3], [2,1])
reverse_iter([], [3,2,1])
[3,2,1]

> reverse :: [a] -> [a]


> reverse [] = []
> reverse (x:xs) = (reverse xs) ++ [x]
tail recursively.
reverse' :: [a] -> [a]
reverse' a = reverseIter a []
reverseIter :: [a] -> [a] -> [a]
reverseIter [] a = a
reverseIter (x:xs) a = reverseIter xs (x:a)
-----------------------------------------so what is reverse_iter(x:xs,y)?
reverse_iter(xs,x:y)
3. when to use tail recursion
-----------------------------------------WHEN TO USE TAIL RECURSION
When you want to minimize your stack of recursive
function calls. See Last Call Optimization.
when manipulating random-access collections (arrays)
when you need an index (a for loop)
if you want to return without going through
recursions
> index_of :: Eq a => a -> [a] -> Integer
> index_of x ys = index_iter ys 0
>
where index_iter [] i = -1
>
index_iter (y:ys) i
>
| x == y
= i
>
| otherwise = index_iter ys(i+1)

-----------------------------------------|
|
What are some examples we have seen of need
|\\\\\\\\\\\\\\\\\\\\\\\\\ <____
to use tail recursion?
SP (stack pointer)
D. memory management
1. overall memory layout
How do we represent the environment and the
--------------------store in a single
does saved part save information about caller
address space on a conventional computer?
or callee?
-----------------------------------------How would this be used in making a call?
How would this be used in a return?
3. Last call optimization
OVERALL MEMORY LAYOUT
-----------------------------------------LAST CALL OPTIMIZATION
|---------------|
Scheme first language to take advantage of this
|
Code
|
feature.
|---------------|
def: a language implements the
| Static Data
|
*last call optimization* if
| (constants)
|
it reuses the current AR for the last
|---------------|
call made during a function's execution.
| run-time
|
~ Environment
| stack of ARs |
length' ls = length'iter ls 0
|
|
length'iter [] acc = acc
|
|
|
length'iter (_:xs) acc = length'iter xs (acc+1)
|
v
|
\\\\\\\\\\\\\\\\|
Tracing this:
|\\\\\\\\\\\\\\\|
|
(heap)
|
|---------------|

~ Store

-----------------------------------------2. activation records (stack organization)


Why is an activation record needed for every
*call* of a procedure,
instead of one for each procedure?
How to access the values of local identifiers in
the environment?
--------------------Aho and Ullman's design for Activation Record (using
static links):
__________________________
RET: |
returned value
|
|
(for functions)
|
|________________________|
PAR: |
|
|
actual parameters
|
|
|
|________________________|
| DL: |
dynamic link
|
|
|________________________|
|
SL: |
static link
|
fixed |
|
(or display)
|
size
|
|________________________|
fields |
IP: |
saved machine status |
<_________ EP (env pointer)
|
| (ip and other regs) |
|________________________|
VAR: |
local data
|
| (storage for vars) |
|________________________|
|
|
TEMP:|
temporaries
|

length' 1:2:3:[]
= length'iter (1:2:3:[]) 0
length' :: [a] -> Int
length' ls = length'iter ls 0
length'iter :: [a] -> Int -> Int
length'iter [] acc = acc
length'iter (_:xs) acc = length'iter xs (acc+1)
-----------------------------------------What is it useful for?
Does the semantics already to this?
Do C, C++, and Java require this optimization?
Not sure but involves the JIT = Just-In-Time feature
What does that say about using recursion in these
languages?
VI. data-driven recursion (Thompson 14, Davie
sections 3.2, 4.4)
A. data declaration in Haskell
1. example: the natural numbers
-----------------------------------------DATA-DRIVEN RECURSION or
FOLLOW THE GRAMMAR!
Definition of natural numbers:
> data Nat = Zero | Succ Nat deriving Eq
To define a function f :: Nat -> t
define recursively by:
f Zero =
...
-- basis
f (Succ n) = ... -- inductive case

Examples:
> toInteger :: Nat -> Integer
toInteger (Succ (Succ Zero)) == 2
toInteger (Succ Zero) == 1
toInteger Zero == 0
> plus :: Nat -> Nat -> Nat
plus
plus
plus
==

Zero (Succ Zero) == Succ Zero


(Succ Zero) (Succ Zero) == (Succ (Succ Zero))
(Succ (Succ (Succ Zero))) (Succ (Succ Zero))
(Succ (Succ (Succ (Succ (Succ Zero)))))

Anda mungkin juga menyukai