[HN Gopher] Multiplicity Choices Are Hard to Model and Change
___________________________________________________________________
Multiplicity Choices Are Hard to Model and Change
Author : ltratt
Score : 11 points
Date : 2022-05-27 07:08 UTC (1 days ago)
(HTM) web link (tratt.net)
(TXT) w3m dump (tratt.net)
| dataangel wrote:
| I broadly agree with multiplicity problems being the worst, but
| have some nits.
|
| > because my language's static type system probably won't give me
| any leads on what needs fixing
|
| This is because moving to Vec<Address> introduced 0 addresses as
| a possibility into the type already and you didn't deal with it
| then. If the author had moved to NonEmptyVec<Address> first, then
| you could have transitioned to Option<NonEmptyVec<Address>>.
|
| > Ironically, I often find that the hardest places to work out
| what to do are those where the static type system forces me to
| deal with the possibility of there not being a T but my analysis
| of the code shows (or, at least, suggests) that at run-time there
| always will be a T. This leads to a counter-intuitive situation:
| although the static type system has helpfully told me all the
| places where changing the multiplicity needs to be considered, I
| can introduce more run-time errors than I could ever have
| encountered in a non-option-types language!
|
| This doesn't quite make sense. Either the errors could also
| happen in the dynamic type setting in which case you were missing
| checking you needed, or they can't happen in either setting in
| which case you may have unnecessary code _checking_ for a missing
| T, but those runtime errors never actually occur in practice. I
| think maybe the author means those unnecessary checks are "more
| runtime errors", but it's not that you actually get more errors
| in practice, it's just that someone reading the code might think
| there is the possibility of errors in more places than there
| actually are. There is an easy solution to this though: find the
| earliest point where it's guaranteed that there is actually a T,
| put one assert there with a comment indicating that if this
| assert is ever false it's a bug, then stuff the the unwrapped T
| in a new variable and use it from then on. If you need to pass it
| to a function that requires an option just call it with
| f(Some(foo)).
|
| > (e.g. do I dynamically check the property each time I create
| one of my new wrapper types? what is the performance cost?)
|
| No you only have a constructor that requires you to pass in at
| least one initial element which will statically enforce that it's
| at least size one, and then only have the container assert that
| it's still at least size one when methods that remove elements
| are called (which in most use cases you probably won't ever call
| or will call rarely). The cost is one branch when erasing, it's
| very cheap. And since erasing from anywhere in the vector except
| the end involves shifting comparatively speaking the branch is
| cheap.
___________________________________________________________________
(page generated 2022-05-28 23:01 UTC)