Eamonn O'Brien-Strain

LinkedIn

Sure you can program in Scala just like you would in Java and get all the advantages of the cleaner syntax. But if you really want to explore the power of Scala you should try some functional programming.

One way to tell if you are programming in a largely functional manner is if you prefer val declarations to var declarations and if you prefer immutable to mutable classes.

To implement matrices, let's leverage the immutable lists generated by Scala's default List(...) call.

Arbitrarily choosing a row-major representation, we will represent a row of a matrix as as a list of doubles. For convenience let's create a type alias for that:

type Row = List[Double]

A matrix can then be a list of rows:

type Matrix = List[Row]

One fundamental operation we will be doing is a dot product. Let's implement this in map-reduce style:

def dotProd(v1:Row,v2:Row) =
  v1.zip( v2 ).map{ t:(Double,Double) => t._1 * t._2 }.reduceLeft(_ + _)

The zip method combines together two parallel lists of numbers into a single list of pairs of numbers. The map method multiplies the elements of each of these pairs together. The reduceLeft method sums the numbers of the list to create a single number.

OK, now let's see how we can create some of the standard matrix functions.

First here is how we can transpose a matrix:

def transpose(m:Matrix):Matrix =
  if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

Notice this is a recursive function. It uses the construct _firstRow_ :: _remainderOfRows_ to form the list of rows that is the output matrix. It calculates the first row of the output matrix by using map to get the first element of each row of the input matrix. It gets the remainder of the rows by recursively getting the transpose of the matrix formed by the tail of each input row (i.e. every element except the first one).

How about matrix multiplication? That turns out to be pretty straightforward using standard Scala “for comprehensions”:

def mXm( m1:Matrix, m2:Matrix ) =
  for( m1row <- m1 ) yield
    for( m2col <- transpose(m2) ) yield
  dotProd( m1row, m2col )

Here we directly implement the matrix multiplication formula, iterating through the rows of the first matrix and the columns of the second matrix, and calculating the dot-product of each. Note that to iterate over the columns of a matrix we actually iterate over the rows of the transpose of the matrix.

However it would be nice to be able to use standard mathematical operators like A*B and AT when coding with matrices. Well, we can using the power of Scala's operator identifiers, infix syntax, and implicit conversion:

case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

}

implicit def pimp(m:Matrix)  = new RichMatrix(m)

The user of this library need never explicitly instantiate any RichMatrix objects — they are automatically created from List[Double[Double]] object whenever the T or * method is called on it.

This allows you to do things like:

        val M = List(
          List( 1.0, 2.0, 3.0 ),
          List( 4.0, 5.0, 6.0 )
        )
        val MT = List(
          List( 1.0, 4.0 ),
          List( 2.0, 5.0 ),
          List( 3.0, 6.0 )
        )

        M.T  must_==  MT

        val A = List(List( 2.0, 0.0 ),
    		 List( 3.0,-1.0 ),
    		 List( 0.0, 1.0 ),
    		 List( 1.0, 1.0 ))
        val B = List(List( 1.0,  0.0, 2.0 ),
    		 List( 4.0, -1.0, 0.0 ))
        val C = List(List(  2.0,  0.0, 4.0 ),
    		 List( -1.0,  1.0, 6.0 ),
    		 List(  4.0, -1.0, 0.0 ),
    		 List(  5.0, -1.0, 2.0 ))
        A * B  must_==  C

While we are at it we might as well add a few more convenience methods to the RichMatrix:

    case class RichMatrix(m:Matrix){

      ...

      def apply(i:Int,j:Int) = m(i)(j)

      def rowCount = m.length
      def colCount = m.head.length

      def toStr = "\n"+m.map{
        _.map{"\t" + _}.reduceLeft(_ + _)+"\n"
      }.reduceLeft(_ + _)

    }

The apply method is a special method invoked when the parenthesis operator is applied to an object. It allows you to, for example, do c(1,3) to get the number on the second row, fourth column of the matrix. Note that this method should not be used in performance-sensitive inner loops because it is not efficient. A matrix uses linked-lists as storage so the element access is O(N) not O(1) as would be the case if the matrix used arrays.

The rowCount and colCount methods are I hope obvious.

