Tao of the Machine

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

Groovy (3)

A bit more Groovy stuff...

From the groovy-dev mailing list: "You can now define functions in scripts which can be very useful in shell-scripty type use cases. Here's an example test case..."

def foo(list, value) {
     println "Calling function foo() with param ${value}"
     list << value
}

x = []
foo(x, 1)
foo(x, 2)
assert x == [1, 2]

println "Creating list ${x}"

Nice, this makes things more Pythonic and scriptable. I don't like the new << operator... lists already have an add method that does the same; what's the point of adding a redundant operator that looks like line noise?. Then again, let's not forget that Groovy doesn't have the same design philosophy as Python...

The expression 1..3 creates a list [1, 2]. In other words, the upper bound is not inclusive. This is kind of counter-intuitive, methinx... Haskell has a similar construct that does the right thing, if I recall correctly. Of course, Python's range(1, 3) returns the same list, but for some reason the .. operator "feels" to me like it should include the upper bound. Hmm.

Also, code like

for (i in [1..10]) {
        println(i)
}

doesn't do what you might expect... [1..10] is a list with one element, viz. a list containing the numbers 1 through 9. When you want to loop over such a list, use for (i in 1..10) instead.

That's it for now. I'm glad to see that the language is in steady development, and that new, useful features are added regularly. I do get the feeling that the language somewhat lacks a coherent design philosophy, but it could also be that the creator is still looking for that. Time will tell. But with its dynamic features, code blocks, and ties to the Java libraries, there's enough reason to start using it.

Update. Apparently the CVS version of Groovy has different behavior for the .. operator. 1..3 is now [1, 2, 3], and 1...3 is [1, 2]. I'm not sure how often changes like this happen... I'm aware the language is under heavy development, but this makes me a bit worried about using it for production code.

Posted by Hans Nowak on 2004-01-16 23:04:10   {link} (see old comments)
Categories: programming

Snippets

Around 1998-1999 I created and maintained the Python Snippets site. It was a collection of small Python scripts, modules and demos, meant to illustrate certain programming principles or solve certain problems.

Before Python, I had been using Turbo Pascal as my main language, and often benefited from the so-called SWAG archives, that contained lots of snippets of Pascal code. I figured that a similar archive for Python would be a nice thing to have. So I started collecting pieces of useful Python code, most often from newsgroup posts.

I didn't have much control over my server at the time, just FTP access... I could upload files but not much more. So all I could do was uploading the snippets (most of them .py files), and generate pages that categorized them and linked to them. There was no search function, no way for readers to submit their own code, etc. The only way to get new snippets was to scan the newsgroup relentlessly, looking for new pieces of code that seemed worthwile. There were not many user contributions. Eventually I got too busy to maintain the site much, and it kind of stagnated. I then donated all the snippets to the Python FAQTS page. (They can still be found there.)

After a while, the idea was, um, borrowed by the ActiveState Python Cookbook site. The rest, as they say, is history. Their site was more professional and user-friendly, and got lots of contributions, eventually culminating in a paper version of the Python Cookbook.

For kicks and giggles, I uploaded the old collection of snippets. Maybe it will be of interest to someone. There are ~400 snippets. As said, this is mostly code done by others, as seen in the newsgroup. The archive includes a number of previously unpublished snippets as well. Note that I make no guarantee about the usefulness of this code, nor of its validity, years later. (Most, if not all, code was for Python < 2.0.) Anyway, snippets.zip can be found in the download area, as usual.

Posted by Hans "geniet, maar programmeer met mate" Nowak on 2004-01-15 23:35:22   {link} (see old comments)
Categories: Python

Welkom in mijn laboratorium

A short overview of the projects in the download section, and what I hope to do with them in 2004.

  • Antilog: Simple Apache log file reader. Could use a patch or two, but I don't expect much further development.

  • Charm: Python IDE/editor. Like with many of my projects... I use it myself, but it's not ready for prime time yet. Possibly lots of stuff can be added. Support for other languages, integration with Bicycle Repair Man, better editor functions, etc. Requires Wax.

  • Firedrop: Client-based CMS. Now that some people (besides me) are actually using it, and with a Py article coming up (probably), I plan to add a lot more features, if I have time. Needs to become more user-friendly, and to grow more content types. Requires Wax.

  • Google In-Depth: Small project to interpret Google search results, and download files based on them. Probably no further development.

  • Kaa: Client-based blogging tool. Development has not stopped yet, but Kaa will eventually be replaced by Firedrop.

  • pic2html: Silly little program to convert small pictures (BMP, icons) to HTML tables using CSS. Probably no further development.

  • PyZetaLisp: Lisp interpreter written in Python. Could definitely use more features, but it's really a toy project, so this is not one of my priorities. Python integration could be better though.

  • reginspector: Small script to inspect the Windows registry. Seems done.

  • selfish: Self-style classes in Python. Probably room for improvement, but not really important.

  • Sextile: Text-to-HTML format, loosely based on Textile. There's definitely room for improvement, and maybe Sextile will grow macros. If at all possible, I'll want to write my book in this. Expect more in 2004.

  • Tarantulon: Makes offline copies of websites. Originated in 1999, this code is getting a bit old, and there's lots of room for refactoring and rewriting. Not one of my top priorities though.

  • Testipy: Simple testing framework. May grow a few more features; I'm content with it as it is, though.

  • Wax: GUI framework; a friendly layer on top of wxPython. Important. Some people are actually using it. Should see lots of new features this year (or so I hope).

