Programming Clojure

12:37 PM EDT Sunday, June 28 2009

Programming Clojure

A few weeks ago I received my printed copy of Programming Clojure by Stuart Halloway in the mail. I had been a technical reviewer of the book so I was excited to see it finally in print. In case you haven't heard of it yet, Clojure is a programming language designed by Rich Hickey, a Lisp dialect, that runs on the Java Virtual Machine and is designed support concurrent programming.

Clojure has excellent documentation and Rich has posted several great videos of talks he has given that cover the rational for Clojure as well as an introduction into the major concepts. I highly recommend that you watch those videos if you haven't already because Rich does a great job explaining why concurrency is hard using the typical Object-Oriented model that we program in today and how the features of Clojure support a better model for concurrency. Whether you are programming in Java, C#, Erlang, Haskell, Python, Ruby, etc., you will probably be able to learn something from these talks, and plus Rich is just an interesting guy to listen to.

So after all that, you might be saying why do we need a book about Clojure? The answer is that although the documentation is good, it can be a little intimidating when first learning Clojure. For programmers with little or no Lisp or functional programming experience, figuring out how to do basic things the idiomatic way in Clojure can be a daunting task. Stuart's book does an excellent job filling this gap.

The book covers all the major feature of Clojure and is very up-to-date. As a reviewer I got to see the evolution of this book from revision to revision and it was amazing to me to see how much work Stuart put in. Chapters were often completely re-written to keep up with changes in the language that occurred before it stabilized in a 1.0 release. I think the final product greatly benefited from that work and is an excellent resource for learning Clojure. I encourage you to pick up a copy today.

Posted in  | Tags Clojure | 1 Comments

Zip Code Proximity Search with Rails

2:17 AM EDT Saturday, June 27 2009

So you're building the next big social networking website using Rails and like all the other hip kids you are going to need to allow your users to search for other users near them. The fancy term for this is "Proximity Search". For our search, we just want be able to find other people that are generally within some radius, like 5, 10 or 25 miles. For this, there is no need to geocode the address for each user in our database, we'll just use their zip code. So effectively, in our system, every user's location is just the center point of their zip code.

For starters we want to create a zip code model:

script/generate model zip code:string city:string state:string lat:decimal lon:decimal

That will create a model and a migration. You need to alter the migration to specify the precision and scale for the lat and the lon.

t.decimal :lat, :precision => 15, :scale => 10
t.decimal :lon, :precision => 15, :scale => 10

So to populate this database, luckily the good people over at the US Census Bureau have the data readily available for us. I've created a rake task to download and load that data into your zips table. Simply put the load.rake file from this gist into the lib/tasks directory of your Rails app.

So now when you run rake load:zip_codes you should see something like:

== Loaded 29470 zip codes in ( 1m 40s) ========================================

Next we need a table for our users. So let's generate a model and a migration:

script/generate model user

I'll save you the hassle of typing out all the fields at the command-line and just give them to you here. Paste this into the create_users migration that was generated:

t.string   :username
t.string   :email
t.string   :password
t.string   :password_confirmation
t.string   :first_name
t.string   :last_name
t.string   :address
t.string   :city
t.string   :state
t.integer  :zip_id

Next you need to hook up the relationship between the zip and the user. This is basic stuff, the zip has many users and the user belongs to a zip.

Now we need some users to play with. A great tool for this is Mike Subelsky's Random Data gem. I've already created a rake task that uses this gem to create some test user accounts. You call it like this:

rake load:random_users[10000]

The 10000 is the number of users we want the rake task to generate for us. Did you know you can pass command-line arguments to a rake task like that? Pretty spiffy. 10000 is a pretty good number because it gives us a fairly large dataset to work with and is still able to load in a reasonable amount of time. 10000 users finished in about 6 minutes and 30 seconds for me.

Next we need to setup our methods to do the querying. For this I basically used Josh Huckabee's Simple Zip Code Perimeter Search method, but re-worked it a little so we can use named scope with it. You can grab the code for both zip.rb and user.rb from the gist.

There are a couple of things we get here. First is a named scope to easily find zip codes. Looking at the output of the loading of the random users, the last one for me was Mr. Steven Moore of Koloa, HI, 96756. So let's see how many other people are in that zip code. Start up script/console and run this:

>> Zip.code(96756).users.count
=> 1

Hmm...I guess it's lonely in Hawaii. Let's find the zip code that randomly ended up with the most inhabitants:

>> Zip.count_by_sql "select zip_id, count(*) as count 
from users group by zip_id order by count desc limit 1"
=> 18177

Ok, so that's the id of the zip record, not to be confused with the actual zip code. So let's find the first person in this zip code:

>> user = Zip.find(18177).users.first
=> #<User id: 1267, username: "cabel1266", ...>

I got Ms. Cheryl Abel of Bloomville, NY. So now for the big moment. What we really want to do is find everyone within 25 miles of Cheryl.

