Leandro Lucarella wrote:
retard, el 1 de diciembre a las 11:42 me escribiste:
Tue, 01 Dec 2009 03:13:28 -0800, Walter Bright wrote:
retard wrote:
Overall these simplifications don't remove any crucial high level
language features, in fact they make the code simpler and shorter. For
instance there isn't high level code that can only be written with
8-bit byte primitives, static methods or closures, but not with 32-bit
generic ints, singletons, and generic higher order functions. The only
thing you lose is some type safety and efficiency.
I'm no expert on Python, but there are some things one gives up with it:
1. the ability to do functional style programming. The lack of
immutability makes for very hard multithreaded programming.
Even if the language doesn't enforce immutability it's indeed possible to
use immutable data types in a language without pure/const/final
attributes.
And BTW, Python *have* some built-in immutable types (strings, tuples,
integers, floats, frozensets, and I don't remember if there is anything
else). Python uses convention over hard-discipline (no public/private for
example), so you can make your own immutable types, just don't add
mutating methods and don't mess with. I agree it's arguable, but people
actually use this conventions (they are all consenting adults :), so
things works.
I agree that statically enforced immutability is unnecessary if you are
able to rigidly follow an immutability convention. C++ also has
immutability by convention. People who work in large teams with
programmers of all skill levels tell me, however, that having a
convention and being sure it is followed 100% are two very different things.
I can only speak from experience, and my bug count in Python is extremely
low, even when doing MT (the Queue module provides a very easy way to pass
messages from one thread to another).
How about the GIL?
I agree that, when you don't care much for performance, things are much
easier :)
I would also agree that your bug count and complexity should be low as
long as you're staying within the paradigms that Python (or any
language) was designed to support.
2. as you mentioned, there's the performance problem. It's fine if you
don't need performance, but once you do, the complexity abruptly goes
way up.
In D, there's the simplicity problem. It's fine if you don't need
readability, but once you do, the efficiency abruptly goes way down.
That, I strongly disagree with.
3. no contract programming (it's very hard to emulate contract
inheritance)
True, this is a commonly overlooked feature. I don't know any other
languages than Eiffel or D that support this.
I'm not sure how hard it would be to emulate this feature in languages
where you can define your own class mechanism.
I suspect it is a very hard problem to do with just front end rewriting,
1. I've never seen anyone manage to do it
2. I had to adjust the code generator to make it work
But I don't many people really wants DbC in Python, so I don't think it
would be implemented.
That goes back to if you're staying inside the supported paradigms or not.
4. no metaprogramming
Dynamic languages support dynamic metaprogramming. Ever heard of e.g.
lisp macros?
Exactly! You can even generate code dynamically! This is a very nice
example:
http://code.activestate.com/recipes/362305/
It makes "self" implicit in *pure Python*.
If you say dynamic languages don't have metaprogramming capabilities, you
just don't have any idea of what a dynamic language really is.
Ok, can you do Bill Baxter's swizzler? Can you do Don Clugston's FPU
code generator?
5. simple interfacing to C
In case you mean no unnecessary wrappers etc., this has more to do with
the execution model than language features. Most scripting languages are
interpreted, and require some sort of assistance from the runtime system.
If the language was compiled instead, they wouldn't necessarily need
those.
In D you need interfacing code too, it can be a little simpler, that's
true.
The interfacing in D is nothing more than providing a declaration. There
is no code executed.
6. scope guard (transactional processing); Python has the miserable
try-catch-finally paradigm
WRONG! See the with statement:
http://www.python.org/dev/peps/pep-0343/
with lock:
some_non_mt_function()
with transaction:
some_queries()
with file(fname) as f:
x = f.read(10)
f.write(x)
Looks like you're right, and it's a recently added new feature. I
suggest it proves my point - Python had to add complexity to support
another paradigm. Python's "with" doesn't look any simpler than scope guard.
8. RAII
Ok.
I think this could also be enforced dynamically.
Again, the with statement.
Yes, you can emulate RAII with the with statement, but with RAII
(objects that destruct when they go out of scope) you can put this
behavior in the object rather than explicitly in the code every time you
use it. It's more complicated to have to remember to do it every time on
use.
9. versioning
I don't know why this can't be done dynamically.
It can, and it's pretty common, you can do things like this:
class A:
if WHATEVER:
def __init__(self):
pass
else:
def __init__(self, x):
pass
10. ability to manage resources directly
What do you mean by resource?
Garbage collection isn't appropriate for managing every resources.
Scarce ones need handling manually. Even large malloc's often are better
done outside of the gc.
11. inline assembler
You can do bytecode manipulation, which is the assembler of dynamic
languages :)
That doesn't help if you really need to do a little assembler.
I really think the *only* *major* advantage of D over Python is speed.
That's it.
I probably place a lot more importance on static verification rather
than relying on convention and tons of unit tests.