The toStr returns a string representation of the matrix in a nice tabular format that is much easier to than the default toString method if List[List[Double]], Note how this is done with two nested map/reduce pairs.

Now, creating a matrix using the List( List(...), List(...), ... ) syntax is fine for small matrices, but what if we want to generate large matrices? One way to do this is:

    object Matrix{
      def apply( rowCount:Int, colCount:Int )( f:(Int,Int) => Double ) = (
          for(i <- 1 to rowCount) yield
    	( for( j <- 1 to colCount) yield f(i,j) ).toList
        ).toList
    }

This allows you do do things like:

        // 100x200 matrix containing random elements
        val A =  Matrix(100,200) { (i:Int,j:Int) =>
          random
        }

        // 5x5 identity matrix
        val I = Matrix(5,5) { (i:Int,j:Int) =>
          if(i==j) 1.0 else 0.0
        }

Note that everything above is pure-functional: all the objects are immutable and each function is implemented as a single expression.

That's it for now. There is obviously a lot more we would have to add to make this a useful, production-quality library,

(If you want to try this yourself, you can download the complete source code and the BDD-style regression test that demonstrates its use.)


layout: post title: “How you might create a Scala matrix library in a functional programming style” date: 2010-01-10 category: Programming


Sure you can program in Scala just like you would in Java and get all the advantages of the cleaner syntax. But if you really want to explore the power of Scala you should try some functional programming.

One way to tell if you are programming in a largely functional manner is if you prefer val declarations to var declarations and if you prefer immutable to mutable classes.

To implement matrices, let's leverage the immutable lists generated by Scala's default List(...) call.

Arbitrarily choosing a row-major representation, we will represent a row of a matrix as as a list of doubles. For convenience let's create a type alias for that:

type Row = List[Double]

A matrix can then be a list of rows:

type Matrix = List[Row]

One fundamental operation we will be doing is a dot product. Let's implement this in map-reduce style:

def dotProd(v1:Row,v2:Row) = 
v1.zip( v2 ).
map{ t:(Double,Double) => t._1 * t._2 }.
reduceLeft(_ + _)

The zip method combines together two parallel lists of numbers into a single list of pairs of numbers. The map method multiplies the elements of each of these pairs together. The reduceLeft method sums the numbers of the list to create a single number.

OK, now let's see how we can create some of the standard matrix functions.

First here is how we can transpose a matrix:

def transpose(m:Matrix):Matrix =
if(m.head.isEmpty) Nil
else m.map(_.head) :: transpose(m.map(_.tail))

Notice this is a recursive function. It uses the construct firstRow :: remainderOfRows to form the list of rows that is the output matrix. It calculates the first row of the output matrix by using map to get the first element of each row of the input matrix. It gets the remainder of the rows by recursively getting the transpose of the matrix formed by the tail of each input row (i.e. every element except the first one).

How about matrix multiplication? That turns out to be pretty straightforward using standard Scala “for comprehensions”:

 def mXm( m1:Matrix, m2:Matrix ) =
 for( m1row <- m1 ) yield
 for( m2col <- transpose(m2) ) yield
 dotProd( m1row, m2col )

Here we directly implement the matrix multiplication formula, iterating through the rows of the first matrix and the columns of the second matrix, and calculating the dot-product of each. Note that to iterate over the columns of a matrix we actually iterate over the rows of the transpose of the matrix.

However it would be nice to be able to use standard mathematical operators like A*B and AT when coding with matrices. Well, we can using the power of Scala's operator identifiers, infix syntax, and implicit conversion:

case class RichMatrix(m:Matrix){

 def T = transpose(m)

 def *(that:RichMatrix) = mXm( this.m, that.m )

}

 implicit def pimp(m:Matrix) = new RichMatrix(m)

The user of this library need never explicitly instantiate any RichMatrix objects — they are automatically created from List[Double[Double]] object whenever the T or * method is called on it. This allows you to do things like:

val M = List(
 List( 1.0, 2.0, 3.0 ),
 List( 4.0, 5.0, 6.0 )
)
val MT = List(
 List( 1.0, 4.0 ),
 List( 2.0, 5.0 ),
 List( 3.0, 6.0 )
)