>> user.within_miles(25).count(:all)
49

Looks like Cheryl has 49 people nearby. Let's see who they are:

>> user.within_miles(25).all.each{|u|
?> puts "%.2f %20s, %2s, %5s" %
?> [u.distance, u.city, u.state, u.zip.code]}
0.00           Bloomville, NY, 13739
0.00           Bloomville, NY, 13739
0.00           Bloomville, NY, 13739
0.00           Bloomville, NY, 13739
0.00           Bloomville, NY, 13739
7.04            Worcester, NY, 12197
7.04            Worcester, NY, 12197
7.43             Maryland, NY, 12116
8.09             Meredith, NY, 13753
8.54            De Lancey, NY, 13752
8.71     Livingston Manor, NY, 12758
9.11             Roseboom, NY, 13450
9.88          Jordanville, NY, 13361
...

So there you have it! I'm still trying to work out some kinks with this and get it to work with count and will paginate, so if you have any suggestions, fork the gist, hack away and leave a comment. I'll update this post when I get count and pagination working.

Posted in  | Tags Rails, Ruby | 0 Comments

Ruby Nation

10:43 AM EDT Saturday, June 13 2009

Thanks to everyone who attended my talk yesterday at Ruby Nation about BrowserCMS. I've posted my slides online here. Unfortunately the demo part of the talk wasn't record, so I'll try to record a screencast of the demo. Look for that in the next few days.

If you did attend my talk, I would appreciate it if you take a minute to rate it.

Posted in  | Tags Ruby | 0 Comments

This Just In: JavaScript is a Real Language

2:15 PM EDT Monday, May 11 2009

