Saturday, January 19, 2008

Fox/FXRuby/Leopard, Part the Second

As a follow-on to my previous post, I discovered that there's a little more work to be done to actually be able to use my freshly installed FXRuby. I tried using the listexample.rb program from the aforementioned Pragmatic Programmers book, and promptly found that the 'fox16' library couldn't be required. Grumble.

Fortunately, this post on the fxruby-users mailing list (again, courtesy of Lyle Johnson, lead programmer of FXRuby and author of the PragBook) was able to get me going:
a workaround is to use the "gem env" command to identify your Gems installation directory (usually something like /usr/local/lib/ruby/gems/1.8) and switch to the "gems/fxruby-[version]/ext/fox16" directory underneath that:
cd /usr/local/lib/ruby/gems/1.8/gems/fxruby-1.6.0/ext/fox16
and then type:
make
Note: Since RubyGems comes installed with Leopard, your gem installation directory is more likely to be something like "/Library/Ruby/Gems/1.8", at least if you did a fresh install as I did. YMMV.

But here I encountered the same architecture problem I referenced in my previous post. This time I ended up editing the Makefile and deleting all references to "-arch ppc"; setting the ARCHFLAGS environment variable before running make didn't cut it for me.

Once you've re-made the gem, you should be able to verify your installation in irb:
>> require 'fox16'
=> true
Two final caveats:
  • I had to modify the PragExample with the line "require 'rubygems'" at the top of the file, right before the "require 'fox16'" line. This was because I haven't yet set my RUBYOPT environment variable in Leopard to require rubygems automatically for me.
  • The example program worked fine for me after all this (try holding the shift button to do multiple selections), until I quit, at which point I got:
    X Fatal Error.
    Abort trap
So this FXRuby thing is not an exact science yet. Sigh.

Installing Fox and FXRuby on Mac OS X Leopard (Intel)

I'm planning to start playing with some of the GUI toolkits available for Ruby, and I know there's a Pragmatic Programmers book (currently in beta) for FXRuby, so I thought I'd get the fixin's in place to be able to play with it. Unfortunately, the standard sudo gem install fxruby alone didn't get the job done for me. Even using MacPorts to install Fox first (sudo port install fox) let me down. Here's what (eventually) did work:

  • Download and Install Fox:

    • Download the source. I picked the current stable version from the "Downloads" section, "Linux/Unix" subsection.

    • Set the LDFLAGS environment variable as described in Lyle Johnson's (author of FXRuby and the book) very helpful post:
      export LDFLAGS="-dylib_file \
      /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:\
      /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"
      Note: There's a typo in Lyle's instructions that will trip you up if you just cut and paste from there; there should be a space between the "-dylib_file" and the first "/System/Library/...". And, in case you're cutting and pasting from here, there should be no space between the colon and the second "/System/Library/...".

    • cd to the expanded Fox source folder.

    • ./configure, with whatever options you would normally use. I didn't specify anything in particular.

    • sudo make install, again with your typical options. The vanilla command worked for me.



  • Install the FXRuby gem:

    • sudo env ARCHFLAGS="-arch i386" gem install fxruby

    • The extra bits about the ARCHFLAGS are a workaround for a problem in ld (and/or lipo) trying to build this gem for both PPC and Intel architectures. As you might guess, this will work for you only if you're on an Intel Mac.

    • From the Credit-Where-Credit-Is-Due department: I cribbed the "env ARCHFLAGS" trick from the most excellent Hivelogic website, specifically this post.



  • Write a cool GUI! (Haven't gotten that far on this item yet...)


Oh, and I'll be looking at Shoes too. No weird Unix/Linux project dependencies for that one, thank goodness. Just a regular .dmg to download and install. Nice.

Thursday, January 17, 2008

Required Reading: The Role of the Study of Programming Languages...

Via the always excellent Patrick Logan -- Daniel Friedman: The Role of the Study of Programming Languages in the Education of a Programmer.

Some key quotes:

  • On the lack of tail call support in Java:
    Guy Steele...was promised back in 1997 that this flaw would be fixed. Here it is 2001 and there is still no resolution of this problem on the horizon.
    Emphasis mine. The more things change...

  • On Friedman's own background and educational goals:
    Later, I wanted to be able to implement a language per week.
    Followed later by:
    I want the student to be able to implement (perhaps crudely) every language that they study...
    Now that's Thinking Different.

  • Friedman quoting Jonathan Sobel, a former student who successfully used (uses?) these concepts in practice:
    Efficiency comes from elegant solutions, not optimized programs. Optimization is just a few correctness-preserving transformations away.

  • Finally, and perhaps my favorite, Patrick Logan's cogent take:
    Probably programming in C itself (or Java or Scala) is a kind of premature optimization.
WARNING: Refers to -- and poses some examples in -- the lambda calculus. Implementations in Scheme. Don't let either of those put you off, though. I don't understand every line of code (yet), but I've seen enough to be inspired to figure it out.

Challenge yourself.

Friday, January 04, 2008

Java Generics Broken? We Report, You Decide.

Since I've been taken to task in the past for my cogent observations of Java's, um, shall we say "unintuitive" behavior, particularly in the era of generics and autoboxing, I'm just going to put this one out there without making any (public (explicit)) value judgments.

So it seems that if you define a method thusly (note: requires Java 5 ("Gangly Geek") or better greater having a numerically higher version number):
public void doSomethingGenerically(Collection<Supertype>){...}
and you attempt to call it thusly:
List<SubtypeOfSupertype> bogus = new ArrayList<SubtypeOfSupertype>();
doSomethingGenerically(bogus);
you get a compiler error saying you can't call that method with those arguments.

So my question here is: why the heck not?

Inheritance 101: a List isa Collection, right? A SubtypeOfSupertype isa Supertype, right? So why am I being told that an instance of type List<SubtypeOfSupertype> isn'ta Collection<Supertype>?

Paging Dr. Liskov...