How can i create function that takes an instance and updates it?

i am trying to complete a homework task based on structure,but when i came to the third bullet point where it asked me to create a function for a customer instance,i got confused how am i supposed to do that,because i don't know which arguments to take.Here is the assignment brief.

A chain of supermarkets has decided to offer a loyalty card to its regular customers. Customers 
can collect points to get exclusive discounts on several products. 
1. Define a struct type to represent a customer. The structure should contain fields 
allowing to store the name of a customer, the number of points collected by a 
customer, the number of points already spent by a customer (i.e., point used to obtain 
special discount) and the current number of points owned by a customer, initialized to 0 
(i.e., points collected - points spent). 
2. Define five named instances, e.g., “James Anita”, 3200, 1200, 0. (Note: the number of 
points collected by a customer should always be greater or equal to the number of 
points he already spent) 
3. Write a function that takes as input an instance of a customer struct and updates the 
field corresponding to the current number of points owned by a customer. The current 
number of points is computed by subtracting the points spent from the points collected. 
E.g., given the struct “James Anita”, 3200, 1200, 0, it should update the last field with 
2000.   
4. Before proceeding to the payment of his purchase, a customer can choose to use his 
points. Write a function that will take as input an instance of a customer struct, the 
number of points which would be collected by the customer by proceeding to the 
payment of his purchase, and the number of points the customer intends to use.  
a. If the number of points which would be collected by a customer by proceeding 
to the payment of his purchase and his current number of points are greater 
than the number of points he intends to spend, his loyalty card account will 
automatically be updated after payment (number of points collected, number of 
points spent, current number of points).  
b. If not, the message "Unfortunately, you need XXX extra customer points!!", 
where XXX corresponds to the number of points missing, will be displayed on the 
screen. 

and here is my code so far

(define-struct customer  [name nopcbc nofpasbac cnopobac])
;; A custmoer  is a structure:
;;   (make-custmoer  string number number number )

;(make-custmomer  a  b c d) represents a custmoers details
;; with a name 
;; and a nopcbc b
; nofpasbac c
;cnopobac d

;; Interpretation:
;; name is the name of the customer
;; nopcbc is he number of points collected by a customer
; nofpasbac is  the number of points already spent by a customer 
;cnopobac is current number of points owned by a customer, initialized to 0



(define new-customer1 (make-customer “James Anita” 3200 1200 0))
(define new-customer2 (make-customer “John wood” 4200 1800 0))
(define new-customer3 (make-customer “Tom Smith” 3600 1500 0))
(define new-customer4 (make-customer “Brooke eve” 3100 1000 0))
(define new-customer5 (make-customer “Osman Hassan” 3900 1400 0))

The current number of points is computed by subtracting the points spent from the points collected.

You need to compute this value, and update the field of the struct
(there are many ways to do so, some of which differ based on whether
or not the struct-field is mutable).

N.B. in modern Racket you would not use define-struct.

The names nopcbc, nofpasbac, and cnopobca are hard to work with;
may I suggest total-points-collected, points-spent, and
current-points? (Of course, the design is awkward, since it must
ensure manually that total-points-collected is always the sum of
points-spent and `current-points, but it is homework…)

Since this is likely a student language, continue to use define-struct.

For 3, determine the signature of your function. What is the problem asking for you to take in and produce? What fields do you have access to from customer?

1 Like

First off, welcome! Nice to have a new person on the list, and I'm glad you're interested in learning Racket.

The key thing to know about Racket is that it's a functional language. As a general rule, you don't change the value something in place, you create a new instance of it with the new value. You can test this using various forms of equality:

;  eq?  asks "do these two identifiers refer to the same memory address?"
;  equal? asks "are these two things sufficiently similar that a human would call them the same in most circumstances?"

; Notice that I've added the keyword "#:transparent", which makes the internals of the struct visible to Racket's various printers and inspectors
(define-struct customer  [name points-collected points-spent points-remaining] #:transparent)

; Create some instances
(define bob (customer 'bob 1700 100 1600))        ; a thing
(define bob-alias bob)                            ; different name for the same thing
(define bob-clone (customer 'bob 1700 100 1600))  ; another thing, has the same values

(equal? bob bob-clone)  ; returns #t because they are both visible,  have the same type, and have the same values [*]
(eq? bob bob-clone)     ; returns #f because they are not the same object in memory
(eq? bob bob)           ; returns #t because they are the same object in memory
(eq? bob bob-alias)     ; returns #t because they are different names for the same object in memory

; Important caveat:  Different struct definition.  I've removed the keyword #:transparent, so now Racket is restricted in how it can look inside the object
(define-struct not-transparent-cust  [name points-collected points-spent points-remaining])

(define alice       (not-transparent-cust 'alice 3 2 1))  ; a thing
(define alice-alias (not-transparent-cust 'alice 3 2 1))  ; same thing, different name
(define alice-clone (not-transparent-cust 'alice 3 2 1))  ; different thing, same values, same type

(eq? alice alice)          ; #t, same object in memory
(eq? alice alice-alias)    ; #t, same object in memory
(eq? alice alice-clone)    ; #f, not the same object in memory
(equal? alice alice-clone) ; #f whaaat???  We can see that the structs have the same values, but the type is not transparent and therefore Racket cannot introspect it sufficiently to verify all values are the same

Given all of the above, how would you write a function that:

  • Accepts a customer struct as its argument
  • Extracts its field values
  • Performs the necessary calculations to determine how things should change
  • Returns a customer struct that has the correct values

Furthermore, how would you write tests that verify it works correctly? (Hint: Look at the various equality tests above.)

1 Like