Some people think of JavaScript as that crappy language that runs inside of browsers. The truth is that the languages is not that bad, aside from a few warts (void/explicit return, global by default I'm looking at you), it's pretty nice. I think it's gotten a bad wrap for a few reasons.

First of all, the DOM. Before modern JavaScript libraries like jQuery and Prototype came along, developers were constantly pulling their hair out dealing with incompatibilities across different browser implementations of the DOM. Modern libraries have done a lot to normalize behavior across browsers and browser implementations have gotten better, but many developers still have bad memories of dealing with "JavaScript" back in the day. The truth was this wasn't really a problem in JavaScript the language, more so the DOM and browser implementations. If the language that Netscape put into the browser originally was Ruby, we would blame Ruby for all of these problems too.

Next, I think there was a whole class of Java developers upset that OO didn't work in JavaScript the way it did in Java. JavaScript wasn't considered a "real" OO language and was therefore inferior to Java. JavaScript has it's own way of dealing with OO and the sooner you understand how that works, the more comfortable you will be with JavaScript.

In the opposite way that many Java developers despised JavaScript, many Ruby developers, including Java developers converted to Ruby developers, started to appreciate JavaScript. JavaScript has anonymous functions just like Ruby has anonymous functions. Ruby makes ubiquitous use of anonymous functions through blocks. I think for many developers, Ruby was the first language they used that showed how useful anonymous functions can be. I think this is also the reason that you see some many Ruby developers interested other functional languages like Erlang, Haskell and Lisp.

Lastly, I think many developers don't see JavaScript as a general purpose language simply because it's trapped inside the browser. You can't run a JavaScript script from the command line just like you can run a Ruby, Python or Perl script.

Well, it turns out that last one isn't true and I want to show you how to get started writing some JavaScript as a "real" language, and specifically, a functional language.

The first thing you'll need is a JavaScript interpreter. There are two that I'm aware of, SpiderMonkey, the C-based JavaScript interpreter, and Rhino, the Java-based JavaScript interpreter. Let's go with SpiderMonkey.

First, download the tarball and untar it somewhere on your machine. I did that in the src directory in my home directory. Then you go into the js/src directory and run the make command. Here's what that looks like:

cd ~/src
wget http://ftp.mozilla.org/pub/mozilla.org/js/js-1.8.0-rc1.tar.gz
tar xvzf js-1.8.0-rc1.tar.gz
cd js/src
make -f Makefile.ref

Now you should have a directory like Darwin_DBG.OBJ, it will be named differently if you aren't on a Mac. Inside that directory there is a js program you can run. To make life easier, add src/js/src/Darwin_DBG.OBJ to your path. Now you should be able to just type js and be at an interactive JavaScript interpreter, with js> as the prompt:

$ js
js> print("Hello, World")
Hello, World

You can also run js -f my_awesome_script.js to run a script saved into a file. I have created a quick hack of a textmate command to be able to a JavaScript file. Click on the image below to see:

Run JavaScript File Textmate Command

So now let's write a little JavaScript. First things first, open a file called hello.js in Textmate and put this into it:

print("Hello, World!")

If you've created the command properly, you should see Hello, World! printed out. If you aren't using Textmate, then you will have to figure out how to get your editor to run the file. Even if you can't do that, it's as simple as running js -f hello.js from the command line.

Now we can write some real code. What we want to focus on doing is functional programming. Most of the basic functions for functional programming aren't defined in JavaScript by default, but it's easy enough to write our own that handle the basic things. Note that this kind of functional programming is going to be functional in that we are going to pass functions to and return functions from functions, a.k.a higher-order functions, but we aren't going to focus on another popular aspect of functional programming, which is immutable data. Baby steps. :)

So the first thing we need is some kind of implementation of an iterator function, because we're not writing for loops. Let's do something like Ruby's each:

function each(f, arr) {
  for(var i in arr) {
    f.apply(null, [arr[i]])
  }
}

What this does is take a Function and an Array and applies the Function to each element of the Array. To test this out, let's also add this line of code to test it:

each(print, [1,2,3,4,5])

You can see that we can pass the print function to each and have it print the numbers from 1 to 5. Ok, next up is map, which takes a Function and an Array and returns a new Array which contains the result of applying the Function to each element of the Array.

function map(f, arr) {
  var result = []
  each(function(e) {
    result.push(f.apply(null, [e]))
  }, arr)
  return result
}

We can test that out with:

print(map(function(e){
  return e * e
}, [1,2,3,4,5]))

This time, we are passing an anonymous Function as the first argument to the map Function. This Function takes one value and multiplies it by itself, better know as square. Now for our last trick, we will do the functional programming equivalent of hello world, fibonacci:

function fib(n) {
  if(n <= 1) {
    return n
  } else {
    return fib(n-1) + fib(n-2)
  }
}

We can test this with:

each(print, map(fib, [1,2,3,4,5,6,7,8,9,10]))

Here's the entire code in one gist.

Now that JavaScript is being viewed as a "real" language, it's even got it's on conference! There's also some IRC channels devoted to JavaScript as well and of course, Stack Overflow. Happy JavaScripting!

Posted in  | Tags Javascript | 3 Comments

The Busy Rails Developer's Intro To Rake

10:02 PM EDT Monday, April 20 2009

This is just a quick 60 second intro to Rake. If you are doing development with Ruby on Rails, you undoubtedly use Rake on a daily basis. For example, you use rake db:migrate to run your migrations or rake test:units to run your unit tests. But do you know how to write your own Rake tasks? If you never have done that, you might hesitate to write a rake task instead thinking you ran just write a quick ruby script rather than take the time to figure out how to write a Rake task.

So to create a rake task, in an existing Rails app, create a file called lib/tasks/app.rake. You can name it whatever you want as long as it ends in .rake. I'm choosing to use app because we are going to write some app-specific tasks. In the file, put this:

task :hello_world

Now from the command line you can run your task with rake hello_world. Nothing happens, but it runs. Now let's have it print hello world:

task :hello_world do
  puts "Hello, World!"
end

Now when you run your task, it prints "Hello, World!". Let's add a description to our task to let people know what it does:

desc "Prints 'Hello, World!'"
task :hello_world do
  puts "Hello, World!"
end

Now if you run rake -T, you will see your hello_world task in the list of tasks. rake -T only shows tasks that have a description. You can also run rake -D hello_world to see the full description of the task. You should give all of your tasks that you expect users to run from the command-line a description.

Now a problem with our task is what happens if someone else wants to write a task named hello_world? Well, we would have a namespace problem. So what we want to do is put all of our tasks into the app namespace:

namespace :app do
  desc "Prints 'Hello, World!'"
  task :hello_world do
    puts "Hello, World!"
  end
end

So now we can run our task as rake app:hello_world.

So this is obviously not a real task. Let's say we want to know what the load path of our app looks like. Easy, we'll just do this:

namespace :app do
  desc "Prints load path of this app"
  task :load_paths do
    Rails.configuration.load_paths.each do |p|
      puts p
    end
  end
end

When you try to run this rake tast, you will get this error:

rake aborted!
uninitialized class variable @@configuration in Rails

The problem is that by default, a rake task doesn't load the Rails environment. It's easy to tell it to do that with this:

namespace :app do
  desc "Prints load path of this app"
  task :load_paths => :environment do
    Rails.configuration.load_paths.each do |p|
      puts p
    end
  end
end

By saying :load_path => :environment, you are saying that the load_path task depends on the environment being loaded. Or more specifically, you are saying "run the environment task before running this task". There is a task called "environment", and it loads the Rails environment. You won't see it under rake -T, because it has no description because it is not a task you should run directly, only as a dependency of other tasks.

Now that we have the Rails environment loading, when you run the rake task, you will get the output you expect. If you make your task depend on environment, you will also be able to access your models from within your task. Now that you know the basics of Rake, you can easily get going making Rake tasks for your Rails app.

Posted in  | Tags Rails, Rake, Ruby | 1 Comments

   Next Page >>