teachscheme, reachjava adelphi university tuesday afternoon june 23, 2009

58
TeachScheme, ReachJava Adelphi University Tuesday afternoon June 23, 2009

Upload: corey-nelson

Post on 24-Dec-2015

217 views

Category:

Documents


2 download

TRANSCRIPT

TeachScheme, ReachJava

Adelphi University

Tuesday afternoon

June 23, 2009

Defining our own structs

1) Choose a name for the new data type2) Choose names and types for each of its parts3) Write a define-struct (next slide) to tell

Scheme about it4) Write contracts for the constructor and accessor

methods5) Write examples of the new data type6) Write a function template for the new data type7) Start writing functions on the new data type

Syntax Rule: Defining a Struct

To define a structure named foo with fields snark and boojum,

(define-struct foo (snark boojum))

This defines a new data type foo and several functions:

; make-foo : snark-type boojum-type -> foo

; foo-snark : foo -> snark-type

; foo-boojum : foo -> boojum-type

; foo? : anything -> boolean

Example: posn (if it weren't pre-defined)

; A posn consists of two numbers (x and y)

(define-struct posn (x y))

; make-posn : number number -> posn; posn-x : posn -> number; posn-y : posn -> number; posn? : anything -> boolean

"Examples of the posn data type:"(make-posn 3 5)(make-posn 12 -7)(define here (make-posn 14 9))(check-expect (posn-x here) 14)(check-expect (posn-y here) 9)

Real example: dogs

; A dog has a string(name), number(age), number(weight), and a boolean(asleep?)

(define-struct dog (name age weight asleep?))

; make-dog : string num num boolean -> dog; dog-name : dog -> string; dog-age : dog -> number; dog-weight : dog -> number; dog-asleep? : dog -> boolean

Real example: dogs

"Examples of the dog data type:"(make-dog "Ludo" 6 78 true)(make-dog "Thibaut" 4 74 false)

(define this-dog (make-dog "Rover" 8 45 false))

(check-expect (dog-name this-dog) "Rover")(check-expect (dog-age this-dog) 8)(check-expect (dog-weight this-dog) 45)(check-expect (dog-asleep? this-dog) false)

Type-based coding patterns

Almost any function that takes in a dog looks like

(define (function-on-dog the-dog)

)

(the "skeleton" step of the recipe)

Type-based coding patterns

Almost any function that takes in a dog looks like

(define (function-on-dog the-dog)

; the-dog a dog

)

(the "inventory" step of the recipe)

Type-based coding patterns

Almost any function that takes in a dog looks like

(define (function-on-dog the-dog)

; the-dog a dog

; (dog-name the-dog) a string

; (dog-age the-dog) a number

; (dog-weight the-dog) a number

; (dog-asleep? the-dog) a boolean

)

(the "inventory" step of the recipe, continued)

Type-based coding patterns

#|(define (function-on-dog the-dog) ; the-dog a dog ; (dog-name the-dog) a string ; (dog-age the-dog) a number ; (dog-weight the-dog) a number ; (dog-asleep? the-dog) a boolean )|#This header-plus-inventory, commented out, can be used as a template,

copying and pasting it as a starting point for any function that takes in a dog.

A function on dogs

Write a function fits-in-lap? which takes in a dog and the weight capacity of a lap, and tells whether the dog will fit in the lap in question

Work this out together

Your turn

Write a function movable? which takes in a dog. If the dog is awake, it's movable. If the dog is asleep but under 20 pounds, it's movable. Otherwise it's not. (Hint: it's shorter and simpler if you don't use a cond.)

Write a function birthday which takes in a dog and returns a dog with the same name, weight, and sleep status, but one year older.

Inventors and Factories

define-struct is like an inventor.Specifies once what's in a particular model of cell phone, but doesn't actually manufacture them. Then invents something else, and doesn't manufacture them either….

make-posn is like a cell-phone factory.Each factory "knows" how to build one kind of thing (cell phones, posns, dogs, etc.)Factory doesn't exist until the thing is invented.Can be used over and over to build many cell-phones/posns/dogs/whatever.

Defining another animalDefine a data structure fish which has a string(color), a

number(weight) and a boolean(salt-water?).

Remember the steps:

1) Choose a name for the new data type 2) Choose names and types for each of its parts 3) Write a define-struct to tell Scheme about it

4) Write contracts for the constructor and accessor methods

5) Write examples of the new data type

6) Write a function template for the new data type

7) Start writing functions on the new data type

Definition by choicesNew data type: animal

; An animal is either a dog or a fish.

