Mac OS X Hack: Autoupdate your desktop background

January 16th, 2008 by comment SarahMei

My new favorite site on teh intarwebs is the Mt. St. Helens Volcano-cam. So serene! So pretty! So different from the view out my office window, which always seems to include at least one screaming firetruck, particularly during conference calls!

Ahem. Anyway, the volcano-cam picture on the main site is updated every 5 minutes (ish). I wanted it to be my desktop background and update more or less in sync with the online version.

To my surprise, I could find no way to set this up in the OS X control panels. Read the rest of this entry »

ˆ Back to top

Repeating a Try-Catch block

December 3rd, 2007 by comment Kris

Here’s a tip for beginners. You know how a try/catch block works: place some code inside a try, and if it fails, catch it with the catch block. But what do you do if you want to try an operation a set number of times, and then throw an exception if it’s still failing? There’s no such animal that is native in C#, but you can quickly implement one yourself. With a counter and a ref parameter, this can be done quite simply. This brief example will show you how.

Suppose we want to do some FooBar operation, but we know it could fail, due to some external circumstance, but we also know could work after the initial attempt or two. Let’s write the code to do 3 tries, and only then throw the error:

int MaxTries = 3;   //this is the limiter value - set this to the number of tries you want to execute
int NumTries = 0;   //this is our counter that keeps track of how many tries we've executed

//Perform the FooBar operation(we retry 3 times and if we don't succeed, the exception will be caught and handled)
while (NumTries < MaxTries)
               throw (err);

private void FooBar(int foo, int bar, ref int numTries)
        {
            try
            {
                //count the try
                numTries++;

                //set up & and perform your operation
                Foo(bar);
                Bar(foo);
                DoFinalOp();

                //if we got here, there was no error so set counter to kick us out of loop
                numTries = MaxTries;
            }
            catch (Exception err)
            {
                //only throw error if we've tried enough times
                if (numTries >= MaxTries)
                    throw (err);
            }

        }

Note that our FooBar method takes a ref parameter of numTries. When we change this value in the method, and the method returns, the counter will have been changed, for re-testing in the while loop clause.

Let’s walk through this and see how it works:

  • After setting NumTries and MaxTries (to 0 and 3), we hit the while loop. This first time, NumTries is definitely less than MaxTries, so we execute FooBar().
  • When we enter FooBar(), the first thing we do is increment tries, to count the attempt. Since this is a ref parameter, changing this local variable tries also ends up changing the global variable NumTries.
  • Then we start executing whatever we have to do in FooBar(). If an error is encountered at this point, we’ll fall to the catch block.
  • In the catch block, we test whether or not to throw an error, based on the value of tries. Since at this point, tries = 1, we don’t throw the error, FooBar() finishes executing and we return to the while loop.
  • Back in the while loop, we retest NumTries to see if it’s still less than MaxTries. Since we incremented it in the method, NumTries is now equal to 1, but this is still a true condition, so we call FooBar() again.
  • Once again inside FooBar(), we increment tries by 1 and try our operation. Suppose this time, it succeeded. In that case, we will reach the line: tries = MaxTries and then exit the method.
  • Now, back in the while loop, the test (NumTries &lt MaxTries) is false, so we don’t execute FooBar() again, and we’re done.

Voila! We’ve implemented try/catch/repeat functionality, allowing us multiple tries before throwing an error.

ˆ Back to top

Searching for Up-To-Date Help

August 5th, 2007 by comment Ana Nelson

When you are searching for help on a programming topic, frequently the answer will come in the form of a blog post. Preferably one with lots of useful feedback in the comments to help you decide if it’s good or bad advice! But, with the speed of software development these days, the answer to your configuration question or what to do if you get a particular error message might be very different today than it was 18 (or even 6) months ago.

A quick way to narrow down search results is to take advantage of the fact that many blogs will incorporate the creation date of a post in the URL, and use google’s inurl syntax in your search. For example, to search for recent posts on session storage in Ruby on Rails, try “inurl:2007 rails session storage”. This isn’t foolproof, you’ll miss out on any resources that don’t use a URL scheme like this, but it will filter out lots of articles from 2005 telling you to empty your tmp/sessions directory on a regular basis. You can even try to include a month parameter, and conveniently “inurl:2007/08″ matches both “2007-08″ and “2007/08″ style URLs.