M.T must_== MT

val A = List(List( 2.0, 0.0 ),
 List( 3.0,-1.0 ),
 List( 0.0, 1.0 ),
 List( 1.0, 1.0 ))
val B = List(List( 1.0, 0.0, 2.0 ),
 List( 4.0, -1.0, 0.0 ))
 val C = List(List( 2.0, 0.0, 4.0 ),
 List( -1.0, 1.0, 6.0 ),
 List( 4.0, -1.0, 0.0 ),
 List( 5.0, -1.0, 2.0 ))

A * B must_== C

While we are at it we might as well add a few more convenience methods to the RichMatrix:

case class RichMatrix(m:Matrix){

 ...

 def apply(i:Int,j:Int) = m(i)(j)

 def rowCount = m.length
 def colCount = m.head.length

 def toStr = "\n"+m.map{
 _.map{"\t" + _}.reduceLeft(_ + _)+"\n"
 }.reduceLeft(_ + _)

}

The apply method is a special method invoked when the parenthesis operator is applied to an object. It allows you to, for example, do c(1,3) to get the number on the second row, fourth column of the matrix. Note that this method should not be used in performance-sensitive inner loops because it is not efficient. A matrix uses linked-lists as storage so the element access is O(N) not O(1) as would be the case if the matrix used arrays.

The rowCount and colCount methods are I hope obvious.

The toStr returns a string representation of the matrix in a nice tabular format that is much easier to than the default toString method if List[List[Double]], Note how this is done with two nested map/reduce pairs.

Now, creating a matrix using the List( List(...), List(...), ... ) syntax is fine for small matrices, but what if we want to generate large matrices? One way to do this is:

object Matrix{
 def apply(
  rowCount:Int, colCount:Int
 )(
  f:(Int,Int) => Double
 ) = 
 (
  for(i <- 1 to rowCount) yield
  (for(j <- 1 to colCount) yield f(i,j)).toList
 ).toList
}

This allows you do do things like:

 // 100x200 matrix containing random elements
 val A = Matrix(100,200) { (i:Int,j:Int) =>
 random
 }
 // 5x5 identity matrix
 val I = Matrix(5,5) { (i:Int,j:Int) =>
 if(i==j) 1.0 else 0.0
 }

Note that everything above is pure-functional: all the objects are immutable and each function is implemented as a single expression.

That's it for now. There is obviously a lot more we would have to add to make this a useful, production-quality library,

(If you want to try this yourself, you can download the complete source code and the BDD-style regression test that demonstrates its use.)

[Originally published on my old blog on 10 Jan 2010.]


date: '2010-01-07 16:46:31' layout: post slug: scala-tip-making-it-easier-to-add-attributes-to-an-xml-element status: publish title: 'Scala tip: Making it easier to add attributes to an XML element' wordpress_id: '609' categories: Programming


In most respects Scala makes it very easy to handle XML, but there are a few things that are hard to do. One is changing the value of an existing attribute on an element, or adding a new attribute to an element.

The simplest way I found to add new attributes c="CCC" d="DDD" is to do:

val modified = elem % new UnprefixedAttribute(“c”,“CCC”,Null) % new UnprefixedAttribute(“d”,“DDD”,Null)

This is a bit verbose. What if instead you could do

val modified = elem % Map( “c”–>“CCC”, “d”–>“DDD” )

Well you can, if you add the following implicit somewhere in scope:

implicit def pimp(elem:Elem) = new { def %(attrs:Map[String,String]) = { val seq = for( (n,v) <– attrs ) yield new UnprefixedAttribute(n,v,Null) (elem /: seq) ( _ % _ ) } }

This uses the library pimping pattern discussed elsewhere to effectively add a new version of the % operator to Elem that takes a Map of attributes.

The new % operator uses a for-yield construct to convert the attrs Map into a sequence of UnprefixedAttribute objects. It then uses the /: fold operator to repeatedly apply the built-in % operator, reducing down to an element with all the attributes added.


date: '2009-12-21 13:14:23' layout: post slug: scala-class-an-online-resource-to-make-it-easier-to-learn-the-next-big-language status: publish ref: https://web.archive.org/web/20150303015136/http://www.scalaclass.com/ title: Scala Class, an online resource to make it easier to learn the Next Big Language wordpress_id: '595' categories: Programming


