Monday, August 16, 2010

Porting ejpi: Meaningless Results

So let's see how the two versions of ejpi compare:

Qt Version
  • Feature parity with the GTK version
  • Improved pie menu performance but two pie menu display bugs
  • Simplified layout with the potential for rotation
  • 3382 LOCs
  • From June 8th to July 16th
GTK Version
  • 4473 LOCs
  • From January 30th to February 25th
LOCs are measured by "wc -l" rather than getting fancy.  I wrote both apps and they were written in a similar style with similar amounts of whitespace and documentation.

The LOC counts look nice, more drastic than my Gonvert port for what it is worth.  I had a lot more distractions going on during my port of ejpi so a comparison of implementation times between Gtk/Qt or Gonvert/ejpi is as meaningless as the title of this post suggests.

My main Qt disappointment in this port is what seems like high coupling both in Qt itself and in code written by others (the example pie menus).

Now for some of the upsides.  Though I implemented them differently, the similarity in the drawing code between Qt and Cairo helped.  Also finding out about QStandardItemModel made my life easier.

I'm split on which direction I want to go in my learning of Qt.  Originally I had planned on porting Dialcentral for gaining experience with threading.  I have too many ideas though and not enough time.  Possible directions include: porting other apps of mine, a new app using QGraphicsView, or some QtMobility contacts (and eventually calendar) plugins (though then I'd also have to learn the quirks of Qt in C++ and deploying compiled apps to Maemo).

Learning Ruby: Vampire Numbers

Instead of the traditional book group at work I'm in a group where each person chooses to learn a new language.  For me to make it feel worth while it either needs easy C bindings, existing bindings, or be used for scripting at work.  That left me with Go, Lua, Io, and Ruby.  Go was out due to error handling and generics.  I decided to stick with Ruby so it would be work practical (Python is heavily used by the company-wide build tools but my group has a lot of Perl and Ruby scripts).

Our first assignment was simple, identify vampire numbers.  They seem arbitrary and useless but oh well.

One of the first things I did was "gem install rubydoctest".  I like doctests from Python for their providing examples for the code and that they provide very low friction low coverage tests.

My work computer is sadly running Windows.  I did not have tool chains setup to install ruby-prof from source and I couldn't figure out how to install the pre-built version referenced from their site.

A quick summary of my initial thoughts
  • rubydoctest has poor error output but I love that "!!!" drops you into irb (though I didn't find out about it until I was done).
  • I was kind of surprised Ruby doesn't have a factorial function.  I'm not as surprised about a lack of a permutation function, Python's just special like that.
  • Very few examples show how to separate module logic from executable logic (Python's "if __name__ == "__main__" idiom)
  • Optional return's are ugly for most code.  The one place they work well is used inside of a block as a predicate for a function (like the comparator for sorting).
  • Optional parenthesis make it confusing what is a property or method.  Not knowing what is going on feels sloppy to me
  • I got thrown off by changing fairly standard names (exception handling, next/continue) and at first didn't think "next" existed.
  • Find it a strange concept to use next, break, retry, redo inside of blocks.  I'd be curious what the underlying principles are for how the block communicates with its caller to execute those.
  • Retry and redo seem cool though I am unsure how often I would ever use them
  • I like Python's separation of repr from str which makes debug output easy.  I was wanting to figure out what some lists I was using were doing but each element was printed on a separate line, making it take up a lot of space and making it hard to distinguish one array from another.  I didn't notice some of the pretty print functions till later and haven't had a chance to try them yet.
  • My program was slow and according to profiling most of it was in iterating.  (0...5).each was the fastest, next was 0.upto(5), and then last was doing the looping raw (I think).  All of that kind of surprised me, most especially how slow looping was in Ruby.  I was impressed the closures for blocks didn't add much overhead (or at least it isn't noticeable compared to how slow ruby is in general).
  • I kept mixing up whether I was working with an actual iterator and an Enumerable (and it took me a while to notice the difference)
  • I really miss the composable iterators of Python (enumerate plus everything in itertools)
  • Remembering  ".." vs "..." is annoying and I end up having to look it up every time (which is very bad for code readability).
  • A problem that drove me nuts for a while is "x = false or true".  The "=" has higher precedence than "or".  What I needed is "x = false || true".  A blogpost I later came across tries to frame "or" and "and" as flow control operators rather than logical operations. I think there are way too many operators.  Can you name the difference between ".."/"...", "=="/"==="/"eq?"/"equal?", etc?