Came to know Python via the famous
article by Eric, where he
recommended Python as the first language for programmers. I followed the doc
from official website of Python, but the overall experience was not so
satisfying. (Not exactly sure why.) I didn’t pursue this language too much
afterwards, and the reason I told myself is that redundancy in this language,
: for introducing one block and the indentation inside one block.
CoffeeScript is one example that removes this redundancy.
Someone may call this nitpicking, so more reasons are required to show Python is the not as intuitive as one thinks. Luckily, I came across this article recently.
Among the ten mistakes, only three are language (syntax) related, which do not have very intuitive semantics. Therefore, one get surprising outcome. The rest are problems existing in practice. (As one theorist, I don’t deal with problems in reality.)
OOP related. (#2 Using class variables incorrectly) It feels weird to use OOP in one scripting language, so I will skip this category.
Exception related. (#3 Specifying parameters incorrectly for an exception block) Exceptions maybe very useful in production code, but I have never written any production code, so I can’t comment on this category.
Programmer related. (#5 Modifying a list while iterating over it #7 Creating circular module dependencies) It’s just wrong in any languages, so what I can say…
Module related. (#8 Name clashing with Python Standard Library modules)
Compatibility related. (#9 Failing to address differences between Python2 and Python3)
Hidden stuff related. (#10 Misusing the
__del__method) I guess it’s not meant to be used, for it has this weird prefix.
Personally, I expect the code does what it seems to do, but I am wrong for Python. (I didn’t even bother myself to find out the “why” for Python.)
def foo (bar = ) bar.append("baz") return bar
Running above Python program in the repl:
>>> foo() ["baz"] >>> foo() ["baz", "baz"] >>> foo() ["baz", "baz", "baz"]
Fortunately, CoffeeScript is intuitive this time.
foo = (bar = ) -> bar.push 'baz'; bar >>> foo() [ 'baz' ] >>> foo() [ 'baz' ] >>> foo() [ 'baz' ]
This is pure stupid. Any reason to back up this design is excuse.
x = 10 def foo(): x += 1 print x >>> foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in foo UnboundLocalError: local variable 'x' referenced before assignment
Let’s see what the right way is:
x = 10 foo = -> x += 1 console.log x >>> foo() 11
It’s actually one feature; variables are captured “by reference”.
x = [1..4].map (i) -> (x) -> x*i y = (((x) -> x*i) for i in [1..4]) for f in x alert f 1 # expected behavior for f in y alert f 1 # surprising behavior
As mentioned in the comment to the original post, generator is proposed as one solution to this problem. To be honest, it seems quite good, syntactically, but this generator syntax is too similar to list comprehension. It’s a matter of taste.