I believe that Scala is poised to take off as the successor to Java as the main programming language for programming on the Java virtual machine. However, I have found the online resources for learning the language to be a bit weaker than for some other programming languages, so I set up scalaclass.com where I gather together material to get you started and support your continued development in this interesting new language. The site is still in embryonic form, but I welcome your initial comments.


date: '2009-12-19 16:53:35' layout: post slug: an-idiom-for-cleaner-pimping-of-libraries-in-scala status: publish title: An idiom for cleaner pimping of libraries in Scala wordpress_id: '592' categories: Programming


In dynamic languages like JavaScript and Ruby you can modify existing classes, including system classes, with extra methods. This can be a very handy, if dangerous, technique.

Scala, being a static language does not allow this same technique. But it does allow the use of implicit functions to get the same effect. For example the standard idiom to add sine and cosine methods to the Double class is

class PimpedDouble(x:Double){ def sin = Math.sin(x) def cos = Math.cos(x) } implicit def pimpDouble(x:Double) = new PimpedDouble(x)

This has the effect of adding sin and cos methods to Double, though what is actually happening is that Double values are automatically converted to PimpedDouble values when doing so would correctly compile.

This is very clever and very handy, but the idiom is a little clumsy, compared to most of Scala's elegant features. It is annoying to have to invent two names PimpedDouble and pimpDouble that are never referred to anywhere else in the code.

Can we do better? Yes we can. We can make the extra class be an anonymous class, which leaves only one arbitrary unreferenced name and also reduces the size of the code.

implicit def pimpDouble(x:Double) = new { def sin = Math.sin(x) def cos = Math.cos(x) }

That seems a lot nicer to me.

Using either of the above techniques you can now do things like

val x = 0.5 cos val y = 0.5 sin

which is taking the cosine and sine of the Double value 0.5

(Thanks to Daniel whose stackoverflow posting first brought this idiom to my attention.)


date: '2009-12-14 16:07:18' layout: post slug: sproutcore-a-rails-like-approach-to-creating-the-client-side-web-programming status: publish ref: http://www.sproutcore.com/ title: Sproutcore, a Rails-like approach to client-side web programming wordpress_id: '545' categories: Programming


A different approach to creating rich JavaScript/AJAX web apps. The programming and development methodology is basically the same as for Ruby on Rails, though it is all client-side and can work with any Server backend. (tags: programming web2.0 library design ruby javascript code web ajax css)


date: '2009-08-17 16:45:43' layout: post slug: how-a-scala-script-can-specify-what-jars-should-be-added-to-its-classpath status: publish title: How a Scala script can specify what JARs should be added to its CLASSPATH wordpress_id: '425' categories: Programming


The reason the Scala programming language has such a name is that it is meant to be scalable, i.e. good for both small scripts and large software systems. I am already convinced that Scala is as good, if not better than Java for the large-scale development, but what about the small scale?

Well it turns out that on Linux if you chmod +x a scala script you can make it executable with a bit of shebang magic as shown by this complete, runnable script:

#!/bin/sh exec scala $0 $@ !# println(“Hello World”!“)

(You do have to make sure that “scala” is in your executable path.)

But what if you are using a scala script to control an existing Scala or Java system? It would be nice to express the CLASSPATH requirements in the script itself rather than depending on the calling environment to be configured correctly. Well, I came up with this convenient idiom to collect all the JAR files in a lib directory and add them to the CLASSPATH:

#!/bin/sh L=dirname $0/../lib cp=echo $L/*.jar|sed 's/ /:/g' exec scala -classpath $cp $0 $@ !# import com.my.special.World val world = new World world.hello

This assumes that all the required JAR files are in directory ../lib relative to the script file.

I have the misfortune of being both very interested in languages and very bad at learning them.

In preparation for trips to various countries, I have attempted to learn many, but have seldom got beyond politeness and survival basics like “please”, “thank you”, “hello”, “I would like that”, and “two beers please”. Such rudimentary smatterings were useful in traveling around those countries and possibly showed some respect to the locals, even if they were insufficient for carrying on a proper conversation.

