Wow, I wish there were some sort of universal wisdom involved, but
I'm pretty sure it was a combination of pragmatism and a personal
bias toward a particular sort of elegance and aesthetics in language
design that appeals to my own sensibilities. (In other words, matz kicks
ass at language design!)
Of course, some languages were easier to loathe than others. <grin>
This article pretty well summarizes the sort of horror I felt when
dealing with VB6:
http://www.ddj.com/windows/184403996
As for Python, i tended to find the experience more frustrating and
less fun than writing comparable code in Ruby. Learning Ruby, for me,
involved a lot of "oh, wow, cool I can do that!" Whereas learning Python
I noticed a lot more, "oh... I'm not allowed to do that."
I last used Python about six years ago, and I understand some things
have evolved or improved since then (don't they have something more
akin to Ruby blocks now? And list comprehensions?)
But anyway, a few examples of things that rubbed me the wrong way
about Python. (Note, these may be things that Python people
absolutely love about the language!)
I found the distinction between expressions and statements, and the
restrictions on where one or the other could occur in the syntax, to be
very rigid and unhelpful.
For example, the syntax is:
if expression:
statement
elif expression:
statement
else:
statement
And assignments are not allowed in expressions.
Thus, code that I wanted to write in Python like this, is illegal:
while match = tagOrTextRegexp.search(html, pos):
pos = match.end()
gd = match.groupdict()
if (val = gd.get('startTag')):
attrs = parseAttrs(gd['allAttrs'])
self.handleStartTag(val.lower(), attrs)
elif (val = gd.get('endTag')):
self.handleEndTag(val.lower())
elif (val = gd.get('text')):
self.handleNonTagText(val)
elif (val = gd.get('comment')):
pass # ARTHUR (to KNIGHTS) Walk away. Just ignore them.
else:
assert 0, "unexpected match in regexp - supposed to be impossible"
...ended up being written like this:
while True:
match = tagOrTextRegexp.search(html, pos)
if match is None:
break
pos = match.end()
gd = match.groupdict()
# no assignment-in-conditional sux, Guido
val = gd.get('startTag')
if val is not None:
attrs = parseAttrs(gd['allAttrs'])
self.handleStartTag(val.lower(), attrs)
else:
val = gd.get('endTag')
if val is not None:
self.handleEndTag(val.lower())
else:
val = gd.get('text')
if val is not None:
self.handleNonTagText(val)
else:
val = gd.get('comment')
if val is not None:
pass # ARTHUR (to KNIGHTS) Walk away. Just ignore them.
else:
assert 0, "unexpected match in regexp - supposed to be impossible"
I found this sort of thing very annoying, as can be seen from the note
I left in the code for Guido (von Rossum, Creator of Python.) <grin>
Another example would be class methods. (As opposed to instance methods.)
I remember how hacky and inelegant it seemed to me that every instance
method in Python needed to explicitly list the 'self' parameter:
class Foo:
def bar(self):
print "bar!"
f = Foo()
f.bar
But when I was learning Python, I had an insight and thought, well, at least
I know how to define class methods! Just leave off the self parameter!
class Foo:
def a_class_method(x,y)
return x+y
Then I should be able to call it directly on the class, with no instance passed
in:
Foo.a_class_method(1,2)
Nope. Just doesn't work. No way to define class methods. (Dunno if this
has changed in the past six years or not.)
Anyway, I don't recall many other examples anymore, but I vividly remember
feeling frustrated in this manner often enough while learning Python that I
would actually exclaim, "Guido!!!!" out loud at my desk when it would
happen. (But I should point out that I was still having fun. After all, I enjoyed
programming in Python _a lot_ more than Java.)
Finally, I suppose this is a bit silly, but my very first few minutes with
Python gave me a tangible feeling of trepidation when the following
happened:
I fired up Python (whatever the version was back then), and I got an
interactive interpreter. I was like, yay! cool!
Python 2.4.1 (#1, May 27 2005, 18:02:40)
Type "help", "copyright", "credits" or "license" for more information.
Then I tried to quit:
And I thought... Oh no. Somebody actually knew exactly what I
wanted the computer to do - and actually went through the trouble
to program a message to tell me I was doing it wrong.
But again, while these are aspects of Python that rubbed me the
wrong way, I realize that others may and do feel completely
differently. If Ruby didn't exist, I'd have probably have used
Python for quite a while (maybe moving on to OCaml or Erlang
by now, I dunno.)
And why did you stop using Forth? Is there *really* a way to break the
addiction?
Hehe.
I would totally still use Forth for embedded systems programming.
How else could one get an entire dynamic interactive extensible image-
based language with its own compiler and interpreter and editor and
assembler into a few KBytes of memory.
What occurred to me over the years, though, was what really made
Forth so remarkable was its achievement of providing such a dynamic
environment out of such utter sheer simplicity of code and memory
architecture.
There's a lot of beauty in an entire interactive compiler / interpreter
system with a main loop that looks like:
: QUIT ( -- ) BEGIN RESET QUERY INTERPRET AGAIN ;
And of course RESET, QUERY, and INTERPRET are quite simple
themselves. And it's like, Wow! All this dynamicity from such a
beautifully simple architecture!
But as computers got bigger and bigger memories and faster
CPU's, hard drives, file systems, operating systems... I started
to want features that would add complexity to the Forth system,
such as heap-based memory allocation, hashed headers to compile
faster (now that my system included thousands and thousands
of words for interfacing with the operating system), etc...
And eventually Forth wasn't so simple anymore.
And I think Forth's simplicity is part of its appeal... so I started to
hit a wall.
I'll admit I've sometimes wondered what a Forth system would be
like, though, if one took Ruby's VALUE type and made everything
on the data stack something akin to a ruby VALUE. So that
elements on the data stack would become actual objects with
an associated type... and ... well anyway... I guess it would be
sort of a cross between Ruby and Forth. <grin>
But anyway... now I have to get back to some C++ code. (But
tomorrow back to getting paid to code Ruby! Yay!)
Regards,
Bill