Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Smalltalk (Pharo for example) compare to Python?

I've seen some comparisons between Smalltalk and Ruby on the one hand and Ruby and Python on the other, but not between Python and Smalltalk. I'd especially like to know what the fundamental differences in Implementation, Syntax, Extensiabillity and Philosophy are.

For example Python does not seem to have Metaclasses. Smalltalk has no concept of generators. And although both are said to be dynamicly typed, I believe that Python does not do dynamic method dispatch. Is this correct?

like image 891
Richard Durr Avatar asked Oct 02 '09 08:10

Richard Durr


1 Answers

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;-).

like image 160
Alex Martelli Avatar answered Nov 02 '22 23:11

Alex Martelli