Live data from Hacker News

A “frozen” dictionary for Python

lwn.net

151–160 of 172 posts

Re: A “frozen” dictionary for Python

#152

Can someone ELI5 the core difference between this and named tuples, for someone who is not deep into Python? ChatGPT's answer boiled down to: unordered (this) vs ordered (NTs), "arbitrary keys, decided at runtime" vs "fixed set of fields decided at definition time" (can't an NT's keys also be interpolated from runtime values?), and a different API (`.keys()`, `.items()`), etc (I'm just giving this as context btw, no…

On top of generating types dynamically being slow and bad as quietbritishjim said, “str values that also happen to be valid identifiers” is a very limiting dict key requirement.

Great point, I can't believe I missed that.

Re: A “frozen” dictionary for Python

#153
post #142

Earlier quoted context omitted.

You cannot return an immutable version. You can return it owned (in which case you can assign/reassign it to a mut variable at any point) or you can take a mut reference and return an immutable reference - but whoever is the owner can almost always access it mutably.

I mean, if you return an immutable reference, the owner in fact cannot mutate it until that reference is dropped. If you in fact return e.g. an Rc::new(thing) or Arc::new(thing), that's forever (though of course you can unwrap the last reference!)

> I mean, if you return an immutable reference, the owner in fact cannot mutate it until that reference is dropped.

Might be worth noting that "dropped" in this context doesn't necessarily correspond to the reference going out of scope:

    fn get_first(v: &Vec) -> &i32 {
        &v[0]
    }

    fn main() {
        let mut v = vec![0, 1, 2];
        let first = get_first(&v);
        print!("{}", first});
        v.push(3); // Works!
        // print!("{}", first); // Doesn't work
    }

Re: A “frozen” dictionary for Python

#154
post #39

Earlier quoted context omitted.

> Another PEP 351 world view is that tuples can serve as frozenlists; however, that view represents a Liskov violation (tuples don't support the same methods). This idea resurfaces and has be shot down again every few months. ... Well, yes; it doesn't support the methods for mutation . Thinking of ImmutableFoo as a subclass of Foo is never going to work. And, indeed, `set` and `frozenset` don't have an inheritance re…

> I've felt like frozendict was missing for a long time, though. Type the dict as a mapping when you want immutability: x: Mapping[int, int] = {1: 1} x[1] = 2 # Unsupported target for indexed assignment ("Mapping[int, int]"). The only problem I've seen with this is: y = {} y[x] = 0 # Mypy thinks this is fine. Mapping is hashable, after all! The issue here is less that dict isn't hashable than that Mapping is, though.

This is because the ABC system is defined such that MutableMapping is a subtype of Mapping. Which mostly makes sense, except that if we suppose there exist Mappings that aren't MutableMappings (such that it makes sense to recognize two separate concepts in the first place), then Mapping should be hashable, because immutable things generally should be hashable. Conceptually, making something mutable adds a bunch of mutation methods, but it also ought to take away hashing. So Liskov frowns regardless.

Re: A “frozen” dictionary for Python

#155

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.

> 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.)

Re: A “frozen” dictionary for Python

#156
post #25

Earlier quoted context omitted.

This place hates laziness and imprecision. Using ChatGPT for editing or inspiration is okay as long as you personally review the results for accuracy and completeness, at which point people care about it as much as you announcing that you used a spell checker.

Pasting chat GPT responses is against the site rules. always has been even before GPT https://news.ycombinator.com/item?id=46206457

True, but the original comment that we're talking about here (by sundarurfriend) just mentioned an LLM's output in passing as part of their (presumably) human-written comment. Nothing you've linked to prohibits that.

Re: A “frozen” dictionary for Python

#157

Earlier quoted context omitted.

Pasting chat GPT responses is against the site rules. always has been even before GPT https://news.ycombinator.com/item?id=46206457

True, but the original comment that we're talking about here (by sundarurfriend) just mentioned an LLM's output in passing as part of their (presumably) human-written comment. Nothing you've linked to prohibits that.

Presaging your bot produced comment with "A bot said this" is not human written

Re: A “frozen” dictionary for Python

#158

Earlier quoted context omitted.

True, but the original comment that we're talking about here (by sundarurfriend) just mentioned an LLM's output in passing as part of their (presumably) human-written comment. Nothing you've linked to prohibits that.

Presaging your bot produced comment with "A bot said this" is not human written

Except in that case they were summarizing it, which I read as closer to “I found this on Stack Overflow but don’t know if it’s right”. I think that’s less offensive than having the post be LLM output or, especially, pretending to be authoritative.

Re: A “frozen” dictionary for Python

#159

Earlier quoted context omitted.

Same. Recently I saw interview feedback where someone complained that the candidate used OrderedDict instead of the built-in dict that is now ordered, but they'll let it slide... As if writing code that will silently do different things depending on minor Python version is a good idea.

Honestly, if I was writing some code that depended on dicts being ordered I think I'd still use OrderedDict in modern Python. I gives the reader more information that I'm doing something slightly unusual.

Same. Usually if a language has an ordered map, it's in the name.

Re: A “frozen” dictionary for Python

#160

Earlier quoted context omitted.

> I've felt like frozendict was missing for a long time, though. Type the dict as a mapping when you want immutability: x: Mapping[int, int] = {1: 1} x[1] = 2 # Unsupported target for indexed assignment ("Mapping[int, int]"). The only problem I've seen with this is: y = {} y[x] = 0 # Mypy thinks this is fine. Mapping is hashable, after all! The issue here is less that dict isn't hashable than that Mapping is, though.

This is because the ABC system is defined such that MutableMapping is a subtype of Mapping. Which mostly makes sense, except that if we suppose there exist Mappings that aren't MutableMappings (such that it makes sense to recognize two separate concepts in the first place), then Mapping should be hashable, because immutable things generally should be hashable. Conceptually, making something mutable adds a bunch of mu…

It really doesn't make sense for there to be an inheritance relationship between Mapping and MutableMapping if Mapping is immutable (it isn't, of course), but the weirder part is still just that the typing machinery is cool with unhashable key types like:

  x: dict[list, int] = {}

  x[[1, 2, 3]] = 0
Post reply on HN