For example Python does not seem to
have Metaclasses.
It sure does -- it just doesn't implicitly generate a new metaclass for every class: it uses the same metaclass as the parent class, or type
by default. Python's design philosophy, aka "The Zen of Python", can be perused by doing import this
at an interactive interpreter's prompt; the applicable point here is the second one, "Explicit is better than implicit."
In Python 2.X, you specify a custom metaclass with the following syntax:
class sic:
__metaclass__ = mymeta
...
In Python 3.X, more elegantly, you use named-argument syntax:
class sify(metaclass=mymeta):
...
Smalltalk has no
concept of generators.
Python's generators are first-class (typically standalone) functions, and Smalltalk doesn't have the concept of "standalone" functions -- it has methods inside classes. But it certainly does have iterators -- as classes, of course:
iterator := aCollection iterator.
[iterator hasNext] whileTrue: [iterator next doSomething].
Since Smalltalk has first-class "code blocks" (Ruby took them from it), you accomplish iteration, just like other "control structures", by sending a code block to a suitable method, and if you wish you can do that directly with the collection (think select:
):
aCollection select: [:item | item doSomething].
So in Smalltalk (and Ruby) you send the code block to the iteration; Python does things the other way round, the iteration sends values out to the surrounding "calling" code. Looks very different, but not "deeply" different in the end.
First-class code blocks mean that Smalltalk doesn't need nor have "control structure" statements and keywords such as if
or while
: they can be accomplished by sending code blocks as arguments of appropriate methods (e.g. ifTrue:
method of booleans). (Ruby chooses to have the keywords/statements in addition to the first-class code blocks; I would say that Python [[explicitly]] and Smalltalk [[implicitly]] both try, like C, to "offer a single way to perform an operation", while Ruby's more in the Perl-ish school of "there are many ways to do it").
And although
both are said to be dynamicly typed, I
believe that Python does not do
dynamic method dispatch. Is this
correct?
No, absolutely incorrect -- Python intensely does dynamic method dispatch, to extremes. Consider for example:
for i in range(10):
myobject.bah()
By Python semantics, this performs 10 lookups for method bah
in myobject
-- just in case the previous execution of the method had caused myobject
to entirely restructure itself internally so that its current bah
method is completely different from the previous one (might be a pretty insane thing for the programmer to rely on such furious dynamism, but Python supports it). This is the reason that makes:
themethod = myobject.bah
for i in range(10):
themethod()
a common hand-optimization in Python code -- does one dynamic lookup before the loop instead of 10 inside the loop, one per leg (it's a case of "constant hoisting", since the compiler is forbidden from doing the "constant folding" itself by Python's extreme rules for dynamic lookups -- unless it can prove that it's guaranteed to be innocuous, and in practice such proof is too hard so Python implementations typically don't bother).
Python uses unified namespaces: methods are attributes of an object just like any other, except that they're callable. This is why extracting the method without calling it (known as a "bound method"), setting a reference to it in a variable (or stashing it into a list or other container, returning it from a function, whatever) is a plain and simple operation like in the above constant-hoisting example.
Smalltalk and Ruby have separate namespaces for methods and other attributes (in Smalltalk, non-methods attributes are not visible outside the object's own methods), so "extracting a method" and "calling the resulting object" require more introspective ceremony (but the common case of dispatching may be thereby made marginally simpler in certain cases -- in particular, "just mentioning" an argument-less method implicitly calls it, while in Python, like in C, calling is explicitly performed by appending parentheses, while "just mentioning", well... "just mentions" it, making it available for any sort of explicit operation including calling;-).