Lecture 23 : Set-structure! and creating data Imagine that I'm writing a gradebook (list of structures, like you did for an earlier homework). For each of the following tasks, should I use set!, set-structure!, or neither? 1. Correcting an incorrect assignment grade for a student 2. Adding a student 3. Sorting the students by numeric grades 4. Adding a homework assignment for the entire class 5. Adding 10 points to the midterm grade for everyone in the class 6. Experimenting with grades for a given student on the final to see how they would affect possible final course grades 1 is a set-structure! because the change is local to one student 2 is a set! because the change is to the gradebook as a whole 3 is neither because we have nothing to remember (nothing is changing) 4 is a set! because set-structure! can only affect components that are already in the structure, it can't add new components 5 is either set! or set-structure! (a local change, but to every student) 6 is neither since we don't want to make changes while we are just experimenting ------------------------------------------------------------------- When we looked at family trees, we did two versions: one in which people referred to parents and one in which people referred to children. If we were buiding software for family trees, it would seem useful to be able to make family trees that had links _both_ ways: people refer to their parents AND their children. Let's try to make those sorts of family trees. ;; A person is a (make-person string famtree famtree list-of-person) (define-struct person (name mother father kids)) ;; A famtree is either ;; - 'unknown, or ;; - a person Now, create an example family tree for a person named Judy whose mother is named Brenda and whose father is unknown. Let's start from Judy: (make-person "Judy" (make-person "Brenda" 'unknown 'unknown (list -))) What can we put in for the -? We can't put "Judy" because that's a string and not a person. What if we used define to give Judy's person a name? Could we do (define Jper (make-person "Judy" (make-person "Brenda" 'unknown 'unknown (list Jper)))) No, Scheme complains because it doesn't define Jper under after it finishing making Jper, so the Jper in the list doesn't yet refer to anything. Maybe we should start with Brenda then: (make-person "Brenda" 'unknown 'unknown (list (make-person "Judy" --))) Nope -- we're back to the same problem: we need Judy to make Brenda, but we need Brenda to make Judy. We can't make this sort of cyclic data in the same way that we've always created non-cyclic data. Since people are structures, set-structure! should be helpful here. What we will do is make an initial structure for Brenda that has no children. Then, once we have a structure for Judy, we'll use set-structure! to make Judy Brenda's child. (define Bper (make-person "Brenda" 'unknown 'unknown empty)) (define Jper (make-person "Judy" Bper 'unknown empty)) (set-person-kids! Bper (list Jper)) Assume now that we learned that Brenda also has a son named Eddie. Write a function add-child-to-mother that takes a person and the name of their child and expands the tree to include the child. ;; add-child-to-mother : person string -> void ;; creates person with given name and the given person as their mother ;; EFFECT: changes kids component of given mother (define (add-child-to-mother mothper cname) (local [(define childper (make-person cname mothper 'unknown empty))] (set-person-kids! mothper (cons childper (person-kids mothper))))) Summary : if two pieces of data need to contain each other, you have to create at least one piece first, define the second to refer to the first, then use set-structure! to make the first refer to the second. Note that having these links going to both parents and children doesn't make our programming task harder, just our task of creating data. If we wanted to write a program, we would either start at the top of the tree and go down (using the list of kids), or start at the bottom of the tree and go up (using the parents). We will not ask you to write programs that go both directions at once (that's a more advanced topic).