Now I am preparing for my first trip to China and so attempting to learn at least a few words of Chinese because of all the countries I have been, China is probably the place where knowledge of the local language will be most useful. Unfortunately, Chinese is also the language that I am finding most difficult to learn, even at a rudimentary level.

Of course Chinese is not inherently more difficult than English. According to linguists, all widely spoken languages are equally complicated. However, that complexity can manifest itself differently in different languages. European languages have all kinds of ways in which the spelling and sound of words change according to their use in sentences. For example German has so much information encoded in word endings that you can switch around the order of words in sentences without effecting the meaning much. Chinese words however generally always sound the same no matter what their context or what their role in a sentence, but the exact sequence that the words appear in the sentence determines their role.

English is somewhere between Chinese and German in that both word ordering and word modifications encode role information. English has a fixed basic pattern of subject-verb-object for declarative sentences but has some flexibility in placement of some words such as adverbs, which in contrast have a fixed position in Chinese sentences. English verbs do change their endings depending on tense and person (“I walk”, “he walks”, “he walked”) and its nouns and adjectives change endings when used in plural or possessive contexts (“dog, dogs, dog’s”). However, it is missing many of the other word ending complexities of gender and case that appear in many other European languages.

It was a welcome relief in looking at Chinese to discover that I only have to learn one form of every word. For someone who has previously tackled the grammar of European languages, it almost seems like Chinese has no grammar. For example, all the forms of the verb “to be” such as “am” “is”, “are” are all translated by the single word 是. However, as you can see from this example there are some particular challenges for an English speaker. The first and most obvious one is that written Chinese does not use a phonetic alphabet. It turns out that this word 是 in the Mandarin dialect has a sound something like “shi!” said with a falling tone.

And that tone is important, which raises the second challenge for English speakers. In European languages, we use tone to indicate that a sentence is a question (rising tone) or an exclamation (falling tone). In Chinese, these tones are part of the meaning of each individual word itself. So for example if I say the same sound “shi?” but with a rising tone then it means “ten” and has a different character 十.

You might wonder why the Chinese do not just switch to a phonetic alphabet. Well, there is one such phonetic alphabet used in mainland China called pinyin in which 是 is rendered as shì and 十 as shí (note the different tone marks on the vowel). However this brings up a third challenge of Chinese, which is that, even considering the variations due to tones, there actually is quite a limited range of sound combination that are allowed in the language. This means that many words that sound the same, even with the same tone, have different meanings. For example, an online dictionary shows 112 meanings for falling-tone shì – each of these different meanings having a different character. Of course, just as in English when you have homophones like this you can usually figure out the meaning by context. However because there are so many more homophones in Chinese a lot more information is lost when transcribing into phonetic pinyin, possibly rendering some texts unclear and ambiguous, especially those written in a formal terse style. This is probably why pinyin has not replaced Chinese characters but plays a minor role as a teaching aid and as a way to express Chinese words in foreign languages.

Of course, spoken Chinese has all the ambiguities of pinyin because of these homophones. However, in practice, people add extra words when they speak to remove the ambiguities – for example using a combination of two different words for the same concept. In theory, this more verbose speaking style could be used in written Chinese so that it would be clear when written in phonetic pinyin, but it seems the Chinese people like the more terse conventional style of writing.

Written Chinese also has another advantage, in that all the Chinese dialects have same written form even though their spoken forms are sometimes different enough to be like different languages, and in fact non-Chinese languages like Japanese and Korean also use Chinese characters as part of their writing systems. This mutual comprehensibility in writing despite mutual incomprehensibility in speaking is only possible because of the non-phonetic nature of the writing system. It also helps bridge the gap to historical writings, where modern Chinese readers can understand texts even when the spoken language has changed a lot.

So, there are a lot of challenges in learning Chinese for an English speaker. As well as the tones, and the homophones, and the non-phonetic writing system there is an almost complete lack of cognates – the similar-sounding words that mean the same in related languages – that are such a help for English speakers learning another European language. There is also the difficulty that some of the basic consonant and vowel sounds in Chinese are different to, or sometimes have no equivalent to, the sounds in English.

