Prolog for Ruby (ruby-prolog) Updated, Hits v1.0.1

After a long period of inactivity I’ve updated the F/OSS ruby-prolog gem! It’s been updated for ruby 2.0.0, bundler, and minitest, and released as v1.0.1!

ruby-prolog allows you to solve complex logic problems on the fly using a dynamic, Prolog-like DSL. Basic use is encompassed by stating basic facts using your data, defining rules, and then asking questions. Why is this cool? Because ruby-prolog allows you to leave your normal object-oriented vortex on demand and step into the alternate reality of declarative languages.

With ruby-prolog:

  • There are no classes.
  • There are no functions.
  • There are no variables.
  • There are no control flow statements.

You can use all these wonder things — it’s still Ruby after all — but they’re not needed, and mainly useful for getting data and results into/out of the interpreter. Prolog still tends to be favored heavily in artificial intelligence and theorem proving applications and is still relevant to computer science curricula as well, so I hope this updated release proves useful to the Ruby community.

Check out a simple ACL enforcement example or, for the daring, the ruby-prolog solution to the Tower’s of Hanoi problem!

 

Quick FASTQ File Parsing Via Memory Mapping In C/C++

I recently had a need to speedily parse through 8GiB+ .fastq text files to calculate a simple statistic of genomic data. My initial “pfastqcount” implementation in Ruby worked fine, but with many files to process took longer than I had hoped in addition to consuming an alarming amount of CPU. I ended up reimplementing the pfastqcount command-line program in C, which takes one or more .fastq files, memory maps them, and creates the statistic. Simply dropping my algorithm down to raw C significantly sped up the process and reduced CPU usage, especially coming from an interpreted language. If any of you bioinformaticians find the need to implement a FASTQ data processing algorithm in C, I encourage you to fork the project and use it as a template. The project is Apache 2.0 licensed for your convenience and publicly available on GitHub.

3D Desktop Ruby Applications On Linux

Over the past year I’ve put out a few working demos of how to develop full 3D, OpenGL-based OSX applications using Ruby. Most of the comments I’ve received have been positive, but I think the high learning overhead has been the prime limiting factor in addoption. I also decided to focus exclusively on Mac OS X, further limiting the potential audience.

I’m pleasing to learn that Martin “monkstone” Prout has successfully run the code contained within my Starfield.app–basically a folder of code on a OS X system that looks and behaves like an .exe does Windows–on a Kubuntu Linux system. I haven’t personally tried to replicate this myself due to a lack of time, but you can read how monkstone did it on his blog.

Ruby: On The Perl Origins Of “&&” And “||” Versus “and” And “or”.

Overview

Avdi Grimm has a recent post noting the use of “and” and “or” Ruby keywords as essentially control flow operators, and hinting on their Perl origins. This instantly recalled several mental notes of old Perl programs, so I though I’d put out a few quick notes on the Perl equivalents for Ruby programmers not versed in Perl 5.

Perl Semantics

Perl actually borrows the precedence rules of “&&” and “||” from C, though I’m not entirely convinced the Perl and Ruby semantics of “and” and “or” are identical. We have to remember that Larry Wall is a linguist, and that some of Perl’s idiosyncrasies are due more to human considerations than machine. Programming Perl has several pages of great content on “and” and “or”. For example, here’s an excerpt from the circa 2000 version of Programming Perl:

But you can’t just up and replace instances of || with or. Suppose you change this:

$xyz = $x || $y || $z;

to this:

$xyz = $x or $y or $z; # WRONG

That wouldn’t do the same thing at all! The precedence of the assignment is higher than “or” but lower than ||, so it would always assign $x to $xyz, and then do the ors. To get the same effect as ||, you’d have to write:

$xyz = ($x or $y or $z);

The moral of the story is that you must still learn precedence (or use parentheses) no matter which variety of logical operator you use.

What Avdi says about precedence and control flow seems correct, though the reasons for it–in Perl at least–is to differentiate between two subtly distinct human linguistic semantics. For example, consider the following two English statements.

  1. I’m either traveling by car or just staying home.
  2. I’m either traveling by car or by train.

At first glance the semantics seem identical, but on closer inspection they are completely different. Let’s look at each.

I’m either traveling by car or just staying home.

In Perl, this is the equivalent of:

$traveling_by_car = can_use_car($me) or stay_home($me);

The semantics of or is to describe consequence (aka control flow) in a specific order. Either I’m traveling_by_car(), or else screw the whole thing and I’ll just stay_home() instead, in which case it makes little difference what the value of $traveling_by_car is. In other words, the semantics of the assignment trump that of the consequence, and should the consequence occur (which in this case probably has side effects), the assignment probably doesn’t matter. This is why Perl users often use or in the following context instead of ||:

open FOO, $file or die “a horrible death: $!”;
@lines = <FOO> or die “$file is empty?”;

I’m either traveling by car or by train.

In English, this is a misleading statement of truth for several reasons.

  1. What we mean is that one of the two options is true, but one and only one. As programmers we know this better as an xor statement–A is true if and only if B is false, and vice versa–but since there is no colloquial English equivalent of xor, we instinctively infer the meaning from the speakers misstatement.
  2. As programmers we tend to look at || as a short-circuit operator evaluated left to right. But this English statement defines no explicit evaluation order. This could have been written “I’m either traveling by train or by car” (notice “car” and “train” are reversed), but it means the same thing. In other words, we are evaluating the arguments for truth, not consequence. Thus, order should not affect truth.

Closing Thoughts

In most real-world Ruby contexts these operators will work interchangeably so long as precedence order is considered. But even so, keep in mind that mixing the two styles in different contexts is not necessarily a sign of inconsistency. Using the appropriate operator may actually be a sign of maturity: a way of communicating slightly different semantics in an otherwise logically equivalent context.

3D OSX Applications With Ruby-Processing Screencast

A two-part screencast series demonstating two different 3D ruby-processing applications. A slide presentation from 2009 created for the Phoenix Ruby Group is also attached as bonus material. Enjoy!

Part 1: Starfield

Demo of a 3D starfield simulation written in pure Ruby, running on the JRuby runtime as a nicely packaged .app program for Mac OS X. (Runs on Snow Leopard and Leopard.)

Part 2: Twiverse

3D Twitter client written in pure Ruby, running on the JRuby runtime as a nicely packaged .app program for Mac OS X. (Runs on Snow Leopard and Leopard.)

Slide Show

What If Ruby Had Final Variables Like Java Or Erlang?

ruby

After a long confusing Ruby debate today at OpenRain on the merits of functional, Erlang-esque write-once-read-many variables, I’m going to step onto the podium and just say it… Ruby should get “final” or “const” variables in a similar semantic style to Java, except at runtime. Rather than ramble on for 12 paragraphs explaining exactly how this might work, read this fictitious Ruby code snippet instead. (Optional: Also check out the chapter on “final” in Hardcore Java.)

Final variables like this are really just an inline TDD mechanism.

Allowing local stack data to be constant provides no functional enhancements to the software, but alleviates the need for certain types of tests by using the compiler and/or runtime to assert certain memory is immutable. The “friend_best” method variant in the code snippet would obviously break most existing Ruby programs, but ups the bar for defensive programming by preventing many common bugs out-of-the-box while still providing support for traditional Ruby variables. At the very least we should have something like “friend_better”. Adding this information to the parse tree will also make it easier for IDEs to provide features more easily implemented for static languages.

TDD/BDD is in–no qualms about it–but we can make our code safer, cleaner and more concise by applying some of the lessons learned by our statically-typed language cousins over the last few decades.