Remix.run Logo
sevensor 2 days ago

Concurrency is a good motivation, but this is super useful even in straight line code. There’s a huge difference between functions that might mutate a dictionary you pass in to them and functions that definitely won’t. Using Mapping is great, but it’s a shallow guarantee because you can violate it at run time.

quietbritishjim a day ago | parent [-]

> There’s a huge difference between functions that might mutate a dictionary you pass in to them and functions that definitely won’t.

Maybe I misunderstood, but it sounds to me like you're hoping for the following code to work:

   def will_not_modify_arg(x: frozendict) -> Result:
       ...
   
   foo = {"a": 1, "b": 2}  # type of foo is dict
   r = will_not_modify_arg(foo)
But this won't work (as in, type checkers will complain) because dict is not derived from frozendict (or vice-versa). You'd have to create a copy of the dict to pass it to the function. (Aside from presumably not being what you intended, you can already do that with regular dictionaries to guarantee the original won't change.)
sevensor 16 hours ago | parent [-]

No, I’d type the function argument as a Mapping. Frozendict is so that the function will raise an exception if it violates its type signature.

Edit: that is, if as the caller you want foo to be immutable, then you make it a frozendict

quietbritishjim 4 hours ago | parent | next [-]

Ah, I see. The last sentence in your previous comment makes more sense now ("Mapping is great, but ... you can violate it at run time"). A type checker would normally catch violations but I can still see a frozendict would be useful.

4 hours ago | parent | prev [-]
[deleted]