I am experimenting with records and I am a little bit confused. In the example person2 and person3 should be the same, but person3 gives me an error…
Can anybody explain the difference?
type alias Date =
{ day : Int
, month : Int
, year : Int
}
type alias Person =
{ firstName : String
, lastName : String
, birthDate : Date
}
person1 : Person
person1 =
{ firstName = "Tom"
, lastName = "Smith"
, birthDate = { day = 6, month = 6, year = 2006 }
}
person2 : Person
person2 =
let date = person1.birthDate
in
{ person1 | birthDate = { date | month = person1.birthDate.month + 1 } }
person3 : Person
person3 =
{ person1 | birthDate = { person1.birthDate | month = person1.birthDate.month + 1 } }
The Elm compiler only accepts a name in the update position, not an expression. The issue is tracked here.
There’s no fundamental reason why this is the case, semantically it would make no difference, but that’s the way it is. I believe the Gren fork has fixed this.
People coming from JavaScript tend to (1) overuse records and (2) have a habit of breaking records into smaller records and to distribute them among a bunch of different files. These are both traps in Elm! (source)
so person2 would be the idomatc way to write it in elm.
Also, if you have have to update a field a lot, it might be helpful to write a utility function for it:
mapMonth : (Int -> Int) -> Date -> Date
mapMonth fun date =
{ date | month = fun date.month }
person4 : Person
person4 =
{ person1 | birthDate = mapMonth (\n -> n + 1) person1.birthDate }
OK, thank you. I wasn’t sure if I was doing something wrong or not understanding correctly. But then it’s just a design decision by Evan. I would find it logical to use the notation of person2. But well, that’s how it is.
This is the only error message in Elm that I find to be genuinely unhelpful. Most others explain what the problem is and explain how to fix it, but this one is really cryptic especially since it seems like the mistake should be valid code.