Hacker News new | ask | show | jobs
by Blikkentrekker 1969 days ago
Python honestly did not learn from many things that were already well known when it was designed.

It wasn't arcane at the time that using exceptions for decision logic, or letting loops run by assignment, rather than by creating a new scope, were not the most salient ideas.

The following Python code contains a bug:

  list_of_adders = []
  for x in iterator:
   list_of_adders.append(lambda y: y+x)
Namely, since `x` is assigned with each iteration of the loop, rather than that a new scope is created, the `x` that the closure encloses is re-assigned with it, so all anonymous functions contain the value that `x` had in the last loop, which is almost certainly not what the programmer intended.

In fact, if within the same scope, which is quite large, since Python does not like block scope, x ever be re-assigned, which is quite likely, as Python uses the same syntax for initialization and assignment, then all the closures collected in the list shall thenceon refer to the new value that x is assigned to.

These are not design choices that many other programming languages at the time made; they were bad with the knowledge of the time, and continue to be bad now. There is no justification to have loops be implemented by assignment, and not create a new scope.

2 comments

The justification for function-scope instead of block-scope is that only the former really works if you have implicit variable declarations.

In turn, implicit variable declarations (using the same syntax for initialisation and assignment) are a reasonable choice for a language that aimed to be “executable pseudocode” and that supports mixing initialisation and assignment in a single statement (e.g. `a, b, self.c = foo()`).

It could easily be written as `var a, var b, self.c = foo()`.

Having the same syntax for initialization and assignment is quite quæstionable.

That’s not a bad suggestion, but it’s quite verbose (it would require declaring multiple variables as `var x, var y, var z` instead of `var x, y, z`).
That could easily be `var (x, y, z) =`, which is similar to what many languages use.
I'm always surprised when something throws in my face how many details we have to keep in memory to make implicit mutability work.

It's amazing that people can program in imperative languages at all, yet it feels easy. I wonder how much trouble this causes for somebody learning how to program in a modern high level language.