The other files in the download directory are old DOS executables and the Python 0.9.1 source code.

For more information, see the labs main page.

Posted by Hans Nowak on 2004-01-14 23:04:37   {link} (see old comments)
Categories: Python

Betta diseases

It seems that when you have a lot of bettas for a year or two, you are treated to a grand tour of fish diseases and ailments.

Our latest encounter is a disease called pop-eye. Like the name suggests, the fish's eye swells up to monstrous proportions. It's really hard not to notice. Fortunately, it can be cured (or so I'm told... I have yet to find out).

Other diseases that I've encountered are:

  • ich: little fuzzy things appear on the fish, like somebody brushed it with cotton wool. Curable.

  • fin rot: like the name says, fins rot away, sometimes exposing the bones. Looks yucky, but it's curable, and the fins will usually grow back (although they might not regain their original size and color).

  • dropsy: fish swells up, its scales stand out, making it look like a pinecone. NOT curable.

Bettatalk has a more complete overview of betta diseases.

Posted by Hans Nowak on 2004-01-13 20:31:02   {link} (see old comments)
Categories: bettas

Groovy (2)

More on Groovy. This language turns out to be an interesting alternative to Python (maybe), although I don't necessarily like all its features. For example, there seems to be a lack of functions. Granted, these can be emulated with "closures" (I'd much rather call these "code blocks", but it seems to be a part of the official terminology).

add = { a, b | return a + b }

This defines a closure that acts much like a function. It takes two arguments and returns their sum. Using it is unsurprising:

a = add(3, 4)
println(a)

The manual claims that a function call's parentheses can be omitted in certain cases (if there's no ambiguity), but that doesn't always seem to be the case:

b = add 5 6
println(b)

This prints something like calls1$1@12d7a10... strange. And add 5, 6 is an error. It doesn't (always) work with one parameter either:

id = { x | x }

a = id(42)
println(a)
# prints 42

b = id 43
println(b)  # same here... doesn't work as intended

Aside from that, closures can be really nice. This is how a list of numbers can be mapped to a list with double the values:

list = [1, 2, 3, 4]
a = list.map { it * 2 }
println(a)
# [2, 4, 6, 8]

The "official" syntax would be list.map({ it * 2}), but in this case the parens can indeed be omitted. I'm not sure I like that feature, although it does seem to make this code a bit more readable.

it is an implicit variable. By default, closures take one argument, called it. A different name can be specified, and so can multiple arguments. For example, the line with list.map could be written like this:

a = list.map { num | num * 2}

Python could do this with a lambda, of course, or by defining a named function first. Neither solution seems ideal, though, when the code block gets a bit more complex. This is one area where Groovy seems better than Python. (And maybe Ruby, considering it has code blocks as well.)

A strange quirk:

b = list.map({ 0-it })
println(b)

This works, but using -it does not, for some reason. I have yet to figure out why not.

A with (like in VB and Pascal) can be specified... more or less. The parentheses are in the way, kind of. Maybe there's a better syntax for this.

with = { obj, closure |
         closure.call(obj)
}

with(lst, {
    println(it)
    println("list size: " + it.size())
})

# prints:
# [1, 2, 3, 4]
# "list size: 4"

/* cannot be written as:
with list {
    println(it)
    println("list size: " + it.size())
}
*/

Note the power of closures here... in Python, we could write a with that takes a list and a function, but not a code block. Apparently closures are used a lot in Groovy, maybe a bit too much... it doesn't always make things clearer.

More later. Too bad there's not too much documentation on these closures. The mailing lists seem to be active, though, maybe I can pick up some more information there.

