Class 20 Announcements/info Reason review, clarifications - - PowerPoint PPT Presentation

class 20
SMART_READER_LITE
LIVE PREVIEW

Class 20 Announcements/info Reason review, clarifications - - PowerPoint PPT Presentation

Class 20 Announcements/info Reason review, clarifications Dictionaries Variant Types Options Show of hands: how many are still having trouble with installing VSCode for reason? Preferred type-annotation for functions: let f : (int


slide-1
SLIDE 1

Class 20

Announcements/info Reason review, clarifications Dictionaries Variant Types Options

slide-2
SLIDE 2
  • Show of hands: how many are still having trouble with

installing VSCode for reason?

  • Preferred type-annotation for functions:
  • let f : (int => string) = …
slide-3
SLIDE 3
  • Reason so far:
  • Basic types: int, float, string, bool, list(int), list('a), function

types, …

  • Builtins: familiar by now
  • "let" instead of (define…); each "let" opens a new

environment.

  • Type-ascription: (x:int) means "x is an expression whose value

has type int"

slide-4
SLIDE 4

A few more things about reason

  • Modules
  • Complex assignments/matching
  • Blocks
slide-5
SLIDE 5

A first look at modules

  • We can collect multiple functions into a module (we can put types and

values in there too; more later)

  • Module names start with a capital letter
  • All the functions in Tank.re become part of the "Tank" module.
  • So you've been defining modules all along without knowing it!
  • To refer to a function – say, "testFull" in the Tank module, you write

Tank.testFull(…)

and Reason finds the relevant file, and uses the definition found there.

  • You've already done this with List.rev
  • Alternative: if you're going to be using "Tank" functions a lot, you can

say

  • pen Tank;

testFull(…)

so that you no longer need to use the "Tank" prefix.

slide-6
SLIDE 6

Assignment

  • You've seen

let a = 4;

  • You can also use (in assignments or in "switch" expressions)

let (a, b) = (2, 4);

  • … to assign both parts at once
  • If you want to ignore one of them, you can say

let (_, b) = (2, 4);

  • Works in general. You can also write

let [hd, ...tl] = [1, 4, 5, 6]; to get hd -> 1, tl -> [4, 5, 6];

slide-7
SLIDE 7

Type definitions

  • Sometimes you keep using a type over and over. You can name new

types! type ibpair = (int, bool); type bignum = list(int);

  • You can even make new types that allow multiple possibilities,

similar to list('a): type pair('a, 'b) = ('a, 'b); type ibpair = pair(int, bool); type matrix('a) = list(list('a));

slide-8
SLIDE 8

Type definition limitations

  • Some type definitions, like "matrix", don't include necessary

information, like "I only want nonempty lists, and the inner lists should be nonempty, too"

  • A perfect place to add this is at the top of the design recipe,

in the data definition (just as you add constraints on values in the I/O specification: "myCount, a positive integer"

slide-9
SLIDE 9

let expressions

  • Racket:

(let ((x 5) (y 2)) (+ x y)) => 7

  • Reason

{ let x = 5; let y = 2; x + y }; [result: the integer 7] x; [result: Unbound value x]

slide-10
SLIDE 10

Block expressions

  • The block itself has a value, the value of the last item in the

block

  • It defines a "local environment", in which bindings are made

temporarily and then forgotten. let k = {let x = 5; let y = 2; x + y};

  • k ends up bound to 7; x and y are undefined.
  • Perfect application: helper functions!
slide-11
SLIDE 11

Helpers inside blocks

type bignum = list(int); let bnAdd: (bignum, bignum) => bignum = (a, b) => { let bnAddHelper: … = … ; bnAddHelper(a, b, 0) };

slide-12
SLIDE 12

Helpers inside blocks

type bignum = list(int); let bnAdd: (bignum, bignum) => bignum = (a, b) => { let bnAddHelper: … = … ; bnAddHelper(a, b, 0) };

slide-13
SLIDE 13

Quiz: Fast-reverse

/* reverse the first list, and append to it the second */ let rec revHelper: (list('a), list('a)) => list('a) = (lst, rest) => switch(lst){ | [] => rest | [hd, ...tl] => revHelper(tl, [hd, ...rest]) }; let rev: list('a) => list('a) = lst => revHelper(lst,[]);

Quiz: rewrite let rev … using a block to "hide" revHelper. You don't need to copy any of the green stuff – just write "…"

slide-14
SLIDE 14

"Or" types

  • Mechanism for saying something can be this or that

type season = Fall | Winter | Spring | Summer let averageTemp: season => int = fun | Fall => 52 | Winter => 30 | Spring => 45 | Summer => 80;

  • The "season" type has only four possible values, just as "bool" has
  • nly two.
  • The "constructors" must start with capital letters.
slide-15
SLIDE 15

Fancier Or types

  • Constructors can include some data

type news = Alert(string) | Normal(string); type myIntList = Empty | Cons (int, myIntList);

  • The kind of data can be a parameter!

type myList('a) = Empty | Cons ('a, myList('a));

slide-16
SLIDE 16

A simple dictionary “data structure”: a list of pairs.

let myDict = [(“I”, “je”); (“you”, ”tu”); (“dog”, “chien”); … ] : list(string*string) better: type dict = list(string * string); let myDict = [(“I”, “je”); (“you”, ”tu”); (“dog”, “chien”); … ] :dict;

let rec lookup: (string, dict) => string = (term, dictionary) => switch(dictionary) { | [] -> ???; | [(k, v), ... tl] -> if (term == k) then v else lookup(term, tail) };

slide-17
SLIDE 17

Using a dictionary

type dict = list(string * string); let myDict = [(“I”, “je”); (“you”, ”tu”); (“dog”, “chien”); … ] :dict;

let rec lookup: (string, dict) => string = (term, dictionary) => switch(dictionary) { | [] -> ???; | [(k, v), ... tl] -> if (term == k) then v else lookup(term, tail) };

slide-18
SLIDE 18

A builtin type for handling success/failure cases!

type option('a) = Some('a ) | None

  • Intended use:
  • “None” means something like “I didn’t find an answer” or “your item

isn’t in the data”, etc.

  • “Some(x)” means “I found an answer, and it was x”
  • Requires new type-signature for most functions

f: int => int becomes f: int => int option

For recursive procs, adds slight complexity

slide-19
SLIDE 19

Small example

let rec lookup: (string, dict) => string = (term, dictionary) => switch(dictionary) { | [] -> None; | [(k, v), ... tl] -> if (term == k) then Some(v) else lookup(term, tail) };

slide-20
SLIDE 20

Annoyance

  • When you look up "dog", you get

Some("chien") not "chien"

slide-21
SLIDE 21

“Sum up all ints in a list except 1s; if empty or nothing but 1s, return None”

slide-22
SLIDE 22

let rec sumButOnes:(list(int) => option(int)) = fun | [] => None | [1, ...tl] => sumButOnes(tl) | [hd, ...tl] => switch (sumButOnes(tl)) { | None => Some(hd) | Some(s) > Some(hd + s) };