Scheme doesn't enforce this; it's up to the programmer.

A function on animals

Write a function fits-in-crate? which takes in an animal (either a dog or a fish) and the weight capacity of a crate, and tells whether the animal can be shipped in that crate.

Hint: fish are never shipped in crates, regardless of weight.

How to write this?

The input type, animal, is one of two sub-categories (dog or fish), so…

• we need at least two test cases, one of each type (in fact, we'll need three dogs — under, over, and borderline — and at least one fish)

• the function body will probably be a cond with two cases, with questions "dog?" and "fish?"

Function template for animalsAlmost any function on animals will look like(define (function-on-animal the-animal)

)

Function template for animalsAlmost any function on animals will look like(define (function-on-animal the-animal) (cond [(dog? the-animal)

] [(fish? the-animal)

]))

Function template for animalsAlmost any function on animals will look like(define (function-on-animal the-animal) (cond [(dog? the-animal) ; the-animal a dog

] [(fish? the-animal) ; the-animal a fish

]))

Function template for animals#|(define (function-on-animal the-animal) (cond [(dog? the-animal) ; the-animal a dog ; (dog-name the-animal) a string ; (dog-age the-animal) a number ; (dog-weight the-animal) a number ; (dog-asleep? the-animal) a boolean ] [(fish? the-animal) ; the-animal a fish ; (fish-color the-animal) a string ; (fish-weight the-animal) a number ; (fish-salt-water? the-animal) a boolean ]))|#

Function template for animalsAgain, we can copy and paste this as a starting point

for any function on animals.In practice, much of it is irrelevant to any given

function, so we can delete those lines.

My answer to fits-in-crate?; fits-in-crate? : animal number -> boolean(define (fits-in-crate? the-animal max-weight) ; max-weight a number (cond [(dog? the-animal) ; (dog-weight the-animal) a number (<= (dog-weight the-animal) max-weight) ] [(fish? the-animal) false ]))"Examples of fits-in-crate?:"(check-expect (fits-in-crate? (make-dog "Bob" 3 58 true) 50) false)(check-expect (fits-in-crate? (make-dog "Dave" 2 65 true) 65) true) ; borderline(check-expect (fits-in-crate? (make-dog "Eddie" 7 35 false) 50) true)(check-expect (fits-in-crate? (make-fish "orange" 0.03 false) 5) false)

Another exerciseWrite a function underweight? which takes in an animal and

tells whether or not it's underweight — which means under 30 pounds for a dog, and under 0.1 pounds for a fish.

Lab exercise

• Open shapes-lab.scm (in Examples folder)• Do the exercises in it

Review: kinds of data types

Primitive data types

number, string, boolean, image, …

Types defined by their parts

posn, dog, fish, circle, rectangle, …

Types defined as one of several choices

subranges of numbers, animal, shape, …

Review: definition by parts; A fish has a string(color), number(weight), and boolean(salt-

water?)(define-struct fish (color weight salt-water?)); constructor, getters, and discriminator defined automagically

Testing pattern:call (make-fish …) to create as many instances as necessary

Coding pattern: (define (function-on-fish the-fish) ; the-fish fish ; (fish-color the-fish) string ; (fish-weight the-fish) number ; (fish-salt-water? the-fish) boolean )

Review: definition by choices; An animal is either a dog, a fish, or a wombatNot enforced by language; programmer conventionTesting pattern:

at least one example for each choiceCoding pattern:

(define (function-on-animal the-animal) (cond [(dog? the-animal)

; the-animal a dog ] [(fish? the-animal)

; the-animal a fish ]

[(wombat? the-animal) ; the-animal a wombat ]))

Just to make sure…

… please take some time to work the shapes-lab exercises.

When are you defining a type by parts?When are you defining a type by choices?How do you write a function on a type defined by parts?How do you write a function on a type defined by choices?

New topic: lists

What is a list?Examples:

shopping listlist of students in classlist of animals in zoo

Properties:can hold many objects, or one, or even nonenumber of objects may not be known in advanceobjects are in one-after-another sequence

So what is a list?

• A list is either empty or not.Definition by choices: empty or not?

• If it's not empty, that means it has at least one thing in it, so there's a "first" thing. There's also "the rest" of the list, which might or might not be empty…. i.e. a listDefinition by parts: first and rest.

One way to define lists; A list is either empty or non-empty.; Definition by choices:(define (function-on-list the-list)

(cons [(empty? the-list) ; the-list an empty list

] [(non-empty? the-list) ; the-list a non-empty list

]))

One way to define lists; An empty list has no parts at all. Definition by (no) parts.

(define-struct empty [])

; make-empty: nothing -> empty

; empty? : object -> boolean

; A non-empty list has a first element and a rest which is itself a (possibly empty) list. Definition by parts.

(define-struct non-empty [first rest])

; make-non-empty : object list -> non-empty

; non-empty-first : non-empty -> object

; non-empty-rest : non-empty -> list

; non-empty? : object -> boolean

One way to define lists; An empty list has no parts at all. Definition by parts, sorta.

(define-struct empty [])

; A non-empty list has a first element and a rest which is itself a (possibly empty) list. Definition by parts.

(define-struct non-empty [first rest])

"Examples of lists:"

(make-empty)

(make-non-empty 3 (make-empty))

(make-non-empty 4 (make-non-empty 3 (make-empty)))

(make-non-empty "Joe" (make-non-empty "Mary" (make-empty)))

The way we really do it• This is a pain.• Lists are so common that Scheme provides predefined functions

to handle them.• empty is a predefined constant, like true and false• cons is short for "construct": it constructs longer lists from

shorter ones. (Equivalent to make-non-empty)

; cons : object list -> non-empty-list; first : non-empty-list -> object; rest : non-empty-list -> list; empty? : object -> boolean; cons? : object -> boolean

The way we really do it"Examples of lists:"empty(cons 3 empty)(cons 4 (cons 3 empty))(cons "Joe" (cons "Mary" empty))

There is an even briefer notation, which we'll get to later.

Examples of working with lists

(define list1 (cons "Joe" empty))(define list2 (cons "Mary" list1))(define list3 (cons "Bob" list2))(define list4 (cons "Phil" (cons "Amy" empty)))(define list5 (cons 3 (cons 6 (cons -5 (cons 3 empty)))))

(check-expect (empty? list1) false)(check-expect (cons? list1) true)(check-expect (first list1) "Joe")(check-expect (first list2) "Mary")(check-expect (first list3) "Bob")(check-expect (first list4) "Phil")(check-expect (first list5) 3)

Examples of working with lists

(check-expect (rest list1) empty)

(check-expect (rest list2) (cons "Joe" empty))

(check-expect (rest list3)(cons "Mary" (cons "Joe" empty)))

(check-expect (rest list4) (cons "Amy" empty))

(check-expect (first (rest list4)) "Amy")

(check-expect (first (rest (rest list5))) -5)

Template using choices and parts

(define (function-on-list the-list) (cond [(empty? the-list)

; the-list an empty list ] [(cons? the-list)

; the-list a non-empty list ; (first the-list) whatever type is in the list ; (rest the-list) a list in its own right

]))

Template using choices and parts

(define (function-on-list the-list) (cond [(empty? the-list)

; the-list an empty list ] [(cons? the-list)

; the-list a non-empty list ; (first the-list) whatever type is in the list ; (rest the-list) a list in its own right ;(function-on-list (rest the-list)) ]))

Shape of data -> shape of code!

The data type was self-referential in the "rest" part of the "non-empty" case, so…

the function is self-referential in the "rest" part of the "non-empty" case.

Recursion has sneaked in; nothing new, just applying the coding patterns we already know.

Students don't know recursion is hard unless you tell them.

This form of recursion cannot go infinite!

Writing functions on lists

; count-elements : list -> number

Writing functions on lists

; count-elements : list -> number

"Examples of count-elements:"(check-expect (count-elements empty) 0)(check-expect (count-elements (cons "Joe" empty)) 1)(check-expect (count-elements (cons "Phil" (cons "Joe" empty))) 2)

Writing functions on lists

; count-elements : list -> number(define (function-on-list the-list) (cond [(empty? the-list)

; the-list an empty list ] [(cons? the-list)

; the-list a non-empty list ; (first the-list) whatever type is in the list ; (rest the-list) a list in its own right ;(function-on-list (rest the-list)) ]))"Examples of count-elements:"(count-elements empty) "should be" 0(count-elements (cons "Joe" empty)) "should be" 1(count-elements (cons "Phil" (cons "Joe" empty))) "should be" 2

Writing functions on lists

; count-elements : list -> number

(define (count-elements the-list)

(cond [(empty? the-list) ; the-list an empty list

]

[(cons? the-list) ; the-list a non-empty list

; (first the-list) whatever kind of object is in the list

; (rest the-list) a list in its own right

; (count-elements (rest the-list)) a number

]))

"Examples of count-elements:"

Writing functions on lists

; count-elements : list -> number

(define (count-elements the-list)

(cond [(empty? the-list) ; the-list an empty list

0 ] ; from one of the test cases

[(cons? the-list) ; the-list a non-empty list

; (first the-list) whatever kind of object is in the list

; (rest the-list) a list in its own right

; (count-elements (rest the-list)) a number

]))

"Examples of count-elements:"

Writing functions on lists

; count-elements : list -> number

(define (count-elements the-list)

(cond [(empty? the-list) ; the-list an empty list

0 ]

[(cons? the-list) ; the-list a non-empty list

; (first the-list) whatever kind of object is in the list

; (rest the-list) a list in its own right

(+ 1 (count-elements (rest the-list)))

]))

"Examples of count-elements:"

Now you try one

; add-up : list of numbers -> number

"Examples of add-up:"

(check-expect (add-up empty) 0)

(check-expect (add-up (cons 3 empty)) 3)

(check-expect (add-up (cons 4 (cons 3 empty))) 7)

Searching

• We represent the ingredients on a pizza as a list of strings, e.g.

– empty– (cons "cheese" empty)– (cons "garlic" (cons "cheese" empty))– (cons "pepperoni" (cons "garlic" (cons "cheese"

empty)))• We want to know whether there are any onions on the

pizza.

Searching

; has-onions? : list-of-strings -> boolean

"examples of has-onions?:"

(check-expect (has-onions? empty) false)

(check-expect (has-onions? (cons "cheese" empty)) false)

(check-expect (has-onions? (cons "onions" empty)) true)

(check-expect (has-onions? (cons "cheese" (cons "onions" (cons "pepperoni" empty)))) true)

(check-expect (has-onions? (cons "cheese" (cons "garlic" (cons "pepperoni" empty)))) false)

Searching

; has-onions? : list-of-strings -> boolean(define (function-on-list the-list) (cond [(empty? the-list)

; the-list an empty list ] [(cons? the-list)

; the-list a non-empty list ; (first the-list) whatever type is in the list ; (rest the-list) a list in its own right ;(function-on-list (rest the-list)) ]))

Searching

; has-onions? : list-of-strings -> boolean(define (has-onions? ingredients) (cond [(empty? ingredients)

; ingredients an empty list ] [(cons? ingredients)

; ingredients a non-empty list of strings ; (first ingredients) a string ; (rest ingredients) a list of strings in its own right ;(has-onions? (rest ingredients)) a boolean ]))

Searching

; has-onions? : list-of-strings -> boolean(define (has-onions? ingredients) (cond [(empty? ingredients)

; ingredients an empty list false ; from one of the test cases

] [(cons? ingredients)

; ingredients a non-empty list of strings ; (first ingredients) a string ; (rest ingredients) a list of strings ;(has-onions? (rest ingredients)) a boolean ]))

Searching

; has-onions? : list-of-strings -> boolean(define (has-onions? ingredients) (cond [(empty? ingredients)

; ingredients an empty list false ; from one of the test cases

] [(cons? ingredients)

; ingredients a non-empty list of strings ; (first ingredients) a string ; (rest ingredients) a list of strings ;(has-onions? (rest ingredients)) boolean ; (string=? (first ingredients) "onions") boolean

]))

Searching; has-onions? : list-of-strings -> boolean(define (has-onions? ingredients) (cond [(empty? ingredients)

; ingredients an empty list false ; from one of the test cases

] [(cons? ingredients)

; ingredients a non-empty list of strings ; (first ingredients) a string ; (rest ingredients) a list of strings ;(has-onions? (rest ingredients)) boolean ; (string=? (first ingredients) "onions") boolean

(or (string=? (first ingredients) "onions") (has-onions? (rest ingredients)))

]))

A slightly different approach; has-onions? : list-of-strings -> boolean(define (has-onions? ingredients) (cond [(empty? ingredients)

; ingredients an empty list false ; from one of the test cases

] [(cons? ingredients)

; ingredients a non-empty list of strings ; (first ingredients) a string ; (rest ingredients) a list of strings ;(has-onions? (rest ingredients)) boolean ; (string=? (first ingredients) "onions") boolean

(cond [(string=? (first ingredients) "onions") true] [else (has-onions? (rest ingredients))])

]))

Searching exercises

Write a function any-over-100? which takes in a list of numbers and tells whether any of them are over 100

Write a function all-over-100? which takes in a list of numbers and tells whether all of them are over 100

Write a function string-in? which takes in a string and a list of strings and tells whether the string appears in the list

Are we done yet?

• Fill out end-of-day survey

• Eat

• Go home

• Sleep

• Come back for another day