I did discover one small advantage I have as someone who learned the Irish language in school when growing up in Ireland. It turns out that Chinese shares a grammatical feature with Irish in not, strictly speaking, having words for “yes” and “no”. In both Irish and Chinese when responding to a question you answer with the verb in the question or its negation, rather than with “yes” or “no”.

Well, let’s see how it goes when I visit China. Luckily, all my business colleagues there speak excellent English. But outside the office will I be able to use the few score of Chinese words I have learned to effect some basic communication? Will anyone understand my mangled pronunciation? Will I be able to understand any of the replies?

After been given advance hands-on access to Wolfram Alpha, I did some testing and my conclusions about the current state of this tool are:

  1. It would be a good educational tool, especially at the secondary/high-school level and perhaps in some areas at the college level.

  2. It is an entertaining exploration tool for those with an interest in the sciences.

  3. It is not a replacement for Google because it returns nothing useful from most typical Google queries.

  4. In areas of the sciences where it should be strong, its coverage is pretty spotty and once you get past the basics most specialized data seems to be missing.

  5. The single-box Google-style interface works only for very simple queries. Its natural language understanding quickly fails for any kind of complex query, and it also fails to recognize many queries written like mathematical formulas.

  6. It is not easy to drill down to find out more information about a topic. I was expecting that the results returned would contain links to more detailed information, but that was mostly not the case.

  7. It is also not easy to find information about related topics. The results returned y a query do not have links to allow you to explore “sideways” into related areas.

I wish Wolfram well in developing this tool into something that is truly useful, but I fear that the expectations for it are so high that when it is finally released the disappointed reaction to it could be very damaging to its reputation.

There follows more details of my explorations.

Stephen Wolfram has described Wolfram Alpha as the third big endeavor of his life, after the Mathematica symbolic computation system and the New Kind of Science book. I have been a big fan of the first two and so I was thinking that his latest work could possibly be a game-changer for the Internet.

As a computer scientist, I have had Mathematica in my tool chest for several years. Every so often, I encounter problems that require some hairy algebra that Mathematica can perform much more accurately and quickly than I could with pen and paper. Or I sometimes prototype some algorithm using Mathematica’s extensive library of mathematical operations. Or I use its graphing and visualization to get insight into my problem. Or I use its symbolic manipulation to simplify formulae that I then use in my own code.

When Wolfram published the New Kind of Science, I devoured it. I read the huge tome from cover to cover, including the extensive footnotes. He build up a persuasive argument, sparing no detail, from chaos-generating cellular automata, to general theories of computability, to hints of how the physical world might be best described as computing the laws of physics. It was an amazing intellectual achievement, though it remains to be seen if it is indeed the great breakthrough that Wolfram considers it to be.

So, along with many people, I was intrigued by the build-up to the release of Wolfram Alpha, a web application with natural language processing backed by a large corpus of “curated” data and a large grid of computers running Mathematica code. Some of the hype on the Internet, was calling this a Google-killer. I thought that it could realize the vision of the Semantic Web as championed by Tim Berners-Lee, but done in a proprietary closed way rather than as an open network of interacting semantic web services.

I was very happy then to get access to a preview version of Alpha, ten days before the general release.

The first thing I tried to test was to see was it indeed a “Google killer”. Like many people, I use Google a lot, both as part of my work and for personal use. I went back through my Google search history over the last few weeks and tried some of the queries I had made to Google. I tried searching for a particular play, “The Beauty Queen of Leenane”, but apparently the current set of Alpha data does not include plays, even ones that have been on Broadway, and I got a “Wolfram|Alpha isn't sure what to do with your input” message with which I was about to become very familiar. I tried searching for the playwright “Martin McDonagh” and got an unhelpful comparison between the surname “Martin” and the erroneously-corrected surname “Mcdonald”. A tried some more queries such as “java deprecated annotation argument” which I had used successfully on Google to figure out some detailed usage information about a highly technical aspect of programming in the Java programming language. However, Alpha was of no value. In fact, as far as I can tell it knows nothing about any programming languages, except presumably Mathematica itself.

And so I slogged on through my Google query history, but everything I tried returned nothing from Alpha. Eventually, going through weeks of Google history I found one query that it got correct: “speed of sound”. (I had been trying to estimate how far my house was from the Golden Gate Bridge fog horns, given it takes the sound 10 seconds to get here.) And, when I typed in “speed of sound * 10 seconds” I got the correct answer in both Google and Alpha.

