Scott Hanselman

Ruby as Cross Platform Monad

April 5, '06 Comments [4] Posted in PowerShell | Ruby | Watir
Sponsored By

Ted Neward and Glenn Vanderburg are having lines-of-code measuring contest between Ruby and Monad (MSH). They've taken Lee Holmes' clever Encarta Answers script and Glenn's written it in Ruby.

Ted says:

"...notice how we're making use of the vast power underneath the .NET framework to lay out a pretty straightforward use of the code, in a way that's entirely dynamic and loosely-typed, including the assumed return value from the if/else block, and so on."

Using Ted's own words against him, Glenn says:

[when considering lines of code/syntactic tokens]...Ruby is clearly the winner.
Ruby: 17 lines, 76 tokens
Monad: 37 lines, 217 tokens

Personally, I'm Switzerland in this argument. Learn them both, you'll be a better person. I know .NET better so the Monad version makes more sense to me.

One thing I would suggest that Glenn do, if he really wants to get into some fun, is take a good hard look at John Lam's RubyCLR. Sure, there've been some cursory attempts at bridging the CLR and Ruby before as well as current work to get Ruby code compiling to IL. However, for the Windows world at least, Ruby's success on our platform will be (I predict) measured by two things:

  • Watir - A Ruby Interop layer on top of IE (and now Firefox with FireWatir)
  • John's RubyCLR - I'm convinced that John is doing the whole world a service with this bridge.

RubyCLR is elegant in that it doesn't attempt something so lofty (or perhaps ultimately tilting at windmills) as compiling Ruby to IL. Instead it does what Watir did - it opens another whole world to the already great Ruby interpreter. Will there be a Ruby/Mono bridge? There should be, and then Glenn would have something to smack Ted over the head with as then the IRB (Ruby Interactive Shell) starts looking like cross-platform Monad.

Me? I don't care, I'll just run them both in a Tabbed Console like the Console Project at SF.NET.
(Note the screen shot above, it's the Console Demo 15 drop. Support this project!)

UPDATE: Lee Holmes has retorted brilliantly with a rewrite of the original get-answer script. Here's his rewrite along with the ruby version.

param([string] $question = $(throw "Please ask a question."))

[void] [Reflection.Assembly]::LoadWithPartialName("System.Web")
$webClient = new-object System.Net.WebClient

$text =  $webClient.DownloadString("http://search.msn.com/encarta/results.aspx
q=$([Web.HttpUtility]::UrlEncode($question))")

if($text -match "<div id=`"results`">(.+?)</div></div><h2>Results</h2>")
{
   $partialText = $matches[1]
   $partialText = $partialText -replace "<\s*a.*?>.+?</a>", ""
   $partialText = $partialText -replace "</(div|span)>", "`n"
   $partialText = $partialText -replace "<[^>]*>", ""
   $partialText = ($partialText -replace "`n`n","`n").TrimEnd()
   $partialText
}
else
{
  "No answer found."
}

And the Ruby version...

#!/usr/bin/env ruby

require 'open-uri'
require 'cgi'

fail "Please ask a question." unless ARGV.size > 0
question = ARGV.join(" ")
query = "
http://search.msn.com/encarta/results.aspx
?q=#{CGI::escape(question
)}"
page = URI(query).read or fail "Couldn't get response."

puts

if page =~ %r{<div id="results">(.+?)</div></div><h2>Results</h2>}
  response = $1
  response.gsub! %r{<\s*a.*?>.+?</a>}, ""  # remove links
  response.gsub! %r{</(div|span)>}, "\n"  # insert newlines
  response.gsub! %r{<.*?>}, ""  # remove tags
  puts response.squeeze("\n").rstrip  # collapse adjacent newlines and trim whitespace
else
  puts "No answer found."
end

Clearly Lines of Code is a ridiculous metric to measure just about anything, and this is more proof that both Ruby and Monad kick the llama's ass.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Thursday, April 06, 2006 1:23:29 AM UTC
This is my mission at OSCON 2006 - to recruit Mono developers to port the C++ parts of RubyCLR (< 1400 LOC) to C# + lots of nasty interop goo. That should be sufficient to get RubyCLR running on Mono since most of the hard parts of the bridge are actually written in Ruby.
Thursday, April 06, 2006 12:30:36 PM UTC
Or you could just use native OS scripting capabilities :-)

Save the following as GetAnswer.js, then from command prompt type

cscript GetAnswer.js "What is the populations of China?"

var ie = new ActiveXObject("InternetExplorer.Application");
ie.Navigate2("http://search.msn.com/encarta/results.aspx?q="+encodeURI(WScript.Arguments(0)));
while(ie.ReadyState !=4)
{
WScript.Sleep(1000);
}
if(ie.Document.getElementById("bubble_header"))
WScript.StdOut.Write(ie.Document.getElementById("bubble_header").innerText);
else
WScript.StdOut.Write("No Answer Found for: [" +WScript.Arguments(0) +"]");

ie.Quit();
Thursday, April 06, 2006 2:16:54 PM UTC
Damn you Hanselman! Yet another utility [Tabbed CMD] I must now download. :)

Thx.
Saturday, April 08, 2006 7:35:47 PM UTC
The overarching narrative is this:

The CLR exposes a vast array of functions from a wide range of sources in a way that allows ANY language to leverage. A good chuck of Microsoft's $7 billion yearly R&D spending is going into functions exposed via the CLR not to mention the huge investment made by the rest of the industry. All CLR languages are able to take advantage of this huge investment stream with little to no effort.

We believe that Monad provides a unique value proposition being a great production-quality interactive shell as well as a great scripting/programming environment. We think it is going to have lots of support and be used by lots of people. I encourage you to kick the tires and use it if it meets your needs (and complain to me if it doesn't). If you prefer to use Ruby over CLR - that is great as well - its a big tent. Ditto for any other language on the CLR Python, C#, VB, etc. If you want to invent a new language on the CLR - go for it, you'll find that with a little work on your part, your users can get access to all the CLR libraries as well.

The CLR is a rising tide that lifts all language boats.

Jeffrey P. Snover
Monad Architect
Jeffrey Snover
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.