reset password
Author Message
comlor
Posts: 16
Posted 23:41 Oct 21, 2015 |

Is there a way to update a value of a struct or do we have to create a whole new struct with the new values?

ex:

(struct ball (color y-pos velocity) #:transparent)

just want to change one value for this let's say only the y-pos.  

 

 

rabbott
Posts: 1649
Posted 23:58 Oct 21, 2015 |

Yes and no. It's possible to set the value of a struct by, e.g. set-ball-y-pos! but it's not good functional programming style. In functional programming one prefers immutable values. To get Racket to generate those functions for you declare the struct mutable.

(struct ball (color y-pos velocity) #:transparent #:mutable)
Last edited by rabbott at 11:44 Oct 22, 2015.
comlor
Posts: 16
Posted 00:05 Oct 22, 2015 |

ok.  I see my error now.  i was using (set! ball-y-pos) not set-ball-y-pos!.  

Since immutable values are preferred what would be a better way to handle this?  define a new ball and "copy" the values to the new ball and set new values for the values that need to change?

layla08
Posts: 70
Posted 10:00 Oct 22, 2015 |

The book used an example that helped me with what you're asking. Regarding the Guess My Number game we built, if we were to build a GUI version using big-bang, instead of using set! to change the lower or upper bounds, we would create new interval structures:

(define (smaller w)
  (interval (interval-small w)
            (max (interval-small w) (sub1 (guess w)))))

Hope that helps :)

rabbott
Posts: 1649
Posted 11:10 Oct 22, 2015 |

More sophisticated FP Languages like Haskell have means to create modified structures by reusing the unmodified parts of the old one. It's like adding a new element to a list. The old list still exists! The new one starts at the new element and then points to the old list. But as far as someone using the new list is concerned, it's just a list.

So if you have an existing list L, you can create (cons 'a L) and (cons 'b L). These are two "new" lists, but in both cases they only create a new element and then refer to the existing list. (This works only if the existing list L is never mutated. Otherwise, the two new lists are also mutated, which is not what you want. But the that's the case with FP. Nothing is every mutated! It's surprising how many bugs don't occur when one uses immutable values. You are never surprised by something changing that you don't expect to change.)

To stay within FP good graces, I'd write functions that update fields by building new structs. So for Layla's example, assume you have (struct interval smaller larger). Then write

(define interval-new-smaller old-interval small-number)
    (interval small-number (interval-larger old-interval))

Similarly for interval-new-larger.

I wouldn't put tests that are specific to the guess-a-number problem in these functions.

Then to "put" a new smaller number s into an existing interval i call (interval-new-smaller i s).

Admittedly, it's a pain to write all those functions, but once written, you don't have to rebuild the interval every place in the code you want a modified version of an existing interval. Too bad Racket doesn't generate those functions for us the way it generates other struct functions.

The smaller function would look like this.

(define (smaller w)
  (interval-new-larger w  
                      
(max (interval-small w) (sub1 (guess w)))))

 

 

Last edited by rabbott at 13:10 Oct 22, 2015.