FPS: Chapter 40
Chapter 40: A Functional Game
This is an example of writing a game with immutable state, so It’s going to be a meh chapter. Just going to get through it - had to open up the code on the book’s recommendation. Looking at the code it’s pretty simple - there’s a case class for game state that he’s copying and overwriting fields on.
He’s not going to handle I/O in a functional way with monads so this chapter is going to be very boring.
The main game loop is recursive with a @tailrec
annotation which is interesting. Also the game extends App
which I thought was an aka library thing but must be basically a Scala primitive. He encouraged us to write it ourselves which usually I would do, but in this case I really don’t think is worthwhile.
Yeah, this chapter was pretty useless other than the fact that I get to see a recursive game loop which is interesting. Funny the game was a heads/tail predictor.
Chapter 41: Case Classes
A case class generates a lot of code for you:
- An
apply
method so you don’t need to use thenew
keyword on creation. This is also why you still need to usenew
when instantiating a Java class - Accessor methods for each constructor parameter, because they are
public val
by default so they get accessor’s - An
unapply
method is generated which makes it easy to use case classes inmatch
expressions. This is a huge FP win apparently. copy
method which you can use to make a new val of your variable with fields changed.equals
andhashCode
so you can use your objects as keys in a map or set, and also compare objects. Really with Java had this auto-comparison, I used to hate generating that code! I’ve heard of nasty bugs from hashCode methods that were missing a field.- A default
toString
method is generated which is useful for debugging. Also great, really hated generating that code in the past.
Code Examples
No need for the new
keyword:
case class Person(name: String)
val chris = Person("Chris")
Unapply method allows pattern matching and to expand the inner properties:
chris match {
case Person(name) => println(name)
}
Normal Scala classes do not compile in a match
, only case classes. Maybe if you had an unapply on the class and you extended a trait you could make it work however - I’m not sure.
Copy Method:
val chris = Person("Chris")
val jeff = chris.copy(name = "Jeff")
Useless here with one field in a case class, but normally allows you to update only one field on an object
Equals and hashCode:
val chris = Person("Chris")
val jeff = Person("Jeff")
if(chris == jeff) println("This will never happen")
toString method:
val chris = Person("Chris")
println(chris)
This will print helpful information.
So overall case classes are amazing - they reduce a ton of Java boilerplate that I used to have to write, which removes a bunch of code and potential avenue for bugs. Also pattern matching is great, you always love to use it. It’s just pretty.
Next chapter is on copying case classes, which should be great.