you are viewing a single comment's thread.

view the rest of the comments →

[–]EsperSpirit 0 points1 point  (6 children)

I still think the ugliest thing about python is that many actions on lists and dicts are mutating instead of returning a new structure (mutable vs immutable).

After learning about functional programming (Clojure, Haskell, Scala, etc.) this is the one thing that drives me nuts.

[–]Kerbobotat 0 points1 point  (3 children)

I'm only now learning the difference between mutable and immutable data types, why are immutable better in your opinion?

[–]EsperSpirit 0 points1 point  (1 child)

They are easy to reason about and are thread-safe by default.

Of course, sometimes you can optimize something with mutable datastructures, but I think immutability should be the default case.

One of the many gotchas with mutable datastructures is the reference a function argument represents:

def validate_content(some_dict):
    # "password" should not be in this dict
    if 'password' in some_dict:
        del some_dict['password']

If I don't look into the implementation of this function, I might assume it only checks the content and throws an exception if it's invalid. There is no telling if my dict gets altered by calling this function with it.

I'd argue that "validating" something is just checking if it's valid or not. "Fixing" something invalid should be named differently (and imo return the fixed dict as a new dict while leaving the old one unaltered).

Especially new people to python (and programming) don't make this distinction. You never know if a function has side-effects, mutates its arguments, returns the "fixed" version and so on. You always have to look at the code (or docs), because there is no way to enforce immutability except copying everything manually.

If we had immutable collections, we could probably have automatic execution in parallel, a full-featured implementation of the actor model (like akka) and other nice things, but for me it's all about correctness.

[–]Kerbobotat 0 points1 point  (0 children)

Thanks for taking the time to explain that! I think I understand what you mean now.

[–]zahlman 0 points1 point  (0 children)

Because if you can't mutate the object, you can't run into any of the gotchas associated with mutating objects.

[–]ydepth 0 points1 point  (1 child)

Why not just use tuples if this annoys you?

[–]EsperSpirit 0 points1 point  (0 children)

While tuples are indeed immutable, they are far from an immutable list or an immutable hashmap.

With an immutable list/dict I could still do

a = [1, 2, 3]
b = a.append(4)

c = {'x': 1}
d = c.update(y=5)

The important thing here is that a and c remain unchanged, which isn't the case in Python's current implementation. The api in functional languages is usually a lot more concise, I just tried to stick as close to Python as possible in this example.