Complaints about a language usually come from people who dislike the whole thing. Those who are passionate about a language may be more insightful to its own shortcomings.
Python: one case where I believe explicit is not better than implicit is the explicit passing around of self. It just seems to add extra clutter to the code, as well as demanding a certain cognitive overhead in remembering that a function is defined with N parameters but is invoked with N-1.
Perhaps there are good reasons for it, but generally I prefer java's implicit 'this.'
I'm not sure that it's a good reason, but the explicit self allows for weird intermingling of functions and members. For instance,
class foo:
def __init__(self,val):
self.x=val
def square(self):
return self.x**2
#imperative way
imperative = [foo(x).square() for x in range(5)]
#functional way
s = foo.square
composed = lambda x: s(foo(x))
functional = map(composed,range(5))
print imperative==functional
The explicit self allows you to treat member functions as generic function and compose them in a functional way. Now, most functional programming isn't necessarily Pythonic. However, given a proper compose function, I could imagine it being useful to mix a long chain of function and member calls without needing to make a distinction between the two.
Ruby: too slow. Love the language, makes me happy to code in, but compared with other languages I use (Common Lisp, Java, Clojure) it is slow. That said, for many applications execution speed does not matter.
I found it a little confusing ready ruby code that omits parentheses, but sometimes I feel like a method call with no input params shouldn't need parens
None of the code I want to install on my hard drive is written in Scheme (except a Scheme compiler).
Also, Scheme cannot practically be used as an interactive command processor and file-name-space browser like a Unix shell can. (Yes, I know about scsh; I do not like it.)
I agree with the python one.
Some more things I find annoying in Python:
- Hardcoded recursion limit + no tail call optimization. I understand Guido's reasons for this but I find myself writing ugly code instead of beatiful code. (But maybe changing this would make Python's internals ugly.)
Mainly Python but other languages too.
- Length of the collection: len(foo). String representation: str(foo). Why not foo.len() or foo.str().
Or even better: foo.len or foo.str.
As a Python user, I'm not a fan of getters. I think we should use the "attribute syntax" to get data about and of the object/type/thing, regardless if it involves any computations or not.
(but would probably generate more problems than solve little nitpicks)
I second the Python one. Why the wierd distinction between packages, modules, and things in files?
I believe all of these three should give me os.path.isdir:
import os
import os.path
import os.path.isdir
os.path.isdir(...)
And to get isdir() directly, I would use either:
from os.path import isdir
import os.path.isdir as isdir
This should work if path is either a package (a directory), a module (a file), or an object defined in os.py!
Sometimes, for some reason if I only import a module, I can't use submodules. So `import os` wouldn't give `os.path.isdir`. I don't know when that occurs, maybe it was in an ancient version of python. But it leaves me with an uneasy feeling every time I use a submodule. Anyone know when this happens?
Last but not least, it should be easier to import stuff from above the script. If my script lives at ./tools/foobar.py, and I want to import ./helper.py, it should just be something like
Python: The fact that they broke the syntax with Python 3, splitting the language in two parts: one that is widely deployed, and one that is actively developed. I never had the luck to use Python 3 in actual work.
If I could, I would make Python 5 (2+3=5), which is Python 3 but accepts all the legacy syntax of Python 2 (especially the print statement).
I'd solve the str/unicode problem by providing
bytes, str, unicode = python5.legacy_strings
or
bytes, str, unicode = python5.modern_strings
that you would put at the top of the file. I'd make the modern strings builtin for system modules, or files with the .py5 extention. Problem solved.
(mapcar 'funcall
(loop for x below 3
collecting
(lambda () (print x))))
producing:
3
3
3
(3 3 3 )
OK, it is the loop DSL that chooses to rebind the same variable over which I closed, but loop is in the standard so I'll blame lisp. The syntax really looks like a fresh binding. Shucks, this is almost a bug: the loop implementation was allowed to leak into the loop semantics.
Go: no generics, the community is small, Go allows you to use functions as data (to some extent), but doesn't take advantage of this to the extent that it could. I'm relatively new to the language, so my observations may either be incorrect or not include the full picture. If anyone has anything to chime in or, I'd love to hear.
24 comments
[ 3.4 ms ] story [ 59.2 ms ] threadPerhaps there are good reasons for it, but generally I prefer java's implicit 'this.'
SQL - you SELECT fields before you specify what table they come from, so tooling is virtually impossible.
Haml: Hard to control whitespace around elements.
SQL: Can never remember which date functions go with which RDBMS.
Also, Scheme cannot practically be used as an interactive command processor and file-name-space browser like a Unix shell can. (Yes, I know about scsh; I do not like it.)
Javascript: semicolon insertion
Erlang: periods, commas and semicolons
Clojure: not much, actually
PHP: ugh, nearly everything
Python: lambdas can only have a single expression
Everything except Lisps: expression/statement dichotomy
Javascript: Lacks support for 64-bit integers and arbitrary-precision decimals.
SQL: SQL injection.
- Hardcoded recursion limit + no tail call optimization. I understand Guido's reasons for this but I find myself writing ugly code instead of beatiful code. (But maybe changing this would make Python's internals ugly.)
Mainly Python but other languages too. - Length of the collection: len(foo). String representation: str(foo). Why not foo.len() or foo.str(). Or even better: foo.len or foo.str. As a Python user, I'm not a fan of getters. I think we should use the "attribute syntax" to get data about and of the object/type/thing, regardless if it involves any computations or not. (but would probably generate more problems than solve little nitpicks)
[1]http://docs.python.org/2/library/sys.html#sys.setrecursionli...
As for tail-call optimization, here's Guido's opinion (which I agree): http://neopythonic.blogspot.pt/2009/04/tail-recursion-elimin...
I believe all of these three should give me os.path.isdir:
And to get isdir() directly, I would use either: This should work if path is either a package (a directory), a module (a file), or an object defined in os.py!Sometimes, for some reason if I only import a module, I can't use submodules. So `import os` wouldn't give `os.path.isdir`. I don't know when that occurs, maybe it was in an ancient version of python. But it leaves me with an uneasy feeling every time I use a submodule. Anyone know when this happens?
Last but not least, it should be easier to import stuff from above the script. If my script lives at ./tools/foobar.py, and I want to import ./helper.py, it should just be something like
and not or what I'm using nowIf I could, I would make Python 5 (2+3=5), which is Python 3 but accepts all the legacy syntax of Python 2 (especially the print statement).
I'd solve the str/unicode problem by providing
or that you would put at the top of the file. I'd make the modern strings builtin for system modules, or files with the .py5 extention. Problem solved.(mapcar 'funcall (loop for x below 3 collecting (lambda () (print x))))
producing:
3 3 3 (3 3 3 )
OK, it is the loop DSL that chooses to rebind the same variable over which I closed, but loop is in the standard so I'll blame lisp. The syntax really looks like a fresh binding. Shucks, this is almost a bug: the loop implementation was allowed to leak into the loop semantics.
NSString *result