Tao of the Machine

Programming, Python, my projects, card games, books, music, Zoids, bettas, manga, cool stuff, and whatever comes to mind.

Robijn, fleur en fijn, part 3

More Ruby comments. (part 1, part 2)

I'm really not sure what these procedure objects are good for. At first glance, seems like a hack. On the other hand, it lets you define anonymous functions. Python's lambda isn't as powerful; whether it should be more powerful or should be removed altogether, is an entirely different discussion. :-)

I find the special global variables an atrocity. The names (or rather, characters) have no relation with their function whatsoever.

This syntax for accessors is interesting, but it wouldn't work in Python this way:

ruby> class Fruit
    |   def kind=(k)
    |     @kind = k
    |   end
    |   def kind
    |     @kind
    |   end
    | end


If I have to reach a conclusion, based on my skimming of the tutorial and some other documentation, I would say this:

  • Ruby and Python are more alike than unalike.
  • Being used to Python already, I see no compelling reason to learn a language that's so similar. Ruby doesn't really have any features that I very much want to try out.
  • Although Ruby claims to adhere to "the principle of least surprise", I found many features quite surprising. Python isn't perfect, but it surprises me less. Ruby regularly throws intuition out the door and falls back to Perlish or shell-esque behavior.

Further reading:

Posted by Hans Nowak on 2003-08-22 10:06:37   {link}
Categories: programming

Robijn, fleur en fijn, part 2

OK, now for some comments on the Ruby tutorial...

Note: There are just *comments*. I am not trying to make a point, or to show that Python is better than Ruby or vice versa. I am merely comparing the two languages.

'return' can be omitted: This is a mixed blessing. It makes code shorter, and allows for a syntax that is almost functional (or at least looks that way), like x = if cond then a else b end. On the other hand, "explicit is better than implicit" is probably not a Ruby mantra. IMHO, it makes code slightly less readable.

Regular expressions have special syntax: Is there a good reason for this? I like Python's way better... no special syntax, regexen are strings, and are used via a module.

Arrays have a join method: This is neat. Too bad Python doesn't do it this way. Yes, I am aware that there are good reasons why Python doesn't do it this way. Still, it's nice to see a language that gets it right.

There are also dictionaries (called hashes). I find the syntax a bit unappealing (h = {1 => 2, 3 => 4}). They have a delete method, as opposed to Python, which is slightly inconsistent (using del). On the other hand, Python is consistent in its usage of del to delete names and elements (from lists, dicts, classes, modules...).

Ruby doesn't have goto [correction]. What it does have is loop manipulators: break, next (like Python's continue, which comes from C) and redo (Python has no equivalent for this).

The yield statement seems to be different from Python's, and can lead to some confusing code (at least from a Pythonic point of view). Looking at this,

ruby> def repeat(num)
    |   while num > 0
    |     yield
    |     num -= 1
    |   end
    | end

would you expect that it can be called like this?

ruby> repeat(3) { print "foo\n" }

Methods can be added to instances using the syntax def instance.method. Neat.

The . notation works to get methods from a module, but not constants. For that, we need ::. Compare:

