CSE30511.pptx

advertisement
CSE305: Data Types
Lukasz Ziarek
lziarek@buffalo.edu
Announcements
• No recitations next week
• Instead we will hold office hours during
recitation times in case you have any questions
prior to the midterm
• Request for note takers still open
• Study guide to be released on Thursday
• Sample questions on Friday and likely more over the
weekend as well
Compile-Time Descriptors
Single-dimensioned array
Multidimensional array
3
Array Representation for
Predictability
• Just like with large strings, we may need to break
up arrays into chunks
• Use a layered structure (arraylettes)
spine
content
content
content
4
content
Associative Arrays
•
•
•
An associative array is an unordered collection of data
elements that are indexed by an equal number of
values called keys
•
User-defined keys must be stored
Design issues:
•
What is the form of references to elements?
•
Is the size static or dynamic?
Built-in type in Perl, Python, Ruby, and Lua
•
In Lua, they are supported by tables
5
Associative Arrays in Perl
• Names begin with %; literals are delimited by
parentheses
•
%hi_temps = ("Mon" => 77, "Tue" => 79, "Wed"
=> 65, …);
• Subscripting is done using braces and keys
•
$hi_temps{"Wed"} = 83;
•
Elements can be removed with delete
•
delete $hi_temps{"Tue"};
6
Record Types
• A record is a possibly heterogeneous aggregate of
data elements in which the individual elements are
identified by names
• Design issues:
• What is the syntactic form of references to the
field?
• Are elliptical references allowed?
7
Records in ML
• record expressions are of the form {x1=e1,...,xn=en}
where the identifiers x are labels
val x = {first = "John", last = "Doe",
age = 65, balance = 0.12}
• # and the label act as the selector (index)
val y = #first x
8
Evaluation and Comparison to
Arrays
• Records are used when collection of data values is
heterogeneous
• Static subscripts, ordering does not matter
• Dynamic subscripts could be used with record field
access, but it would disallow type checking and it
would be much slower
9
Implementation of Record Type
Offset address relative to the
beginning of the records is
associated with each field
10
Tuple Types
• A tuple is a data type that is similar to a record, except that
the elements are not named
• Used in Python, ML, and F# to allow functions to return
multiple values
• Python
• Closely related to its lists, but immutable
• Create with a tuple literal
myTuple = (3, 5.8, ′apple′)
Referenced with subscripts (begin at 1)
• Catenation with + and deleted with del
11
Tuple Types (continued)
ML
val myTuple = (3, 5.8, ′apple′);
- Access as follows:
#1(myTuple) is the first element
- A new tuple type can be defined
type intReal = int * real;
F#
let tup = (3, 5, 7)
let a, b, c = tup This assigns a tuple to a
tuple pattern (a, b, c)
12
Why are tuples important?
• Provide a mechanism for heterogeneous data
storage
• Usually immutable
• Combined with pattern matching, provide a clean
mechanism for defining functions
13
Functions and Tuples in SML
• Functions take only ONE argument in SML
• … but wait, what is this then?
fun max(r1, r2)=
if r1 < r2
then r2
else r1
14
Functions and Tuples in SML
• Lets break the function down to its more basic form
fun max(r1, r2)=
if r1 < r2
then r2
else r1
fun max tuple =
let val (r1, r2) = tuple
in if r1 < r2
then r2
else r1
end
15
Functions and Tuples in SML
• This means I can use max in two ways
val max = fn : int * int -> int
- val b = (1,2);
val b = (1,2) : int * int
- max b;
val it = 2 : int
- max (1,2);
val it = 2 : int
16
A few common errors explained
- fun f(x) = print(Int.toString(x));
val f = fn : int -> unit
- fun g(x) = x+1;
val g = fn : int -> int
- f g(1);
Error: operator and operand don't agree
operator domain: int
operand:
int -> int
in expression:
f g
A few common errors explained
• What is the meaning of “f g(1);”
• This is actually an expression of the form:
<expr> <expr> <expr>
f
g
(1)
• Order of evaluation is left to right and <expr>
<expr> if function application
• Thus we evaluate f g
A few common errors explained
• What happens if we evaluate f g?
operator domain: int
operand:
int -> int
in expression:
fg
fun f(x) = print(Int.toString(x));
fun g(x) = x+1;
f expects an int
g is a function
A few common errors explained
• What is the meaning of “f (g(1));”
• This is actually an expression of the form:
<expr> (<expr> <expr>)
f
(g
(1))
• Order of evaluation is left to right and <expr> <expr> if
function application
• Thus we evaluate <expr> applied to (<expr> <expr>)
• To do this we must first simplify to (<expr> <expr>)
Putting it all together
• Having tuples as primitives allows for a simple
grammar definition for function application
• Functions take one argument return one result
• Tuples give the illusion of multi argument
functions
• Parenthesis specify order of evaluation on NOT
syntactic forms
f(g 1)
f(g(1))
List Types
• Lists in Lisp and Scheme are delimited by
parentheses and use no commas
(A B C D) and (A (B C) D)
• Data and code have the same form
• As data, (A B C) is a list
• As code, (A B C) is the function A applied to the
parameters B and C
• The interpreter needs to distinguish, so if it is data,
we quote it with an apostrophe
′(A B C) is data
22
List Types
(continued)
List Operations in Scheme
• CAR returns the first element of its list parameter
(CAR ′(A B C)) returns A
• CDR returns the remainder of its list parameter after the
first element has been removed
(CDR ′(A B C)) returns (B C)
- CONS puts its first parameter into its second parameter,
a list, to make a new list
(CONS ′A ′(B C)) returns (A B C)
- LIST returns a new list of its parameters
(LIST ′A ′B ′(C D)) returns (A B (C D))
23
List Types
(continued)
List Operations in ML
• Lists are written in brackets and the elements
are separated by commas
• List elements must be of the same type
• The Scheme CONS function is a binary operator
in ML, ::
3 :: [5, 7, 9] evaluates to [3, 5, 7, 9]
• The Scheme CAR and CDR functions are named
hd and tl, respectively
24
List Types
(continued)
F# Lists
• Like those of ML, except elements are separated by
semicolons and hd and tl are methods of the List
class
Python Lists
• The list data type also serves as Python’s arrays
• Unlike Scheme, Common Lisp, ML, and F#, Python’s
lists are mutable
• Elements can be of any type
• Create a list with an assignment
myList = [3, 5.8, "grape"]
25
List Types
(continued)
Python Lists (continued)
• List elements are referenced with subscripting,
with indices beginning at zero
x = myList[1] Sets x to 2nd element of myList
• List elements can be deleted with del
del myList[1]
•
List Comprehensions – derived from set notation
[x * x for x in range(6) if x % 3 == 0]
range(12) creates [0, 1, 2, 3, 4, 5, 6]
Constructed list: [0, 9, 36]
26
List Types
(continued)
• Haskell’s List Comprehensions
• The original
[n * n | n <- [1..10]]
• F#’s List Comprehensions
let myArray = [|for i in 1 .. 5 -> [i * i] |]
• Both C# and Java supports lists through their
generic heap-dynamic collection classes, List
and ArrayList, respectively
27
Using a list as a stack
exception stackError
fun push(x, xs) = x::xs
fun pop(x::xs) = xs
| pop([]) = raise stackError
val push = fn : 'a * 'a list -> 'a list
val pop = fn : 'a list -> 'a list
Fold Left and Fold Right
• The fold functions provide an abstract mechanism to
traverse a structure (lists and sometimes arrays) and
generate an accumulator during the course of the
traversal
• Two forms, left and right, dictate the order of the
traversal
• Thus they also dictate the order of the
accumulation
29
Fold Left and Fold Right
• Fold takes conceptually three arguments
• A list over which we will fold (traverse)
• An initial value for an accumulator
• A function which given a pair (list element and
accumulator) produces a new accumulator
30
Fold Left and Fold Right
• Assume we call foldl on a list [1,2,3,4,5] with an
initial accumulator (z) and a function f
31
Fold Left and Fold Right
• Assume we call foldr on a list [1,2,3,4,5] with an
initial accumulator (z) and a function f
32
Implementation of foldl
Type of foldl :('a*'b->'b)->'b->'a list->'b
fun foldl (f:'a*'b->'b)(acc: 'b)(l:'a list):'b =
case l of
[] => acc
| x::xs => foldl f (f(x,acc)) xs
Call fold
recursively
Apply f on x and the accumulator
33
Implementation of foldr
Type of foldr :('a*'b->'b)->'b->'a list->'b
fun foldr (f:'a*'b->'b) (acc:'b) (l:'a list):'b =
case l of
[] => acc
| x::xs => f(x, (foldr f acc xs))
Apply f on x and the accumulator
O get from recursive calls
Recursive calls that build
up the accumulator
34
What can I do with foldl/r?
fun
fun
fun
fun
length l = foldl (fn (_,a) => a+1) 0 l
rev l = foldl List.:: [] l
map f l = foldr (fn (x,a) => (f x)::a) [] l
filter f l = foldr (fn(x,a) =>
if f x then x::a else a) [] l
Download