Lecture 25 : Mutable structures ;; An account is (make-account number number) (define-struct account (acctnum balance)) (define accounts (list (make-account 1 500) (make-account 2 1000) (make-account 3 10))) When you use define-struct, Racket also gives you operators for changing the contents of structures. Specifically, for the account structure defined above, you get set-account-acctnum! : account number -> void set-account-balance! : account number -> void Using these, we could write deposit as ;; deposit: number number list-of-account -> void ;; consumes account number, amount of money, and list of accounts and ;; adds the amount to the balance in the given account ;; EFFECT: changes balance in one of the accounts (define (deposit acctnum amt aloa) (cond [(empty? aloa) (error "No such account")] [(cons? aloa) (cond [(= acctnum (account-acctnum (first aloa))) (deposit-into (first aloa) amt)] [else (deposit acctnum amt (rest aloa)))])]) ;; deposit-into : account number -> void ;; adds the given amount to the account balance ;; EFFECT: increases the balance in the account (define (deposit-into acct amt) (set-account-balance! acct (+ amt (account-balance acct)))) ---------------------------------------------------------------------- Assume the bank wants to store personal info on account holders as well their accounts. They create the following data definition: ;; A customer is (make-customer string number account) (define-struct customer (name phone acct)) Now assume that two customers, Maria and Phil, are married and share an account (but have different cell-phone numbers). How might we create the data for them as customers? Approach 1 : (define Mcust (make-customer "Maria" 5553245 (make-account 24 500))) (define Pcust (make-customer "Phil" 5556702 (make-account 24 500))) This seems wrong from the start, because they aren't sharing the account -- they have two different accounts with the same number and balance. Approach 2 : (define MPacct (make-account 24 500)) (define Mcust (make-customer "Maria" 5553245 MPacct)) (define Pcust (make-customer "Phil" 5556702 MPacct)) Now let's change the balance and see what happened: (set-account-balance! MPacct 1000) The change shows up in both Mcust and Pcust. What if we change the balance going through Maria's customer structure instead of by modifying MPacct by name? (set-account-balance! (customer-acct Mcust) 2000) That still does what we want it to, because the same account structure is inside both of Mcust and Pcust. What if we used set! instead, and wrote (set! MPacct (make-account 24 3000)) Note that now the change doesn't show up in _either_ Mcust or Pcust. This is because the set! redefines the _name_ MPacct, but what Racket stores inside Mcust and Pcust isn't the name MPacct, it's the actual structure. This highlights the difference between set! and set-structure! (When you use a name to build data, Racket puts the data, but not the name, into the structure. In this case, Racket drops the definition for MPacct into Mcust and Pcust; there's no association with the name once it's dropped in.) set! changes what a name refers to but not the data associated with that name, while set-structure! actually changes the contents INSIDE the structure.