Update. When fleshing out new Groovy features, it seems that many people like a syntax that mimicks (or is close to) Java's. I'm not sure that's a valid argument. Sure, similarity of syntax may be nice for people coming from Java. But languages like Groovy (and BeanShell, etc) also attract a different crowd: those who don't like Java, but who wouldn't say no to a dynamic language that uses the Java libraries. 1)

I don't know the proportial sizes of these groups (Java-background vs non-Java-background), but it may be a good idea to go for the "best" syntax (whatever that means), rather than going for a Java-like syntax, disregarding all other considerations.

1) This includes Jython too, but like I pointed out in my previous Groovy post, I cannot use Python for this upcoming project.

Posted by Hans Nowak on 2004-01-13 19:32:22   {link} (see old comments)
Categories: programming

Groovy

I am currently looking at Groovy. It's a hybrid of Java, Python and Ruby, that runs on the JVM. Much like Jython, it gives programmers the power of a dynamic language, while retaining access to the vast Java libraries.

I could just use Jython, but for the project we have in mind (for work), we cannot use Python or Delphi, for non-technical reasons. (We cannot reuse any code from existing Python/Delphi projects, and the safest way to do so is to use a different language.)

Groovy seems nice. Close enough to Python for me to like it. :-) It has lists and dictionaries (although the syntax of the latter seems a bit awkward). More importantly, it has code blocks, known as "closures" (which name is a bit unfortunate, IMHO... they're not like Lisp/Scheme closures).

Much of the new constructs and syntax are like Ruby, but seem a bit less hairy. It also seems a bit more readable.

Installing it wasn't so difficult, even for someone who doesn't have much experience with Java, like me. I had to tweak a batch file or two, because they called the command shell to verify something, which caused odd effects on my console screen. After setting the correct environment variables, everything worked. groovysh is an interactive interpreter, not as powerful as Python's, but usable nonetheless.

At the moment, I have a hard time understanding this code:

class Foo {
  myGenerator(Closure yield) {
    yield.call("A")
    yield.call("B")
    yield.call("C")
  }
}

foo = new Foo()
for (x in foo.myGenerator) {
  print("${x}-")
}

That is, I can see what it does... but it's unclear how it does it. Foo.myGenerator looks like a method. But when for (x in foo.myGenerator), that method is not called. Or is it? If so, what happens to the yield parameter? Is it implicit? I would like to know more about the inner workings of this construct.

Hopefully this is explained somewhere else. More later.

Posted by Hans Nowak on 2004-01-12 12:30:18   {link} (see old comments)
Categories: programming

Books: Assassin's Apprentice / Royal Assassin / Assassin's Quest

The Farseer Trilogy, by Robin Hobb

  • Assassin's Apprentice
  • Royal Assassin
  • Assassin's Quest

Spoilers ahead...

These books describe the life of Fitz (or FitzChivalry as he is known later), the bastard son of prince Chivalry of the Six Duchies. Taken away from his mother at age six, he starts living at the castle of Buckkeep, where he is trained in many skills... including those of an assassin. These skills come in handy when the kingdom is threatened from several sides: pirates raiding the coasts, and treachery from within the royal family.

For an assassin, Fitz seems kind of... wimpy. He's more of a spy and a diplomat than anything else. His assassinations often consist of slipping some poison into someone's food or drink. An assassin is not a brawler, but you'd think he could hold his own in a fight, knowing lots of clever tricks and lethal strikes, and having plenty of hidden weapons handy. This does not seem the case. Fitz does win some fights, but often takes great damage. Also, it's kind of annoying that he often is powerless against his enemies, simply because he is not allowed to kill members of the royal family, or their servants.

I like the first two books very much. The third one is a bit disappointing. I just like simple stories where the guy gets the girl. ;-) That doesn't happen here. Nor does Fitz seem to succeed in some of his goals, and quite a few of his friends and bond-animals die along the way, making the books somewhat frustrating to read.

Overall, good books, but not always an easy read.

Posted by Hans Nowak on 2004-01-11 12:29:27   {link} (see old comments)
Categories: books

The light side beckons

Another content Mac user. Maybe I should give the thing another try. I agree with Simon's observations... a weird key binding here and there, but aside from that everything Just Works, and looks gorgeous. (On Windows, the first thing I do is change the way it looks... on the Mac, I just left the layout the way it was, because I felt no need to change anything.)

My main problem with it was that I couldn't get any actual work done, due to circumstances... see the older posts in this switch category. Still, it's very tempting to go back, especially when I see yet another good review.

Then again, I also have an SGI to play with, which is arguably much cooler than a Mac. emoticon:wink2

Posted by Hans Nowak on 2004-01-10 18:31:29   {link} (see old comments)
Categories: switch

--
Generated by Firedrop2.