I was disappointed that almost none of my Google queries returned anything useful. At one point last week I had been trying to find a formula to convert colours from CMYK (as used by printers) to RGB (as used by displays), and through various Google queries I discovered that this was a very complex issue because the conversion depended on printer characteristics, but I did find an approximate formula that was good enough for my purposes. None of these queries returned anything in Alpha, despite the fact that this kind of conversion would be the kind of thing it would do well.

So Wolfram Alpha is definitely not a Google killer. Its corpus of information is undoubtedly of much higher quality than the Internet information available to Google. However, despite being a lot of data, it is still a tiny fraction of the information on the Internet, so it is unlikely to have information on some random topic that you are interested in.

So, to be fair to Wolfram, I gave up on comparing to Google and instead tried creating queries based on the examples on the Wolfram web site.

And I was able to create some interesting queries. For example “volume of ocean / amazon average discharge in years” revealed to me that it would take 200,000 years to fill the ocean if started empty and was filled at the rate of water flowing from the Amazon river into the sea. However I really wanted to find the average flow of all rivers into the ocean, but I could not craft a query for that, even though I could find the information for each river individually.

Then I tried something fun (at least to me). I had heard the expression “boil the ocean” describing something so overly ambitious as to be effectively impossible. So how much energy would it require to boil the oceans, and how does that compare to say the energy output of the sun per year? I tried the query “”latent heat of vaporization of water * volume of ocean * density of water” which I hoped would give me an answer in units of energy (Joules) but it insisted on expressing the latent heat of vaporization in as the molar heat of vaporization which meant I ended up with a value in the wrong units (gram-kilojoules/mole). Finally after some playing around I got the correct result of 3.124x10^24 kJ (kilojoules) using the query “latent heat of vaporization of water * volume of ocean * density of water / molecular weight of water”. However, I could not find the power output of the Sun or even the solar flux on the earth using Wolfram Alpha – even in this very scientific area its corpus of data seemed lacking. So I cheated and using Google I was easily able to find that the power output of the Sun is about 4x10^26 Watts so I tried dividing the above query by this value, but I could not get it to work despite what kinds of parentheses I used. For example “latent heat of vaporization of water * volume of ocean * density of water / ((molecular weight of water) * (4x10^26 W))” would not parse correctly, nor would “((latent heat of vaporization of water) * (volume of ocean) * (density of water)) / ((molecular weight of water) * (4x10^26 W))”, Finally I just copied and pasted values to enter the query “3.124x10^24 kJ / 4x10^26 W” to discover that if the entire energy output of the Sun were applied to boil the Earth’s oceans ist would take 7.81 seconds to do so.

So, in its domain of strength the Alpha system can produce some useful results, but I found that it was not easy to “drill down” into the results and combine them in interesting ways without a lot of manual cut-and-paste.

Could Alpha be developed to overcome all these limitations?

Perhaps the querying interface could be improved. Maybe instead of just having a single box for typing free-form “natural language” there could be an advanced query mode that allows more complex structured queries.

Perhaps the user interface could be improved to allow more exploration from the results of a query to explore related concepts. For example from the results of my query about the Amazon there could be links to related queries for Brazil, or for other major world rivers.

Perhaps more curated data could be added to fill in the gaps and increase the depth of the knowledge base. However, this seems like a economically hopeless task given the current Wolfram model of using their experts to validate all data. Even if they increased their effort ten-fold they could still only manage to curate a small fraction of all data. They only systems that seem to work are those like Wikipedia or Google which rely on the open cooperative accumulation of large numbers of Internet users – but that does not seem to fit into the envisioned Wolfram business model.

So far, there have been two main approaches to the problem of organizing the world’s information: (1) throw machine-learning techniques at vast quantities of unstructured information, as Google does or (2) create complex networks of interrelated ontologies and apply inference techniques, as the Semantic Web community does.

As a fan of both the tool Mathematica and the book New Kind of Science, I am extremely interested in seeing how the upcoming Wolfram Alpha tool is going to approach the problem.