irb(main):003:0> Math.sqrt 4
=> 2.0
irb(main):004:0> Math.PI
NoMethodError: undefined method `PI' for Math:Module
        from (irb):4

:: works for both constants and modules:

irb(main):005:0> Math::PI
=> 3.14159265358979
irb(main):008:0> Math::sqrt 4
=> 2.0

Ruby seems to have special syntax for a bunch of constructs where Python used functions, modules, or other language constructs. Ranges, regular expressions, the each method, switch, etc.

Enough for now...

Posted by Hans Nowak on 2003-08-21 21:12:33   {link}
Categories: programming


I just uploaded an old project: Tarantulon, a webcrawler. (Find it in the download area.) Back in the day (1999), I could not find an acceptable web spider, so I wrote one myself in Python. (Some would call it a "websucker"; it makes an offline copy of a website.)

Now this code is old; I haven't updated it in a while, it needs some serious refactoring, has missing features, etc. Still, it's usable. Just experiment with tarantulon.py (and inspect the source for command line params). There's also a bunch of test files and some other scripts.

Tarantulon is now Ikeaware. That means, if you buy me this snake, you'll get 10 hours of Tarantulon development. Is that a deal or what? emoticon:smile

Posted by Hans Nowak on 2003-08-21 20:57:40   {link}
Categories: Python

Robijn, fleur en fijn

With all the talk about Ruby in blogs and troll-initiated c.l.py threads, I took a(nother) look at a Ruby tutorial. Remarks on that later. For what it's worth, here are some comments on 37 reasons I love Ruby. Most, though not all, of these reasons apply to Python as well. (I comment on the reasons that don't apply.)

20. It uses punctuation and capitalization creatively. A method returning a Boolean result (though Ruby doesn't call it that) is typically ended with a question mark, and the more destructive, data-modifying methods are named with an exclamation point. Simple, informative, and intuitive. All constants, including class names, start with capital letters. All object attributes start with an @ sign. This has the pragmatism of the old "Hungarian notation" without the eye-jarring ugliness.

Yes, recently I've been wondering why Python doesn't allow the ? character in identifiers. It would make names a bit clearer.

21. Reserved words aren't. It's perfectly allowable to use an identifier that is a so-called "reserved word" as long as the parser doesn't perceive an amibiguity. This is a breath of fresh air.

It's too bad that Python doesn't work the same way, although I've come to expect that reserved words cannot be used as identifiers *ever*, coming from Pascal. Still, it's an eyesore (and counter-intuitive) that you have to write self.assert_(something) (unittest), or pop3.pass_(password) (poplib).

23. It has safety and security features. Ruby borrows Perl's concept of tainting and allows different levels of control (levels of paranoia?) by means of the $SAFE variable. This is especially good for CGI programs that people will try to subvert in order to crack the web server.

I'm not sure how much "safety" this guarantees (mostly because I don't know enough about Ruby). Python doesn't really have such a concept. Bastion was declared unsafe. Even pickling seems to have security issues. Then again, I generally don't worry much about those. :-)

25. It pays attention to detail. Synonyms and aliases abound. You can't remember whether to say size or length for a string or an array? Either one works. For ranges, is it begin and end, or first and last? Take your pick. You spell it indices, and your evil twin spells it indexes? They both work.

This is part of TMTOWTDI, and the opposite of the Python philosophy. That doesn't mean that there's just one way to do something in Python... often there *are* multiple ways, but those are usually there for a good reason. (Hmm, maybe an article on "there's only one way to do it" and how it does (not) apply, would be an idea.)

26. It has a flexible syntax. Parentheses in method calls can usually be omitted, as can commas between parameters. Perl-style quotes allow arrays of strings without all the quotation marks and commas. The return keyword can be omitted.

TMTOWTDI again. Python generally doesn't like multiple syntax for the same feature. 1) Especially not if it makes things less clear. A function call uses parentheses; if you refer to the function object itself, you don't use them. No ambiguity here. Compare:

>>> s = "abc "
>>> a = s.strip
>>> b = s.strip()
>>> a
<built-in method strip of str object at 0x0165DA20>
>>> b

irb(main):022:0> s = "abc "
=> "abc "
irb(main):023:0> a = s.strip
=> "abc"
irb(main):024:0> b = s.strip()
=> "abc"
irb(main):025:0> a
=> "abc"
irb(main):026:0> b
=> "abc"

How do I refer to method s.strip without calling it? I don't know yet, have to read the tutorial. But it seems to me that it must require special syntax. Python wins here, IMHO (although YMMV).

31. It is expression-oriented. You can easily say things like x = if a<0 then b else c.

By design, Python is not.

Maybe it's time to take a closer look at Ruby. (I do hope the Ruby installer doesn't overwrite my Tk/Tcl settings again, though...)

1) There are exceptions, of course. Single- and double-quotes strings, for example, or <> and !=, etc.

The title of this post is an obscure reference to a Dutch laundry detergent. Don't try to understand it. :-)

Posted by Hans Nowak on 2003-08-20 19:12:26   {link}
Categories: programming

Destroy him, my robots

I don't have anything interesting to write, so here's a short list of essential C64 games you should download. :-)

  • Movie Monster: Play a monster that destroys a city. Choose from a huge dinosaur, insect, blob, robot and more.
  • Impossible Mission 2: Somersault through various rooms filled with robots, to collect information.
  • Defender of the Crown: Do the knightly thing in old England, besieging cities, competing in tournaments, rescuing damsels in distress, and conquering some counties while you're at it.
  • Katakis: R-Type-like shoot-em-up, with (for that time) excellent graphics.
  • Ricochet: Wacky, WACKY breakout clone. Gravy on everything.
  • California Games: Compete in 6 Californian events, including surfing, BMX racing, rollerskating, and hacky-sack.
  • Paperboy: Deliver newspapers in a street crowded with joggers, dogs, skaters, trash cans in strategic positions, cars, and more.
  • Alter Ego: A game that simulates your life, how it could/should have been (or maybe not).
  • Kung-Fu Master: Good for at least a few minutes of fun as you kick down big enemies and jump over midgets. :)
  • Law of the West: Sheriff in a wild-west town deals with desperados, a cattle rustling woman, the always drunken doctor, a backstabbing deputy, and more.

Posted by Hans Nowak on 2003-08-19 23:33:53   {link}
Categories: nostalgia, games

So you want to be a...

In the category "weird stuff": Whigger Dressup. (From the makers of Jesus Dressup, I reckon?)

Is it spelled "wigger" or "whigger", by the way? Google says:

whigger: 1,170 hits
wigger: 42,700 hits
wigga: 4,460 hits

Nuff respect. Google's da bomb.


In other news, here's an ongoing Mirrodin spoiler [mtgnews]. The new set seems to focus on artifacts and has some interesting new features. Provided these rumors are true, that is. Most things here seem reasonable, except for Fiery Gambit -- I thought R&D didn't like coin flips anymore? Of course, I could be wrong.


More Mac weirdness: I still have the strange connection problems described yesterday (to the Apple site no less); however, they disappear when I connect directly with PPPoE. So I tried Sherlock again... it finds the channels now, but for Yellow Pages and Movies it says, "You need to upgrade to Mac OS X 10.3 or later to use this version of the Movies Channel." Cool, I would do that if 10.3 was out yet!

This doesn't make any sense. Maybe it has something to do with the security updates I installed yesterday. These features are so secure now, that even I cannot use them. ^_^;

Posted by Hans Nowak on 2003-08-18 13:15:05   {link}
Categories: general, CCGs

Back to the grill again

I was going to try my hand at designing a new game today, but Mac problems got the best of me. 90% of the work is done in 10% of the time, and vice versa, stuff like that.

This is not another Mac rant. In fact, what I wanted worked quite well. Only, there's a few things that don't work, and it puzzles me very much.

Anyway, my modem/router has both a USB port and an Ethernet port. PC uses USB, Mac uses Ethernet. So, I wondered if I could connect to DSL with my PC, then have the Mac share the same DSL connection (without having to authenticate, dial in, etc). After some tinkering, this indeed seemed to work. I appear to have a little (and probably malfunctional in some ways :-) LAN now, allowing me to share folders between PC and Mac. Great stuff, and maybe it'll be possible to share the printer too. Also, I can surf the Net as usual... browsers, ftp, NetNewsWire, Proteus, etc.

What *doesn't* work is Sherlock and Software Update. Sherlock cannot get the resources it needs. Upon inspection, this seems to be a regular HTTP call. An example URL is this. The Mac, in it current state, cannot retrieve this file. Not with Sherlock, not with a browser, not with wget, not with anything. I can, however, fetch this URL with no problem on Windows, and the Mac didn't have a problem with it before (using a PPPoE connection for DSL). This confuses me greatly. What is so special about this URL (and probably a bunch of other URLs like it) that it cannot be retrieved? It's not a name resolution conflict; wget resolves the name just fine, but the HTTP request times out. It's not a weird port or protocol either, just a HTTP request over port 80. And I can ping si.info.apple.com just fine. emoticon:confused

I suppose I don't really *need* Sherlock, and for the Software Update I can always make a "real" DSL connection (rather than sharing the PC's), once a month or whatever. Still, this is an interesting puzzle.

Other Mac observations:

  • My site doesn't look good in Mac browsers (like IE 5.2 and Safari 1.0). Needs fixed.
  • MacPython 2.3 for OSX installs, and seems to work (although IDLE crashes).
  • wxPython works as well. I even got to run the demo. ^_^ Maybe there's hope. Great work from Python and wxPython developers.

Posted by Hans Nowak on 2003-08-17 21:08:30   {link}
Categories: switch, Python

A rat repellent for your registry

I'd like to thank everyone who mailed me with suggestions for anti-pitfalls. I'm still pondering what features would be suitable for the article. Meanwhile, back at the labs...

In the heroic battle against the forces of evil, some progress has been made. I installed AIM the other day (because I tried to find someone on the Net), and it seemed polite, at first glance... Then I saw that it put shortcuts everywhere, even though I told it not to. Worse, I discovered that it nestled itself in certain parts of my registry, so it starts every time Windows starts.

How rude. I don't want it to start automatically, especially because it crashes on my computer (for whatever reason). So, it was time again to search the registry and remove the key that causes this behavior. However, this happens fairly often, so I decided to (finally) write a little script that helps me remove these unwanted keys.

The result can be found here: reginspector. It's a simple script, a bit basic-y in fact. It inspects those parts of the registry that Windows uses to auto-start programs (and some services). It shows a list of keys, for example like this: 1)

Section: HKEY_LOCAL_MACHINE Software\Microsoft\Windows\CurrentVersion\Run
[ 1] 'Synchronization Manager': mobsync.exe /logon
[ 2] 'ConMgr.exe': "C:\Program Files\EarthLink 5.0\ConMgr.exe"
[ 3] 'Iomega Startup Options': C:\Program Files\Iomega\Common\ImgStart.exe
[ 4] 'Iomega Drive Icons': C:\Program Files\Iomega\DriveIcons\ImgIcon.exe
[ 5] 'NeroCheck': C:\WINNT\system32\NeroCheck.exe
[ 6] 'PrinTray': C:\WINNT\System32\spool\DRIVERS\W32X86\2\printray.exe
[ 9] 'TaskReg': C:\WINNT\system32\w3app.exe
[10] 'TangoManager': C:\PROGRA~1\EFFICI~1\TANGOM~1\app\TANGOM~1.EXE
[11] 'Tweak UI': RUNDLL32.EXE TWEAKUI.CPL,TweakMeUp

If you see unwanted elements, you select a number, and the key is deleted (after confirmation). If you don't want to delete anything, just press Enter. That's all.

The usual disclaimers apply, even more so than normal. So, just so there are no misunderstandings: This program writes to your registry. Use at your own risk.

On a side note, writing it was not as easy as it seems... For starters, the documentation of the _winreg module lacks examples, which makes it a bit hard to use the module if you're not familiar with the Windows API. Effbot guide to the rescue. Also, I kept wondering why DeleteKey didn't work... after a lot of frustration, I found out that I should have used DeleteValue instead. emoticon:bonk

Ah well. Enjoy, and let me know if there are any bugs.

1) displayed smaller so it doesn't mess up my (table-oriented, semantically-incorrect) layout on 800x600 ^_^

Posted by Hans Nowak on 2003-08-16 22:17:40   {link}
Categories: Python

Generated by Firedrop2.