5 ms·
Oh, of course. In Python's case, I'd advocate to just get rid of tuples and be done with it. (Maybe replace it with a nice immutable adaptor class; I'm sure o
by colanderman 10y ago
Oh, of course. In Python's case, I'd advocate to just get rid of tuples and be done with it. (Maybe replace it with a nice immutable adaptor class; I'm sure one already exists.) It's a dynamically typed interpreted language, neither performance nor type-correctness is its strong point.
- pdonis 10y ago> In Python's case, I'd advocate to just get rid of tuples and be done with it. That would be a bad idea for at least two reasons: sometimes you want containers to be immutable, and mutable containers can't be used as dictionary keys.
- kazinator 10y agoYou mean in Python or in computer science? Because I'm pretty sure that it's possible to use mutable objects as keys in general. The users just have to observe restrictions: like don't insert the keys into the dictionary and then mutate them while they are in the dictionary and expect the dictionary to still work fine. (Objects can also be used as keys even if they are mutated while in the dictionary, if identity-based equality is used for the dictionary; i.e. two keys are equal if they are acually one and the same object, and not just two similar objects.)
- kilink 10y agoThis is a Python specific restriction. Ruby for example allows mutable keys in dictionaries.
- catnaroek 10y agoSo, which is the case? (0) Object identities are used as keys? (e.g., two different list objects that contain the elements 1,2,3 are treated as different keys) (1) Catastr... I mean, hilarious things happen if you mutate an object that's being used as a key?
- kilink 10y agoI'm not sure if you are asking about Python, or Ruby. Anyway, both languages use value-based hashing for dictionaries. I am not a Rubyist, but I guess you are just expected to not mutate the keys? Ruby's dictionary implementation also has a rehash method to deal with this case [1], if for some reason you are purposely mutating the keys I suppose... [1] http://docs.ruby-lang.org/en/2.0.0/Hash.html#method-i-rehash http://docs.ruby-lang.org/en/2.0.0/Hash.html#method-i-rehash
- catnaroek 10y ago> I'm not sure if you are asking about Python, or Ruby. Ruby, since you said it allows mutable keys in dictionaries. > Anyway, both languages use value-based hashing for dictionaries. Neither Python nor Ruby has compound values. Object identities are primitive values. > but I guess you are just expected to not mutate the keys? I guess C programmers are expected not to use memory after they free it.
- kazinator 10y agoBut if Python got rid of tuples, it would be a radical change; in that case it could as well allow lists to be dictionary keys in the same stroke.
- catnaroek 10y ago> Because I'm pretty sure that it's possible to use mutable objects as keys in general. The users just have to observe restrictions: like don't insert the keys into the dictionary and then mutate them while they are in the dictionary and expect the dictionary to still work fine. In other words, mutable objects don't work as keys, and pretending they do requires unenforced conventions to preserve the integrity of the dictionary abstraction. > Objects can also be used as keys even if they are mutated while in the dictionary, if identity-based equality is used for the dictionary; i.e. two keys are equal if they are actually one and the same object, and not just two similar objects. The fundamental problem is very simple: dictionary keys have to be values, not objects, and Python simply doesn't have compound values. There is no such thing as “the list [1,2,3]” in Python: you just have one or more objects whose current state happens to be the sequence 1,2,3. The very next moment, their states might be different sequences. Object identities are first-class values in Python, but identities are primitive and indecomposable - not compound!
- philipov 10y agoIt's worth noting that tuples aren't actually immutable in Python. Tuples have immutable length, but the values in those slots can be changed at runtime.
- colanderman 10y agoNo, they definitely can't: >>> (1,2,3)[2]=5 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment I wish they could. (Maybe Python 3 is different?)
- gakada 10y agoTuples are immutable so that they can be used as keys in hash tables.
- kazinator 10y agoBut a sibling comment to yours by shoyer argues that mutable objects can be elements of a tuple. A tuple whose elements are mutable is effectively mutable. Can (1, 2, [3]) be used in a hash table, and what if the [3] is mutated to [3, 4]?
- philipov 10y agoWhen it tries to hash the tuple, it finds the list inside of it, realizes the tuple is mutable, and throws an error.
- shoyer 10y agoYou can't replace a value in a tuple, but you can modify it, e.g., >>> x = (1, 2, [3]) >>> x (1, 2, [3]) >>> x[2].append(4) >>> x (1, 2, [3, 4])
- nemothekid 10y agoYou haven't changed anything about the tuple. The holds a reference to a list and will always hold a reference to that list. What you did was modify the underlying list, the tuple itself is immutable.
- colanderman 10y agoYes, hence my suggestion to introduce an immutable adaptor class. Then all containers (sets, dictionaries, etc.) gain those abilities.
- pdonis 10y ago> hence my suggestion to introduce an immutable adaptor class What does this gain you over just doing tuple(obj) (or the equivalent--tuple(d.items()) for a dictionary, for example) when you want to make it immutable for use as a dict key?
- colanderman 10y agoIt can be implemented copy-on-write. It can have more compact storage if the runtime is smart. It can continue to efficiently support lookup (e.g. tuple(d.items()) would not).
- pdonis 10y ago> It can be implemented copy-on-write. Which only makes sense if the underlying mutable object is mutated. But if the underlying mutable object is mutated, the adaptor instance, if it is immutable, can no longer have the same value as the underlying mutable object. So the "adaptor" is no longer an adaptor; it's just a separate immutable object with the value that the mutable object had originally. I.e., it's just the same as tuple(d.items()) or whatever. If by "copy-on-write" you just mean that two different containers that both store the same immutable value, say a string, can both point to the same memory storing that value, and the mutable container's pointer only changes if a new value is stored at that key/index, Python already does that; for example, tuple(d.items()) does not create new storage for the items themselves, it points the tuple to the same objects that are contained in the dict at the time of the call to d.items(). > It can have more compact storage if the runtime is smart. A tuple in Python does have more compact storage than a list, dict, or set. > It can continue to efficiently support lookup Same issue as above; this only matters if the underlying object is mutated, in which case an immutable "adaptor" can no longer have the same value, so lookup on the adaptor isn't the same as lookup on the underlying mutable object. Lookup on the adaptor is just lookup on the immutable value, which is easily made efficient.
- nerdponx 10y agoI use them as the semantic guide when I write code. Then again, I also use single and double quotes as a semantic guide to mean different things. I feel like that would probably make most programmers want to throw the computer at the wall, but so it goes
- philipov 10y agowhat, of course, single quotes are for characters and double quotes are for strings.
- markrages 10y agoC programmer identified.
- colanderman 10y agoI do the same! But I get frustrated that I can neither modify individual elements of my "cultural" tuples, nor is there an immutable (functional) "cultural" list (or dictionary, for that matter).
- omaranto 10y agoWhat do you use single and double quotes for?
- SpaceManiac 10y agoI can't speak for GP, but I like to use single quotes for symbolic strings ('go_left', 'parent', 'alpha-campus', some_map['fixed_key']) and double quotes for textual strings ("An error occurred", "package/__main__.py").
- omaranto 10y agoOh, I like that idea: compensate via a convention for Python's lack of a symbol data type. :)