ˆ Back to top

Twitter4R on Rails

July 26th, 2007 by comment mbbx6spp

Last night Twitter4R version 0.2.4 was released with a fix that makes using Twitter4R in Rails much easier.

So let’s quickly kick the tires to see how this all works:

  1. Install the Twitter4R v0.2.4 (or above) Ruby Gem: sudo gem install twitter4r
  2. Create a new rails application: rails twitter4rails
  3. After setting up your config/database.yml to your personal tastes and tweaking the Rails configuration settings in environment.rb, scroll to the bottom of environment.rb and add the following:

    gem(‘twitter4r’, ‘>=0.2.4′)
    require(‘twitter’) # loads core library
    require(‘twitter/console’) # loads a helper method we will use
    require(‘twitter/rails’) # added Rails extensions for Twitter4R

    module YourAppNamespace
    ENV["RAILS_ENV"] ||= “test” # assume test environment if no RAILS_ENV set.
    ClientContext = Twitter::Client.from_config(“#{RAILS_ROOT}/config/twitter.yml”, ENV["RAILS_ENV"])
    end

  4. Now in your controllers you can access YourAppNamespace::ClientContext object as you need to or any other part of the Twitter4R API.

If you still want more, feel free to check out the following links:

ˆ Back to top

will_paginate array?

July 23rd, 2007 by comment desi

Today I started putting pagination in the app that I have been working on. Based on recommendations from Obie I decided to use “will_paginate”, a rails plugin for pagination put out by the err the blog guys. It worked amazingly and the view helper was great! I really like the fact that I can apply the same look and feel to all page pagination throughout the app… well umm.. until I wanted to add pagination to a collection not generated from a finder or association. Since I really wanted everything to look the same and behave the same I did the following little trick so that you can call paginate on a plain old array.

class Array
  def paginate(page=1, per_page=15)
    pagination_array = WillPaginate::Collection.new(page, per_page, self.size)
    start_index = pagination_array.offset
    end_index = start_index + (per_page - 1)
    array_to_concat = self[start_index..end_index]
    array_to_concat.nil? ? [] : pagination_array.concat(array_to_concat)
  end
end

Before folks say anything about the above code.. yes I know it could be more concise if I didn’t use all the local variables but I wanted it to be really clear what I was doing here so.. leave it alone.

Now basically you can say

myarray.paginate(params[:page], per_page)

If you want to see it work yourself feel free to run this spec.


require File.dirname(__FILE__) + '/../spec_helper'

describe 'Given we call paginate on an array' do
  it 'should return an array containing the first 3 elements of the org array when page = 1 and per_page_count = 3' do
    array = ["a","b","c","d","e"]
    current_page = 1
    show_per_page = 3
    expected_array = ["a", "b", "c"]
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an array containing the last 2 elements of the org array when page = 2 and per_page_count = 3' do
    array = ["a","b","c","d","e"]
    current_page = 2
    show_per_page = 3
    expected_array = ["d", "e"]
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an array containing all the elements of the org array when page = 1 and per_page_count = 5' do
    array = ["a","b","c","d","e"]
    current_page = 1
    show_per_page = 5
    expected_array = ["a","b","c","d","e"]
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an array containing all the elements of the org array when page = 1 and per_page_count greater than org number of elements i.e = 6' do
    array = ["a","b","c","d","e"]
    current_page = 1
    show_per_page = 6
    expected_array = ["a","b","c","d","e"]
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an empty array if you ask for a page that does not exist' do
    array = ["a","b","c","d","e"]
    current_page = 3
    show_per_page = 5
    expected_array = []
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an empty array if you ask for a negative page number' do
    array = ["a","b","c","d","e"]
    current_page = -1
    show_per_page = 5
    expected_array = []
    (array.paginate(current_page, show_per_page)).should == expected_array
  end

  it 'should return an empty array if you ask for a negative per_page number' do
    array = ["a","b","c","d","e"]
    current_page = 1
    show_per_page = -5
    expected_array = []
    (array.paginate(current_page, show_per_page)).should == expected_array
  end
end
ˆ Back to top

Perl: Climbing Trees

June 6th, 2007 by comment Nola

HTML tree, that is… Ahh HTML. The tree with often not so perfect branches. Recently for one of my projects I had to grab certain bits of information from a series of HTML pages. The HTML was proper in some and not so good with others (huh? Font tags? Poorly nested tags?). I thought about parsing it as I would an XML document but given the “crooked branches” I figured that wouldn’t work. I could write a mess of regex, but gee — isn’t there a better way? Through a series of searches and poking around, I discovered HTML::Tree module which seemed to suit my purpose well! I will not bore you with the use I had for using HTML::Tree, so I made a fun sample:

#!/usr/bin/perl

use warnings;
use strict;
use diagnostics;

use HTML::TreeBuilder;

The typical top of a Perl script. I usually ″use diagnostics″ when developing and take it out when I am done. Just give you more verbose error messages. I need all the help I can get!

Now the fun stuff:

I made a function to load the DevChix homepage that I had saved to a local file. Ideally, this data would be pulled live from the site. For now though, I start simple.

sub load_tree {
   my $page = HTML::TreeBuilder->new();
   $page->parse_file('DevChix.htm');
   return $page;
}

This returns the TreeBuilder object with my data loaded. Using the most awesome tool Firebug (Also, see Jen′s post about it awhile back), I see that the sidebar list is a div tag with id of “sidebarposts”. Lets look down our Html Tree and find that element:

my $page = load_tree();

my $sidebar = $page->look_down( '_tag', 'div',
   sub { $_[0]->id eq 'sidebarposts' } );

Not too complex. Look down the tree, look for a tag thats a div with the id of “sidebarposts” .. gee, thats nearly english (and people say that Perl is jibberish! Bah!).

Now, lets grab the li elements in that div:

my @ul_list = $sidebar->look_down('_tag','li');

foreach my $li(@ul_list) {
  print $li->as_text, "\n";
}

I know I′ll be getting back more than 1 element so I assign it to an array instead of a scalar. Then in the for loop, I want to iterate through the list and print the element as text, which gives me the name of the link.

Output is something like this:

...
Regular Expressions: The Wart on the Bum of Every Language in Existence
RUBY: DRY up your Enumerations
*waving, not drowning*
Beautiful Python: The programming language that taught me how to love again
RailsConf
Test More for Java?!
Book Review: Beginning Ruby On Rails E-Commerce
...

Using a code ref to find elements came in extremely handy when I had some bunked up HTML, sometimes I had to look_down a table, find a tr that contained a table which had a certain class, or find all href tags that had a certain domain in the URL and then grab the tr container so I could grab the following tr .. etc.

The Tree::Builder interface has a ton more methods than I’ve talked about and you should take a look at it next time you need to grab bits from html pages!

ˆ Back to top

Dynamic Web Content: What you can do in Postgresql that you cannot do in Oracle.

May 27th, 2007 by comment gloriajw

With the advent of dynamic online content comes the need to create, destroy and manage this content in more automated and efficient ways. I have discovered some very nifty ways to do this in Postgresql which cannot be done as well, as easily, or even at all in Oracle. As it turns out, Postgresql is very well suited for dynamic database generation, for any size data set.

Let’s say you have a web site where users create dynamic content. You have these basic choices when determining how to store your content:

1. Place everything in a monolithic database (one large database, many indexed fields), sorting by key/indexed fields. User content can be distinguished by a unique user id, or maybe there is no need to distinguish user content at all. It depends on the data being stored, and the applied use of that data.

2. Dynamically create a database from a fixed (or even from a dynamic) database schema. Store all user data in a separate database, and metadata in a common (master) database.

Option 1 is the most common. Everyone doing web content seems to want to default to this model, maybe because it is the easiest to roll out quickly, maybe because they think they have no other choice.

In some cases, it’s an appropriate model based on the data set. An example that comes to mind which makes this model appropriate would be weather reporting. In a weather database, it probably doesn’t matter who recorded last night’s rainfall around the world, as long as the person had legitimate access, and recorded the data correctly. It also probably makes no sense to break the data out into different databases by zip code, region, or state. The purpose of collecting weather data is not only to report local weather conditions, but to also measure and compare the data statewide, nationwide, or worldwide. This is a contrived but decent example of a data set best being served by a monolithic database.

An example of data which can/should be broken out into separate databases is an inventory application. Let’s say you provide online inventory information for many companies, where each company is unrelated to another. Companies may even have security concerns, or may not want other companies to have access to their hardware inventory data, for example, because it may reveal trade secrets regarding what proprietary hardware designs they have devised for their business needs. Companies may also want to separate and secure their inventory data because competitors can derive sales information form this data.

A monolithic database could be used in this model, but how do you guarantee one client that their data is secure, and will not be exposed to another client, even by accident? Complex selective encryption methods could be used on the monolithic model, but why bother? Breaking the data out into separate client databases is ideal for this data model for many for these reasons:

1. Security: Data is inherently separate. Separate databases can easily be encrypted if necessary. Logins/passwords to each database can be isolated to the individual database.
2. Data Management: Individual client data can easily be archived, exported or purged to meet clients needs.
3. Local Database Support: The model inherently supports database servers owned and run by the client. If the client chooses to switch to a model where they run and maintain your software behind their own firewall, the client’s database can easily be exported, encrypted, sent to the client, decrypted, and imported on their server.

Of course, these issues can be dealt with in the monolithic model, with much wrestling and convoluted scripting/management, but again, why make the job of the developers and database admin more difficult?

Using the above example, let’s say we have an inventory database schema for Postgresql which looks something like this, in a file called client_db_schema (Highlight the text if you have trouble seeing it all):


CREATE SEQUENCE simple_inventory_id_seq  # The sequence number is for DBAPI 2.0 compliance.
    INCREMENT BY 1
    MINVALUE 1
    NO MAXVALUE
    CACHE 1;

CREATE TABLE simple_inventory (
        simple_inventory_id integer unique DEFAULT nextval(('simple_inventory_id_seq'::text)::regclass) NOT NULL PRIMARY KEY,
        item_number integer unique NOT NULL,
        item_description character varying NOT NULL,
        (...any other fields you can imagine)
);

(more client-specific tables go here)

After installing Postgresql, run the createuser command:

createuser -s queen_bean

It will prompt you for a password.

The “queen_bean” super user can create or destroy databases, create other users, etc. She really is the queen.

To create a new inventory database from Python and psycopg, do this:

import os
import psycopg

super_db = psycopg.connect('dbname=template1' + ' user='queen_bean' + ' password=whatever the password is' + ' port=' +   str(5432) + ' host=localhost')
cursor = super_db.cursor()

# Notice that 'template1' is the actual name of the Postgresql internal master database.
# Connect to this to do database create/delete operations, but don't delete the template1 database itself.

super_db.conn.set_isolation_level(0) # This tells Postgresql that we're about to do high level, 'narrow' admin operations.

for i in range(1,6):
     client_string = "client%d" % i
     #cursor.execute("drop database %s_inventory;" % client_string)  #optional
     cursor.execute("create database %s_inventory with encoding = 'UTF-8' ;" % client_string)
super_db.close()

To do this on the command line instead of in Python, you’d type this:

psql template1 queen_bean

psql> create database client1_inventory;
psql> create database client2_inventory;
etc...
pqsl> \\q

This loop created five different, empty client databases. Now we need to add the tables from the client database schema to each database:

# This is the schema file we created above. It's in the current directory, but could be anywhere (change the  ./ component).
new_tables = os.path.abspath(os.path.join(os.path.dirname(__file__),"./client_db_schema"))

# Read this file into memory:
fo = open(new_tables)
commands = ' '.join(fo.readlines())
fo.close()

for i in range(1,6):
     client_string = "client%d" % i

     client_db = psycopg.connect('dbname=' client_string + '_inventory' + ' user='queen_bean' + ' password=whatever the password is' + ' port=' +   str(5432) + ' host=localhost')
     cursor = client_db.cursor()

     cursor.execute(commands)
     client_db.close()

The command line equivalent would be:

psql client1_inventory queen_bean < ./client_db_schema
psql client2_inventory queen_bean < ./client_db_schema
etc...
\\q

The above code is an oversimplification of some db concepts. But it works, and it demonstrates how simple it is to dynamically generate Postgresql databases for client data management.

In Postgresql, all databases are managed under the same data area on the disk. They are all accessible through the same database instance, or daemon. This is why we only connected once to the template1 master database to create the client databases.

In Oracle, the terminology is slightly different. A ‘database’ is understood to be the running instance, or daemon. The ‘instance’ is an individual database as Postgresql would know it. To create new Oracle ‘instances’, or databases requires shutting the entire Oracle daemon down! This means that all users accessing all oracle instances at that moment lose connectivity, because a new database is being dynamically generated.

In any database tool, a shutdown is not trivial. Connection cleanup, index cleanup, memory flush to disk, and garbage collection, amongst other things, happen during shutdown. This means that shutdown could take minutes to perform, making this model impossible to use under Oracle. Being experienced in both Oracle and Postgresql, I could list many other reasons why you would not want to use Oracle over Postgresql on any given day for any given project, but that is material for yet another article.

The above code implies some other neat features as well. Since the database schema comes from a file, that file could be generated in real time, from FORM data. So not only is the database dynamically created, but the schema can change in real time as well.

Beware of bogus arguments against this model:

Gripe: “But a separate connection is required for each user, for each database. This means thousands of connections, which could cause problems”
Answer: ZZZTTTT! Wrong. Connections which are open but inactive take up very few, if any, database resources. Plus, in a dynamic web design, the connection is being opened and closed immediately after use. So connections never linger, because of the threaded model of a web server. Plus, pg_pool does a good job at managing connections, if for some reason they are left open (usually programming bugs and crashes cause this). Unlike Oracle, a process’ database connections are all closed when the process closes. So bouncing an HTTP server will forcably cause db connection cleanup in Postgresql. In Oracle, connections are stored in the IPC table (Inter process communication table, a system resource), and they must be manually closed/cleared.

Gripe: “The multiple database model is inefficient and will negatively affect performance.”
Answer: BBBBBLLLAAP! Wrong. Testing has revealed that it is no more or less efficient than the monolithic database. This model is used very effectively in production web sites.

I hope this serves as a handy primer, and encourages you to play. Feel free to post questions.
~G~

ˆ Back to top

RUBY: DRY up your Enumerations

May 25th, 2007 by comment sandi

Using Higher Order Messaging to honestly reveal your intentions.

If you had a collection of stooges (@stooges) and you were looking for Mo, would you rather say:

@stooges.select {|s| s.name == 'Mo'}

or

@stooges.that.have.name == 'Mo'

I don’t have to ask you twice, right?

In the first example, the fact that it’s an enumeration overwhelms the intention to find Mo.

In the second example, the most obvious thing is that I want Mo. The fact that @stooges is a collection is obviously not the most important thing. What matters is that I want Mo and example 2 does a much better job of revealing that.

This is not magic. It’s Higher Order Messaging. And trust me, you want it.

I stumbled across HOM on Why’s blog over a year ago. I followed a link from his site to some other site and downloaded ho_enumerable.rb (sorry, I can no longer find the orginal site, but if you know, let me know and I’ll make proper attribution here). I’ve been using HOM with delight ever since.

What is Higher Order Messaging?

Higher order messaging lets you talk to collections in a natural way that reveals instead of conceals your ultimate intentions. Here are more examples.

(To follow along at home, download hom_examples.rb and ho_enumerable.rb).

Given class Stooge:

class Stooge

 attr_reader :name, :hair, :habit

 def initialize(aRow)
  @name   = aRow[0]
  @hair   = aRow[1]
  @habit  = aRow[2]
 end

 def baldish?
  hair.nil?
 end

 def muck_with_name
  name.gsub!(/y/, 'x')
 end

 def to_s
  "#<Stooge - name:#{name} hair:#{hair} habit:#{habit}>"
 end
end

and array STUFF

STUFF = [[ 'Mo',    'bowly', 'eye poking' ],
         [ 'Larry', 'curly', 'whomping'   ],
         [ 'Curly',  nil,    'whining'    ]]

I can create a new collection of Stooges by saying

@stooges  = STUFF.as(Stooge)

instead of

@stooges = STUFF.collect {|r| Stooge.new(r)}

I can select all of the stooges that are nearly bald by saying

@stooges.that.are.baldish?

instead of

@stooges.select {|s| s.baldish?}

I can find all of the stooges named ‘Mo’ by

@stooges.that.have.name == 'Mo'

instead of

@stooges.select {|s| s.name == 'Mo'}

I can build an array of all of their names by saying

@stooges.extract.name

instead of

@stooges.collect {|s| s.name}

I can find out if ‘all’, or ‘any’, stooges ‘are’ or ‘have’ some quality. (Since you’re completely sold now I’m gonna leave the iteration style code to you).

@stooges.all.are.baldish?  # false
@stooges.any.are.baldish?  # true
@stooges.all.are_not.baldish?  # false
@stooges.any.are_not.baldish?  # true
@stooges.all.have.name == 'Mo'  # false
@stooges.any.have.name == 'Mo'  # true

I can also order the stooges by some attribute.

@stooges.in_order_of.name
@stooges.in_reverse_order_of.name

And I can perform some operation against every stooge.

@stooges.do.muck_with_name

The ho_enumerable code is very short and delightfully nerdly. You may or may not be interested in looking at it to figure out how it works, but you don’t have to understand the details of implementing HOM to recognize what a great idea this is.

Stick ho_enumerable in your rails/lib directory, require the file and start using HOM. Your code will please you by revealing what it’s doing without drowning you in detail about how it’s doing it. And when your friends have to maintain it, they’ll like you even better than you like yourself.

ps – Thanks to Lori Evans for pouring over the ho_enumerable code with me on the plane on the way home from railsconf. It was more than can possibly be expected of any exhausted human being and she was alarmingly cheerful about it. Thanks.

ˆ Back to top

DIY Binary Hands, base-CAT, and counting to 10 (or is it 2)?

April 19th, 2007 by comment sarah g

Some time ago, I was learning binary operators and struggling to understand the base-2 system of counting. It felt very foreign to me. My friend Zack explained that the reason we use base-10 is really related to the fact we have 10 digits on our hands: i.e., it’s easy and comes naturally. Most people don’t even think of it: it’s just how counting “works”. But, base-10 or “decimal” is not the only counting system, and not the best for every usage (for instance, in computers the binary system makes the most sense because it’s easy to implement electronically). Nor is it the only counting we can do with our hands! In this post we’ll make our very own pair of binary hands that can count, not only to 10, but to 1023… Here goes.

Before getting to the fun part (making hands at home!) it’s worth mentioning that the main difficulty in learning binary is that while describing binary one is often compelled to compare the number to decimal, because we think in decimal so naturally that it seems like it’s the only “real” way of explaining a quantity. This leads us to conflate the representation of the quantity (say, 2 [decimal]) with the fact of the quantity (say, a pair of cats) and treat them as if they are one and the same. When in fact, a numeric description is just that: a description of a quantity. And depending on the base used, one of many possible descriptions of the same quantity. This was a problem for me and is for others, often leading to long transliteration exercises such as: 10[binary] == 2[decimal] followed by a string of powers and multiplications explaining why. What gets lost in the shuffle is the fact of the pure quantity of the measured, which is independent of the base describing it. In this post, I’ll append the string [binary] to digits in base-2, and the string [decimal] to digits in base-10, to make reading easier.

Now, just so you don’t feel cheated, here is that string of powers and multiplications I mentioned above (and again, read wikipedia for a full explanation). So, in binary, the digits “10″ don’t equal the quantity of ten[decimal]: they equal (in decimal): two. This is because:

(1 x 2^1) + (0 x 2^0).
In other words, 2 + 0. Or, two[decimal].

In decimal, the digits “10″ equals ten because it works out to:

(1 x 10^1) + (0 x 10^0).
Or,  10 + 0. Ten [decimal].

Now, here is the same digit-al representation but getting at the underlying quantity of the represented. What do we have here? A pair of cats, eating dinner.

base cat

How many cats is that? You could say there are 10[binary] cats eating dinner. Or 2[decimal] cats eating dinner. But, as William Shakespeare famously said, “A cat in any other base will still eat dinner”.

The fun part:
Despite the fact that it’s relatively simple to get on paper… and when you start using base-cat, it’s almost graspable, it can be hard to reach the “aha!” moment where counting in binary makes natural sense. It’s like cursing in french: you want it to come out easily as cursing in, say, cartoon:

"*#$&!!" == "merde"

The point is, no matter how you say it, you’re still having a bad day! It’s just that, as some bases are more suited to building computers than others, some languages are more suited to inclusion in PowerPoint presentations than others. Speaking of french translation, bad days, and DIY, can you translate “vas te faire encule” to binary? Once you start playing with the hands, I’m sure you can! (hint: it’s 132[decimal], represented in 10 bits, and it’s not work-safe!:)).

Anyway, working towards that moment of enlightenment, we went through the binary finger exercises (a fun java applet is here), which were new to me at the time. To better concretize the system for myself, I took a pen and marked up my knuckles and the pads of my fingers so I could see both the decimal numbers and the binary numbers, as well as their relationship (up, or “on” is represented by 1: down, or “off”, by 0).

I’m a hands-on learner, pun partially intended: the more I can see or demonstrate a concept in human-space, the better I understand it. But, since I was planning to wash my hands before I had fully mastered the new counting, I decided to make permanent versions, to keep and refer to always.

Here’s how you can do this at home: (What am I learning again?)

Materials Needed

1. Hands, 2, preferably yours.

2. Cardstock

3. Pen

4. Scissors

5. Refrigerator magnets (optional)

6. Refrigerator (optional, but really nice to have)

Steps:

1. Trace the outline of both your hands on the cardstock, fingers spread like you’re making a thanksgiving turkey.

2. Cut them out.

3. Place the hands, palms-up, on the table in front of you. On the base-pads of the “fingers”, counting in base-2, start from “1″ at the base of your right thumb. You will get up to 512[decimal] by your left thumb. 1,2,4,8,16,32,64,128, 256,512

4. On the front-tip of each finger, draw a 1

5. Fold the fingers down, and draw a 0 on the knuckle of each bent finger. When the finger is folded, it should obscure the digit on the palm of your hand so that all you see is the 0.

To count:

You can count to any number, up to 1023[decimal] — which is a lot of cats! — by raising and folding your fingers. Notice that each finger represents 2 raised to the next power, which is what base-2 (or base-anything) means. You will be able to see the binary representation of each number from the configuration of 1s (raised fingers) and 0s (folded fingers).

When a finger is raised, and you can see the number on your palm, that bit is “on”, represented by the visible number 1. When a number is obscured, it is “off” and you do not count it: what you see instead is the 0 of your folded knuckle. The number (in decimal) that you reach will be the sum of the visible digits on the palm of your hand.

So, for instance, to get to 1023[decimal], which is the highest you can count with 10 fingers, you’d have all 10 fingers raised so you can see all the digits, like so:


e.g., 1+2+4+8+16+32+64+128+256+512 = 1023[decimal]

Likewise, to get to 0, fold all your fingers: it’s that simple. Of course, there is no need for 10 bits to encode the value of 0 — we’re fine with 1 bit. But, since in this example we’re using our hands and can’t very well lop off our other 9 fingers, it makes sense to just keep them folded. In short, [0+0+0+0+0+0+0+0+0+0+0=0].

Using the combination of refrigerator magnets or just bare or paper hands, challenge yourself to count to any number between 1 and 1023[decimal]. Represent household quanties of items in binary. Fold and raise the appropriate fingers so the visible sum adds up to the number you’re thinking of or looking at, and then read the binary representation of the number in the 1s and 0s of your fingertips and knuckles.

A few other examples

How about 61[decimal]? [32 + 16 + 8 + 4 + 1 = 61].


Or, 449[decimal]:[256 + 128 + 64 + 1 = 449]

You’ll see in the final picture, a yellow rabbit came on the scene. It is a little-known fact that yellow rabbits excel at counting in base-2.

In closing

What I think is the most interesting about this is thinking of what other “real world” implementations you can come up with to represent otherwise abstract principles. When you can start to translate concepts into your own space it allows you to “get” them in a way you might not just reading about them on paper.

I’d love to see other examples of this — how high could you count if your feet were involved? What would base-8 hands look like? What are particularly obtuse concepts you’ve mastered that could be extrapolated using paper, scissors, refrigerator magnets and household pets? Sharing welcomed — and happy counting!

ˆ Back to top

For want of a comma

March 1st, 2007 by comment Liz

my kingdom was lost.

Watch those commas. A little SQL detail that can bite you:

SELECT
SID
NAME,
ETC
FROM MYTABLE

MySQL, and presumably other databases, is just fine with that statement. It’ll alias the field SID to NAME. If you name columns explicitly with the AS keyword, a missing comma will yield an error:

SELECT
SID AS studentid <--baaarf
NAME AS studentname,
ETC AS studentetc
FROM MYTABLE
ˆ Back to top