<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7625777308693137417</id><updated>2012-01-09T15:51:20.601+11:00</updated><category term='esoteric'/><category term='emacs'/><category term='other'/><category term='reports'/><category term='dns'/><category term='security'/><category term='twitter'/><category term='perl'/><category term='project euler'/><category term='reverse engineering'/><category term='irc'/><category term='unicode'/><category term='github'/><category term='vim'/><category term='lisp'/><category term='osx'/><category term='assembly'/><category term='ipv6'/><title type='text'>Luke's Thought Dump</title><subtitle type='html'>Anything about Vim, Emacs, Perl, Lisp, OS X, FreeBSD, Linux or whatever the hell I'm using today.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-7642846353664179344</id><published>2012-01-02T18:00:00.000+11:00</published><updated>2012-01-02T18:00:01.951+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='other'/><category scheme='http://www.blogger.com/atom/ns#' term='reports'/><title type='text'>How I Deal with Lots of Data</title><content type='html'>&lt;p&gt;Just for some context, by "lots of data", I mean a couple hundred million rows in a table joined to other tables of similar size. By no means is it a lot compared to what other people deal with, but it's certainly enough to warrant some forethought instead of just diving right in.&lt;/p&gt;

&lt;p&gt;Late last year, I was tasked with a few one-off reports that required me to summarise data that was stored over a couple hundred million rows in a database. Knowing that it was going to be a long process to retrieve the data for these reports, I had to come up with a game plan to do this as quickly and as efficiently as possible. In the process of doing this, as always when handling relatively large quantities of data, a few things were learned. None of these lessons/ideas are new or original, but I wanted to write them down somewhere, and here feels like as good a place as any.&lt;/p&gt;

&lt;p&gt;Extracting the data that I needed (which, in one instance, was a subset of a couple of ~300 million row tables) into a local database meant I was able to modify the data (like cleaning up dirty, inconsistent spellings of suburbs, states and countries) and modify the schema (like adding new indexes which, because of the odd nature of the reports, the production databases didn't have or ever need previously).&lt;/p&gt;

&lt;p&gt;Assuming that you don't require something like schema changes, that local database doesn't even need to be a relational database. CSV files work perfectly fine a lot of the time. For a couple of reports I wrote a handful of scripts, the first of which was to pull the data out of the MySQL database, perform some simple operations on the data and output it into a CSV file. The other scripts that needed to operate on the same data could then easily (thanks to &lt;a href="https://metacpan.org/module/Text::CSV_XS"&gt;Text::CSV_XS&lt;/a&gt;) read the CSV data, which was a lot quicker than reading it from a relational database.&lt;/p&gt;

&lt;p&gt;Why do CSVs lend themselves nicely to this kind of task? Because with reports like these, in my experience, you very rarely perform complicated operations on the data after extracting it from the original data source(s); you just want to suck the data up, summarise the data, output the summary, and then output the nitty gritty details on subsequent pages or into a separate file.&lt;/p&gt;

&lt;p&gt;An obvious advantage to storing the data like this is the speed in which you can retrieve and process the data. That improvement made a huge difference for me because I like to run my scripts very often throughout the development process, no matter how small the change.&lt;/p&gt;

&lt;p&gt;Of course, depending on the size of the data (in bytes), extracting the data into a local database of some sort may not always be possible.&lt;/p&gt;

&lt;p&gt;The last big win I had was &lt;em&gt;not&lt;/em&gt; using object-relational mappers (&lt;a href="https://metacpan.org/module/Class::DBI"&gt;Class::DBI&lt;/a&gt; in this case). They're great a lot of the time and save on code and development time, but when dealing with millions of rows, they just add bloat and everything runs much slower than it should.&lt;/p&gt;

&lt;p&gt;That's all I can think of now, a few months later.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-7642846353664179344?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/7642846353664179344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2012/01/how-i-deal-with-lots-of-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/7642846353664179344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/7642846353664179344'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2012/01/how-i-deal-with-lots-of-data.html' title='How I Deal with Lots of Data'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-6185137902005358486</id><published>2011-06-28T13:44:00.005+10:00</published><updated>2011-06-28T14:04:18.757+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='irc'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Crappy IRC and Unicode</title><content type='html'>&lt;p&gt;I use MacIrssi as my IRC client at work and at home. It's mostly great. By mostly, I mean, I wish when people sent smart-ass messages on IRC filled with unicode characters, I could actually appreciate how much of a smart-ass they are being. Instead, all I see is this:&lt;/p&gt;

&lt;pre&gt;&lt; ganeshanator&gt; gonna go to the \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
    and \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
    getting those \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
    and the \u2588\u2588\u2588\u2588\u2588
    on \u2588\u2588\u2588\u2588\u2588&lt;/pre&gt;

&lt;p&gt;I always forget how to convert it, so I wrote this, and now I never have to remember again:&lt;/p&gt;

&lt;pre&gt;#!/usr/bin/env perl

use warnings;
use strict;

use Encode;

sub unicode_plz { encode( 'UTF-8', pack( 'U', hex shift ) ) }

( my $message = shift ) =~ s{\\u([a-fA-F0-9]+)}{unicode_plz($1)}ge;
print "$message\n";&lt;/pre&gt;

&lt;p&gt;And, &lt;a href="http://i.imgur.com/haOD4.jpg"&gt;BAM!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crappy was a harsh word. MacIrssi is pretty great, except for this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-6185137902005358486?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/6185137902005358486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/06/crappy-irc-clients-and-unicode.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6185137902005358486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6185137902005358486'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/06/crappy-irc-clients-and-unicode.html' title='Crappy IRC and Unicode'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-4593162966885112035</id><published>2011-03-31T08:32:00.004+11:00</published><updated>2011-03-31T13:28:29.764+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>DateTime Woes</title><content type='html'>&lt;p&gt;This morning, &lt;a href="http://i.imgur.com/tkL5R.jpg"&gt;I hate DateTime for this&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;$ perl -MDateTime -wle'$a = DateTime-&gt;today( time_zone =&gt; "Australia/Melbourne" ); $b = DateTime-&gt;today; $b-&gt;set_time_zone("Australia/Melbourne"); print $a-&gt;iso8601; print $b-&gt;iso8601'
2011-03-31T00:00:00
2011-03-30T11:00:00&lt;/pre&gt;

&lt;p&gt;I understand &lt;em&gt;why&lt;/em&gt; it happens, but it's still an annoying, pissy, little bug to find. &lt;em&gt;sigh...&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-4593162966885112035?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/4593162966885112035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/03/datetime-woes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4593162966885112035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4593162966885112035'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/03/datetime-woes.html' title='DateTime Woes'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-2656134983702158037</id><published>2011-02-03T12:48:00.003+11:00</published><updated>2011-02-03T13:11:28.248+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Update to an Old Post</title><content type='html'>&lt;p&gt;A past post about &lt;a href="http://lukesthoughtdump.blogspot.com/2009/06/tweeting-from-command-line-with-perl.html"&gt;tweeting from the command line with the Net::Twitter Perl module&lt;/a&gt; is one of my most visited entries. Anytime I check my traffic, it is always the second most visited entry for the day/week/whatever. However, it has a problem. The code does not work anymore for a simple, yet annoying, reason.&lt;/p&gt;

&lt;p&gt;Last year, Twitter turned off its basic authentication support and now requires application developers to use OAuth. More detail about how that affected Net::Twitter can be read &lt;a href="https://github.com/semifor/Net-Twitter/wiki/Net::Twitter-and-the-death-of-Basic-Authentication"&gt;here&lt;/a&gt;. This kinda sucks because it's not longer as simple as providing a username/password combination. You need consumer keys/secrets and access tokens/secrets and that makes things a tad messier.&lt;/p&gt;

&lt;p&gt;The original code I posted uses basic authentication and, obviously, will not work anymore. However, if anyone is interested, the code for that small side-project, &lt;a href="https://github.com/ltriant/twitsh"&gt;Twitsh.pm&lt;/a&gt;, is on github and I recently updated it to use OAuth so that it works again, however the configuration file requires you to add your own consumer/access keys/tokens/secrets. Enjoy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-2656134983702158037?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/2656134983702158037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/02/update-to-old-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2656134983702158037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2656134983702158037'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/02/update-to-old-post.html' title='Update to an Old Post'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-718445861722326015</id><published>2011-01-23T20:10:00.003+11:00</published><updated>2011-01-23T20:34:51.787+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ipv6'/><title type='text'>Goal for the Year: IPv6</title><content type='html'>&lt;p&gt;First blog post for the year! Yay? And I'm only setting myself one goal for the year: Learn everything about IPv6 and set it up at home.&lt;/p&gt;

&lt;p&gt;And by everything, I mean everything; from IPv6 packet headers to the implementation complexities to the business issues to the security issues to the political issues.&lt;/p&gt;

&lt;p&gt;Why? Because, &lt;em&gt;potentially&lt;/em&gt;, in the next decade, migrating from IPv4 to IPv6 will become important, and considering that it's a topic that I know next-to-nothing about, other than what I've read in passing on IRC, it's a knowledge gap that needs filling.&lt;/p&gt;

&lt;p&gt;It's certainly possible that this will all take me less than a month, assuming enough free time. When that time comes, perhaps I'll pick a non-geek goal to spend my time on this year.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-718445861722326015?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/718445861722326015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/01/goal-for-year-ipv6.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/718445861722326015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/718445861722326015'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2011/01/goal-for-year-ipv6.html' title='Goal for the Year: IPv6'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-4456558702846176389</id><published>2010-12-01T22:48:00.010+11:00</published><updated>2010-12-10T12:24:40.439+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dns'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Host Discovery via SPF Records?</title><content type='html'>&lt;p&gt;So... my once-a-month posts OCD issue went unsatisfied for the past 2 months. Oh well. Back to business...&lt;/p&gt;

&lt;p&gt;Sender Policy Framework (SPF) records are often used as one method of combatting spam; specifically, spam that wants to look like it has been sent by your company. The general idea is that your SPF records specify which hosts and IP addresses are allowed to send email using your domain(s) in the envelope 'from' address. Any other host, which is not contained within the SPF policies, that attempts to send mail from your domain will fail the SPF check and, hopefully, get picked up by some kind of spam detection software further down the track. It is highly recommended that you setup SPF records for any domains that you own.&lt;/p&gt;

&lt;p&gt;How are SPF records requested? Via DNS. They are usually contained within the TXT record, however they can also, occasionally, be found in the SPF record aswell. &lt;a href="http://en.wikipedia.org/wiki/Sender_Policy_Framework#Implementation"&gt;The format&lt;/a&gt; is very easy to understand. An typical example to look at would be optus.com.au:&lt;/p&gt;

&lt;pre&gt;IN TXT "v=spf1 mx/24 include:opt01._spf.optin2.com.au ip4:180.92.216.0/21 include:rightnowtech.com include:rnmk.com include:custhelp.com ~all"&lt;/pre&gt;

&lt;p&gt;Do the hosts (and the range of IP addresses) in the policies belong to optus.com.au? Maybe. Maybe not. We cannot discern that just by looking at the host names, nor can we, within any real degree of certainty, determine it programmatically. However, the hosts' SPF records have been trusted to send mail on behalf of optus.com.au, so they remain hosts of interest for penetration testers and may not pop up in other DNS requests (A, MX, AFXR, etc..)&lt;/p&gt;

&lt;p&gt;What is a common example of a host who would be in a domain's SPF policies but not actually part of the company who owns the policy? Any mail filtering company who filters outbound mail.&lt;/p&gt;

&lt;p&gt;Just a thought that has been floating around in my head...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-4456558702846176389?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/4456558702846176389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/12/host-discovery-via-spf-records.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4456558702846176389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4456558702846176389'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/12/host-discovery-via-spf-records.html' title='Host Discovery via SPF Records?'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1213253074344910186</id><published>2010-09-30T13:48:00.008+10:00</published><updated>2010-10-02T01:42:57.803+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>End of the Month...</title><content type='html'>&lt;p&gt;Well, it's the end of the month, which seems to have become the day that I write a new blog entry (I feel somewhat empty if there's a month missing from the sidebar over there), but I don't have anything very interesting to post, so I'll post something a little less interesting: A github project I use for testing libraries, &lt;a href="http://github.com/ltriant/Mazer"&gt;Mazer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mazer is a rewrite of an old assignment I did years ago in C++. Originally it just had to automatically solve a maze step-by-step, as if simulating a human walking through the maze. I often write this same program when I start learning a new programming language (which I did for Haskell and Common Lisp), or, as was the case this time around, to play around with libraries. It was the first bit of code I wrote using &lt;a href="http://search.cpan.org/perldoc/Moose"&gt;Moose&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc/Test::Class"&gt;Test::Class&lt;/a&gt; (the tests actually pass!) and, most recently, &lt;a href="http://search.cpan.org/perldoc/Curses::UI"&gt;Curses::UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's nothing special about it. It has basically become my sandbox for Perl libraries. Perhaps others would find it useful, though.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1213253074344910186?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1213253074344910186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/09/end-of-month.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1213253074344910186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1213253074344910186'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/09/end-of-month.html' title='End of the Month...'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-3497572015810811806</id><published>2010-08-31T21:10:00.004+10:00</published><updated>2010-08-31T21:35:47.060+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>The State of the PDF::API2 Graphics Object</title><content type='html'>&lt;p&gt;Often when I write scripts with PDF::API2, I modify the state of my graphics object a lot. Sometimes to change the current fill color, or line thickness, or perhaps to set line dashing. Usually, once I have finished drawing the object, I want to set the state back to what it was before, and then continue on with the rest of the script. Rather than having to either re-set everything on the graphics object or use a new graphics object, there are two methods that will help you out.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;save&lt;/em&gt; and &lt;em&gt;restore&lt;/em&gt; methods will, surprisingly, save and restore the state of your graphics object. What makes it even more handy, is that you can save multiple states and have a stack of states. Some example code:&lt;/p&gt;

&lt;pre&gt;#!/usr/bin/env perl

use warnings;
use strict;

use PDF::API2;

my $pdf = new PDF::API2;

my $page = $pdf-&gt;page;
$page-&gt;mediabox( 100, 60 );
my $gfx = $page-&gt;gfx;

# Make it red.
$gfx-&gt;strokecolor('red');
# Save the first state
$gfx-&gt;save;

$gfx-&gt;move( 10, 10 );
$gfx-&gt;line( 90, 10 );
$gfx-&gt;stroke;

# Make it blue, a bit thicker and add some dashing.
$gfx-&gt;strokecolor('blue');
$gfx-&gt;linedash( 1, 5 );
$gfx-&gt;linewidth(5);
$gfx-&gt;move( 10, 20 );
$gfx-&gt;line( 90, 20 );
$gfx-&gt;stroke;
# Save the second state
$gfx-&gt;save;

# Set some new parameters.
$gfx-&gt;strokecolor('yellow');
$gfx-&gt;linedash();
$gfx-&gt;linewidth(3);
$gfx-&gt;move( 10, 30 );
$gfx-&gt;line( 90, 30 );
$gfx-&gt;stroke;

# Revert back to the 'blue' state.
$gfx-&gt;restore;
$gfx-&gt;move( 10, 40 );
$gfx-&gt;line( 90, 40 );
$gfx-&gt;stroke;

# Revert back to the 'red' state.
$gfx-&gt;restore;
$gfx-&gt;move( 10, 50 );
$gfx-&gt;line( 90, 50 );
$gfx-&gt;stroke;

$pdf-&gt;saveas("$0.pdf");&lt;/pre&gt;

&lt;p&gt;Run the code and you should get the following:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://imgur.com/96iR4.png" /&gt;&lt;/p&gt;

&lt;p&gt;Handy, I think.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-3497572015810811806?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/3497572015810811806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/08/state-of-pdfapi2-graphics-object.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3497572015810811806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3497572015810811806'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/08/state-of-pdfapi2-graphics-object.html' title='The State of the PDF::API2 Graphics Object'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-7500491220640622014</id><published>2010-07-27T12:28:00.005+10:00</published><updated>2010-07-27T13:23:49.886+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>PDF Library for Laying out Widgets... or something...</title><content type='html'>&lt;p&gt;At work I have pretty much become the developer that writes the code to produce reports, whether the output be in PDF, CSV, XLS or whatever format is required. When I started this job, the first task I was assigned was to create a particular report (mentioned in a &lt;a href="http://lukesthoughtdump.blogspot.com/2010/05/pdfapi2-is-underrated.html"&gt;previous PDF::API2 post&lt;/a&gt;), and even now, a year and a half later, I am re-writing a handful of reports for our client-facing web console. Most of the reports I develop, new ones in particular, are outputted as PDF documents.&lt;/p&gt;

&lt;p&gt;My process for developing PDF reports is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Figure out what data is going where.&lt;/li&gt;
&lt;li&gt;Measure up the coordinates.&lt;/li&gt;
&lt;li&gt;Do the magic that gets the data and outputs it in pretty graphs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After writing code for dozens of reports, step 2 has become a lot faster than the first time I did it, but it's still a manual job and it still takes time, and since the process of measuring the coordinates is always the same for me, I want to automate it. I want to be able to hand a bunch of objects (or widgets) to a function or class and have it automatically figure out how and where to lay them out - in a grid or column layout, for example - given certain metadata, e.g. widths, heights, padding, font. I also want the ability later to modify a specific object's metadata if a particular graph or table feels like it would look more appealing with a little extra padding on the left, for example.&lt;/p&gt;

&lt;p&gt;I noticed there is a &lt;a href="http://search.cpan.org/perldoc/PDF::APIx::Layout"&gt;PDF::APIx::Layout&lt;/a&gt; module, however it hasn't been updated since 2005.&lt;/p&gt;

&lt;p&gt;So far I only know what I want it to do, and I have a basic idea of how the backend, PDF::API2 code might look. But I still haven't completely decided how I want the API to look to the developer; procedural, OO, declarative or some fusion of them all? I may even end up trying them all out for myself to see which is easier to develop with.&lt;/p&gt;

&lt;p&gt;I will post more updates in the future, regarding the API, and any code will probably end up on GitHub, but that is basically the idea that has been floating around in my head for a few months.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-7500491220640622014?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/7500491220640622014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/07/pdf-library-for-laying-out-widgets-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/7500491220640622014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/7500491220640622014'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/07/pdf-library-for-laying-out-widgets-or.html' title='PDF Library for Laying out Widgets... or something...'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-5121762945800484126</id><published>2010-06-30T22:35:00.010+10:00</published><updated>2010-07-28T21:22:22.667+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Light Mojolicious::Lite Experience</title><content type='html'>&lt;p&gt;I've been playing with &lt;a href="http://search.cpan.org/perldoc/Mojolicious::Lite"&gt;Mojolicious::Lite&lt;/a&gt; for the past couple of weeks. Why? Well, I had started a small project which records public data from a MMORPG that I frequently play (don't ask which one... it is no longer worth playing or even giving a free mention to) and needed a pretty front-end that myself and some friends could use to view the data.&lt;/p&gt;

&lt;h3&gt;Choices, Choices, Choices&lt;/h3&gt;
&lt;p&gt;The initial code I had written for the project was written in Python, which was two simple scripts; one that ran in a cron job once per day to retrieve the data as XML and one that analysed the data and outputted an ugly, little summary. I had intended to store some of the raw data in a database and wanted a web front-end to display it all and allow my non-technical friends to view and/or export the data as Excel spreadsheets.&lt;/p&gt;

&lt;p&gt;Since this was a hobby project and I like to learn new libraries/frameworks for hobby projects, I had two decisions to make:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which library for database access?&lt;/li&gt;
&lt;li&gt;Which web-framework?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was itching to use &lt;a href="http://search.cpan.org/perldoc/DBIx::Class"&gt;DBIx::Class&lt;/a&gt; for something, especially after using &lt;a href="http://search.cpan.org/perldoc/Class::DBI"&gt;Class::DBI&lt;/a&gt; at work and hearing about the wonderful things DBIx::Class has that Class::DBI doesn't. But that's a Perl library, so I rewrote the Python script that ran in a cron job in Perl, so I could later hook DBIx::Class into it.&lt;/p&gt;

&lt;p&gt;Deciding on the web-framework was next. A couple of years ago at university I had used &lt;a href="http://www.sinatrarb.com"&gt;Sinatra&lt;/a&gt; in a Ruby project and loved it and since then I have had a thing for web micro-frameworks. Python has &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt;, which I always had in the back of my mind, and I like the way it uses decorators for the routing. Perl, luckily, has Mojolicious::Lite. I realise now that &lt;a href="http://perldancer.org"&gt;Dancer&lt;/a&gt; exists, however I found Mojo first (sorry, Dancer devs).&lt;/p&gt;

&lt;h3&gt;What I Like&lt;/h3&gt;
&lt;p&gt;The usual good things about web micro-frameworks: Rapid development.&lt;/p&gt;
&lt;p&gt;The mechanism that Mojolicious::Lite uses for routing is very nice, feels very Perl-ish and allows for very compact code.&lt;/p&gt;

&lt;h3&gt;What I Don't Like&lt;/h3&gt;
&lt;p&gt;Errors in templates can result in cryptic error messages. For example:&lt;/p&gt;
&lt;pre&gt;Scalar found where operator expected at (eval 488) line 25, near "} $_M"
        (Missing operator before  $_M?)&lt;/pre&gt;

And:

&lt;pre&gt;Template error in "rank.html.ep": syntax error at template line 2, near ";
$_M "
syntax error at (eval 488) line 25, near "} $_M "
syntax error at (eval 488) line 29, near "} }"
1: &amp;lt;% my $server_table = { %&amp;gt;
2:      &amp;lt;% my ($ranks, $server, $align) = @_; %&amp;gt;
3:
4:      &amp;lt;div class="rank_list &amp;lt;%= $align %&amp;gt;"&amp;gt;&lt;/pre&gt;

&lt;p&gt;What caused the errors? The following two lines of code were:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% my $server_table = { %&amp;gt;
...
&amp;lt;% } %&amp;gt;&lt;/pre&gt;
&lt;p&gt;When they should have been:&lt;/p&gt;
&lt;pre&gt;&amp;lt;% my $server_table = {%&amp;gt;
...
&amp;lt;%} %&amp;gt;&lt;/pre&gt;
&lt;p&gt;So a couple of spaces in the template produced those error messages. Not terribly obvious, unfortunately.&lt;/p&gt;

&lt;h3&gt;In the end...&lt;/h3&gt;
&lt;p&gt;A cryptic error message from a template error is far out-weighed by the things I like, and HTML::Mason's error messages have caused me much bigger headaches. Most of the time, any personal projects that I have only ever, if at all, need a super basic web interface, and I like to get my web applications up and functional as quickly as possible. Mojolicious::Lite let me do exactly that for this project and I intend on using it again in future projects.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-5121762945800484126?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/5121762945800484126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/06/light-mojoliciouslite-experience.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5121762945800484126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5121762945800484126'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/06/light-mojoliciouslite-experience.html' title='Light Mojolicious::Lite Experience'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-8900446785116198111</id><published>2010-05-31T12:34:00.015+10:00</published><updated>2010-06-16T12:53:43.445+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>PDF::API2 is Underrated</title><content type='html'>&lt;p&gt;I feel like there has not been enough talk about &lt;a href="http://search.cpan.org/perldoc/PDF::API2"&gt;PDF::API2&lt;/a&gt; in the Perl community. Searching for code examples and tutorials does not yield many results, however it does lead to &lt;a href="http://rick.measham.id.au/pdf-api2/"&gt;this tutorial&lt;/a&gt;, which is the only useful one that I have been able to find. It is worth reading. Oh, and it's written by my boss ;) Go and read it if you plan on using PDF::API2 in the future.&lt;/p&gt;

&lt;p&gt;At work, for the past year, we have used PDF::API2 to create this &lt;a href="http://www.mailguard.com.au/uploads/file/Sample%20Risk%20Profile%20-%20WebGuard.pdf"&gt;nice looking report&lt;/a&gt; and many others like it. Since then, I have learnt a number of lessons and picked up a few tips for using this powerful library, so here are some of them. This is by no means a tutorial, or even an introduction to PDF::API2, so if you are looking for something like that, refer to the tutorial I referenced in the previous paragraph. This is more of a coredump of the part of my brain that knows PDF, so to speak.&lt;/p&gt;

&lt;h3&gt;The coordinate system is that of a Cartesian plane&lt;/h3&gt;

&lt;p&gt;Personally, every toolkit I have used in the past (which, admittedly, is not a long list) has placed the origin (0, 0) in the top-left corner. I assume, without actually researching, that this was because it was easier for developers to think about placing the top-left corner of a widget/window around the screen. We (mostly) read articles and books and posters from the top-left to the bottom-right.&lt;/p&gt;

&lt;p&gt;However, coordinates in PDF::API2 work differently; the origin resides at the bottom-left of the document, just like the first quadrant of a &lt;a href="http://en.wikipedia.org/wiki/File:Cartesian_coordinates_2D.svg" title="Don't bother clicking if you already know quadrants"&gt;Cartesian plane&lt;/a&gt;. Once you think of it this way, it becomes a lot easier to visualise what you are doing and the placement of your content.&lt;/p&gt;

&lt;h3&gt;Work from the bottom-left&lt;/h3&gt;

&lt;p&gt;This is linked to the previous point. If you are factoring out specific data or widgets into separate classes or functions, specify the position of the data by the bottom-left coordinate, rather than the top-left. This saves a lot of recalculating when you have to use various text/graphics object functions.&lt;/p&gt;

&lt;p&gt;I prefer to refer to the coordinates as 'bottom' and 'left', which clears up any confusion that using 'x' and 'y' might introduce. I recommend doing the same.&lt;/p&gt;

&lt;p&gt;Occasionally you may need to work from the top of your widget, e.g. for tabular data, in which case you can simply use the bottom + height to get the top-most Y-coordinate.&lt;/p&gt;

&lt;h3&gt;Useful CPAN documentation&lt;/h3&gt;

&lt;p&gt;PDF::API2 documentation is shocking. It's horrible. It's almost non-existant. However, &lt;a href="http://search.cpan.org/perldoc/PDF::API2::Content"&gt;PDF::API2::Content&lt;/a&gt; contains 95% of the functions that you probably want. Specifically, it contains all of the member functions for the text and graphics objects, which are the objects you will use most of the time.&lt;/p&gt;

&lt;h3&gt;Useful function that you might skim past&lt;/h3&gt;

&lt;h4&gt;$text-&gt;advancewidth('foo bar', \%options)&lt;/h4&gt;

&lt;p&gt;Given the state of your text object, i.e. font name and size, this will return the width, in points, required to display the text 'foo bar' on the page. Great for figuring out how much space you need to display content like names of people. If you do not want to use the current state of your text object, the second parameter, with text object settings, can be used instead. I have never needed to use the second parameter so far.&lt;/p&gt;

&lt;p&gt;That's it for now. In the future I would like to write some more about this library - preferably with more structure and a nice example rather than random ramblings - but that will have to wait until I can spare the time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-8900446785116198111?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/8900446785116198111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/05/pdfapi2-is-underrated.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8900446785116198111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8900446785116198111'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/05/pdfapi2-is-underrated.html' title='PDF::API2 is Underrated'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-949269644308086479</id><published>2010-04-30T07:43:00.004+10:00</published><updated>2010-04-30T09:49:24.728+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osx'/><title type='text'>Broken Sound in OS X</title><content type='html'>I use a MacBook with OS X 10.5.8 at work. Every now and then, at work, while streaming radio off the internet through iTunes, running Parallels, an IRC client, a Twitter client, an MSN client, a dozen terminal windows/tabs, Chrome with a dozen tabs, Firefox with a handful of tabs open, 30+ Stickies floating around and having not restarted my laptop for 2 weeks, my sound, all of a sudden, goes distorted and choppy (technical term!), which is very annoying when you are streaming radio to four other developers through a surround sound system.&lt;br /&gt;
&lt;br /&gt;
At first I was just restarting my laptop. But that is a little annoying when you have that many programs, websites/tabs open and have to spend 15 minutes remembering what exactly it was you were doing when the sound decided to go rogue.&lt;br /&gt;
&lt;br /&gt;
I noticed that when this occurs, the coreaudiod process starts to use a lot more CPU than usual, i.e. it becomes one of the top 4 CPU-hungry applications according to &lt;a href="http://en.wikipedia.org/wiki/Top_(Unix)"&gt;top&lt;/a&gt;. After killing the coreaudiod process, a new coreaudiod process was spawned and my sound returned to normal. Success!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-949269644308086479?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/949269644308086479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/04/broken-sound-in-os-x.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/949269644308086479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/949269644308086479'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/04/broken-sound-in-os-x.html' title='Broken Sound in OS X'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-3178328044956444229</id><published>2010-03-23T12:25:00.003+11:00</published><updated>2010-03-23T13:12:37.934+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>New Perl Hate</title><content type='html'>You don't work with a language every day without building up a "things I hate in language X" list. Well, I have a few hates of Perl, but they've all been fairly well covered in other blogs and cover the usual topics (pre-Moose OO, getting bitten by scalar/list context, etc), however yesterday I came across a new one. Here is a one-liner demonstrating the problem:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;$ perl -MData::Dumper -le'@a=qw/a b c/; @foobar = map { $_ } @a[0..7]; print Dumper \@a'
$VAR1 = [
          'a',
          'b',
          'c',
          undef,
          undef,
          undef,
          undef,
          undef
        ];&lt;/pre&gt;
&lt;br /&gt;
Fairly obviously, I have created a list with 3 elements in it, tried to slice it with 8 values and assign that to a &lt;em&gt;different&lt;/em&gt; list, however when printing the contents of the &lt;em&gt;original&lt;/em&gt; list, it has now been padded out to 8 values with undefs. Ok, I thought perhaps doing a slice on a list had that kind of destructive behavior but I had just never noticed it before and had never heard about it previously. So I tried another one-liner to perhaps prove that theory:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;$ perl -MData::Dumper -le'@a=qw/a b c/; @foobar = @a[0..7]; print Dumper \@a'
$VAR1 = [
          'a',
          'b',
          'c'
        ];&lt;/pre&gt;
&lt;br /&gt;
Nope. Bug? Or expected behavior for some reason that I cannot figure out? This was on Perl 5.8.9&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-3178328044956444229?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/3178328044956444229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/03/new-perl-hate.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3178328044956444229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3178328044956444229'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/03/new-perl-hate.html' title='New Perl Hate'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-5587436629922890580</id><published>2010-03-17T06:55:00.013+11:00</published><updated>2010-03-17T14:42:52.879+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reverse engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly'/><title type='text'>Diving into Reverse Engineering</title><content type='html'>Last year I read a blog entry (linked below) about a programmer who edited a component of Skype to fix a bug which was causing problems for many users. The blog entry then showed a very simple example of how to edit programs using OllyDbg without the source code. Even though I always knew the basic idea, I had never seen, or even searched for, any clear examples because I had no immediate need to know the details.&lt;br /&gt;
&lt;br /&gt;
There is a MMORPG that I play on the weekends and recently there was discussion on our guild's forum about client tweaks. In the back of my mind, I knew I could probably apply a little reverse engineering to remove annoying art that clutters up the screen, change font colors to be easier on the eyes, and on top of that, maybe figure out how to fix a few bugs which we have been pushing the developers to fix for months, with no results. The problem was that I had no idea how to reverse engineer a program.&lt;br /&gt;
&lt;br /&gt;
Of course, knowledge of how programs work and assembly language was required. Luckily the former was taught fairly well during my course at university, and although we were taught assembly language for the Motorola 68k processor, it never really clicked for me, or I never had an "ah hah!" moment with it and thus never did anything practical with that knowledge.&lt;br /&gt;
&lt;br /&gt;
But now I did! So for the past ten days I have almost gone blind reading articles about reverse engineering and looking at assembly code.&lt;br /&gt;
&lt;br /&gt;
Despite the moral questions, it has been a very interesting exercise and I'm happy that I've found a practical exercise for reverse engineering and assembly language that interests me. So far I've managed to fix one, semi-annoying bug and modified the layout to remove various things that get in the way of seeing what I'm trying to do/click on..&lt;br /&gt;
&lt;br /&gt;
Below is a link to the initial blog entry that piqued my interest and some of the more useful resources I came across over the past ten days:&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.codexon.com/posts/patching-a-program-without-source-code-how-to-be-like-the-skype-hacker-for-newbies"&gt;Patching a Program Without Source Code: How to be like the Skype Hacker for Newbies&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://www.microsoft.com/msj/0298/hood0298.aspx"&gt;Under the Hood: February 1998&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://www.microsoft.com/msj/0698/hood0698.aspx"&gt;Under the Hood: June 1998&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://pentest.cryptocity.net/files/reversing/X86_Win32_Reverse_Engineering_Cheat_Sheet.pdf"&gt;x86 Win32 Reverse Engineering Cheat Sheet [PDF]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-5587436629922890580?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/5587436629922890580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/03/diving-into-reverse-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5587436629922890580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5587436629922890580'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/03/diving-into-reverse-engineering.html' title='Diving into Reverse Engineering'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1947202911725806510</id><published>2010-02-10T12:40:00.004+11:00</published><updated>2010-02-12T13:04:29.647+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Perl Profilers - Devel::NYTProf</title><content type='html'>Keeping up the spirit of &lt;a href="http://blogs.perl.org/users/leo_lapworth/2010/02/develnytprof---perl-profiling-links-needed.html"&gt;a blog post from Leo Lapworth&lt;/a&gt;, I am advocating the use of &lt;a href="http://search.cpan.org/dist/Devel-NYTProf/"&gt;Devel::NYTProf&lt;/a&gt; and doing my bit to get its name out there. On a number of occasions it has saved me a lot of time searching for bottlenecks in my Perl code and also pointed out parts of code that seemed unsuspicious.&lt;br /&gt;
&lt;br /&gt;
The docs on the CPAN page are very clear in its usage, so I won't bore anyone with the details here.&lt;br /&gt;
&lt;br /&gt;
So as far as &lt;a href="http://search.cpan.org/dist/Devel-NYTProf/"&gt;profiling Perl code&lt;/a&gt; goes, Devel::NYTProf is definitely the winner!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1947202911725806510?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1947202911725806510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/02/perl-profilers-develnytprof.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1947202911725806510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1947202911725806510'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/02/perl-profilers-develnytprof.html' title='Perl Profilers - Devel::NYTProf'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-3885541319688116889</id><published>2010-02-02T20:55:00.004+11:00</published><updated>2010-02-02T21:16:04.849+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>Programming Goals for Common Lisp</title><content type='html'>First post of the year... Somehow I was too busy for the whole of January to post anything. Anyway, moving on...&lt;br /&gt;
&lt;br /&gt;
I've been yearning to use &lt;a href="http://common-lisp.net/project/cl-opengl/"&gt;cl-opengl&lt;/a&gt; and &lt;a href="http://www.xach.com/lisp/vecto/"&gt;Vecto&lt;/a&gt; for SOMETHING but can never seem to come up with any ideas. The only useful thing I have used cl-opengl for is a cellular automata simulator, but it's all very basic and minimal. So instead of trying to come up with a new idea, I'm going to re-use an old idea and extend &lt;a href="http://github.com/ltriant/cl-mines"&gt;cl-mines&lt;/a&gt;; my small, currently CLI-based, Minesweeper game.&lt;br /&gt;
&lt;br /&gt;
I intend to use Vecto to generate each of the images for the mines and uncovered tiles. Not the most intense usage for Vecto, but it's better than nothing for now.&lt;br /&gt;
&lt;br /&gt;
And I, obviously, intend to use cl-opengl for displaying and running the whole game.&lt;br /&gt;
&lt;br /&gt;
Another, secondary, goal is to use more macros, if appropriate. Macros are a feature of Common Lisp I am yet to use in a complex way and is a skill I think I'm missing out on with Lisp.&lt;br /&gt;
&lt;br /&gt;
So that's what I am going to be slowly working on in my spare time between everything else! That should keep me busy for a little while, I hope.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-3885541319688116889?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/3885541319688116889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/02/programming-goals-for-common-lisp.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3885541319688116889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3885541319688116889'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2010/02/programming-goals-for-common-lisp.html' title='Programming Goals for Common Lisp'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-6359271387018546130</id><published>2009-12-10T19:11:00.005+11:00</published><updated>2009-12-10T20:06:37.591+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='esoteric'/><title type='text'>Experimenting with Befunge</title><content type='html'>A few years ago I had a look into my first &lt;a href="http://en.wikipedia.org/wiki/Esoteric_programming_language"&gt;esoteric programming language&lt;/a&gt;, &lt;a href="http://www.muppetlabs.com/~breadbox/bf/"&gt;Brainfuck&lt;/a&gt;. Why? Because an IRC channel I frequented required users to message a bot with Brainfuck code, of, at most, a certain number of bytes depending on how long your nickname was, to output your IRC nickname to get voice status so you could actually chat in the channel! I ended up writing an interpreter for it in Perl in ~130 characters too! Not bad considering I was seventeen years old at the time.&lt;br /&gt;
&lt;br /&gt;
So for the few days this week that I was home sick, I looked into &lt;a href="http://en.wikipedia.org/wiki/Befunge"&gt;Befunge&lt;/a&gt;; an esoteric, stack language. Why? Because I could ;)&lt;br /&gt;
&lt;br /&gt;
Easily the most interesting part of the language, for me at least, is the four operations that change the direction of the program counter, allowing programs to read in all different directions. For example, conventional programming languages start from the top and read left-to-right. In a Befunge program you can change the direction to read operations in the left, right, upward or downward directions. This can be used to create some very interesting programs.&lt;br /&gt;
&lt;br /&gt;
Anyway, here's my first, and, so far, only, Befunge program:&lt;br /&gt;
&lt;pre&gt;v          v                 ,&lt;
                        &gt;:"z"`|
&gt;"!raB ooF"&gt;:#@!_:"a"1-`|     &gt;84*-v
           ^           ,&lt;          &lt;&lt;/pre&gt;
&lt;br /&gt;
It simply capitalises some text. Nothing special.&lt;br /&gt;
&lt;br /&gt;
The things you do when you're sick at home...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-6359271387018546130?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/6359271387018546130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/12/experimenting-with-befunge.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6359271387018546130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6359271387018546130'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/12/experimenting-with-befunge.html' title='Experimenting with Befunge'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1236570314294657256</id><published>2009-12-08T11:53:00.003+11:00</published><updated>2009-12-08T12:02:23.178+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>Profiling Common Lisp Code</title><content type='html'>I just finished reading (and applying to my own projects) an article on profiling and optimising Common Lisp code using SBCL's profiler. The article is &lt;a href="http://t-b-o-g.blogspot.com/2009/12/brians-brain-on-common-lisp-take-3.html"&gt;here&lt;/a&gt;. The whole series that the article belongs to is good reading for any novice-to-intermediate Lisp programmer actually, but this one stands out more for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1236570314294657256?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1236570314294657256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/12/profiling-common-lisp-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1236570314294657256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1236570314294657256'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/12/profiling-common-lisp-code.html' title='Profiling Common Lisp Code'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-8510424189967096403</id><published>2009-11-19T21:00:00.020+11:00</published><updated>2009-11-19T22:42:17.911+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>Manually installing ASDF packages for SBCL</title><content type='html'>When I started getting back into Lisp earlier this year, after a bit of reading I quickly found out that &lt;a href="http://common-lisp.net/project/asdf/"&gt;ASDF&lt;/a&gt; was the more popular method for installing third-party packages. I also quickly found a problem though: simply typing &lt;em&gt;(asdf-install:install 'package-name)&lt;/em&gt; doesn't always work, because some packages, while they have ASDF system files written, are not uploaded to - or are not up to date on - the remote site (&lt;a href="http://cliki.net"&gt;cliki.net&lt;/a&gt;) and thus fail when you try to install it. So when you're out of options and decide to download or checkout the source for the package, how the hell do you install it?&lt;br /&gt;
&lt;br /&gt;
In your home directory you should have a &lt;em&gt;.sbcl&lt;/em&gt; directory. Inside this directory you should have two more directories: &lt;em&gt;site&lt;/em&gt; and &lt;em&gt;systems&lt;/em&gt;. To manually install a package:
&lt;ul&gt;
&lt;li&gt;Unzip/untar/checkout the source code into its own directory inside the &lt;em&gt;site&lt;/em&gt; directory. For example, on my machine cl-ppcre is unpackaged into &lt;em&gt;.sbcl/site/cl-ppcre-2.0.1/&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Create a symlink from the ASDF system file to the &lt;em&gt;systems&lt;/em&gt; directory. For example, &lt;em&gt;.sbcl/site/cl-ppcre-2.0.1/cl-ppcre.asd&lt;/em&gt; is symlinked to &lt;em&gt;.sbcl/systems/cl-ppcre.asd&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
That should be it. Now doing a &lt;em&gt;(require 'cl-ppcre)&lt;/em&gt; in SLIME locates the ASDF system file in &lt;em&gt;.sbcl/systems/&lt;/em&gt; and loads the library as expected.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Note:&lt;/strong&gt; If your SBCL doesn't look in &lt;em&gt;systems&lt;/em&gt; for packages, you can check the &lt;em&gt;asdf:*central-registry*&lt;/em&gt; variable for the correct directory.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Another note:&lt;/strong&gt; If you prefer to install packages for the entire system rather than just your specific user, ASDF system symlinks live in &lt;em&gt;/usr/local/lib/sbcl/site-systems&lt;/em&gt; (assuming you installed SBCL in &lt;em&gt;/usr/local&lt;/em&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Last note, I promise:&lt;/strong&gt; The obvious shortcoming of manually installing libraries is it won't automatically retrieve dependencies for you :(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-8510424189967096403?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/8510424189967096403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/11/manually-installing-asdf-packages-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8510424189967096403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8510424189967096403'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/11/manually-installing-asdf-packages-for.html' title='Manually installing ASDF packages for SBCL'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1763307670238665527</id><published>2009-10-21T12:36:00.002+11:00</published><updated>2009-10-21T12:41:08.933+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Twitter shell tools</title><content type='html'>I've posted my current shell tools for interacting with Twitter &lt;a href="http://github.com/ltriant/twitsh"&gt;here&lt;/a&gt;. Still a work in progress, obviously, but it's progressing none-the-less!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1763307670238665527?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1763307670238665527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/10/twitter-shell-tools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1763307670238665527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1763307670238665527'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/10/twitter-shell-tools.html' title='Twitter shell tools'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-2645229419663545606</id><published>2009-10-15T12:44:00.006+11:00</published><updated>2009-10-15T12:54:29.743+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='other'/><title type='text'>URL Shortening Services</title><content type='html'>I'm currently brainstorming some ideas on determining who is linking to a domain that I own via shortened URLS (e.g. &lt;a href="http://tr.im"&gt;tr.im&lt;/a&gt;, &lt;a href="http://is.gd"&gt;is.gd&lt;/a&gt;, &lt;a href="http://ow.ly"&gt;ow.ly&lt;/a&gt; and similar). Without approaching the owners of the site to purchase that data ;) Basically I'm trying to answer the question "who is linking to my site from Twitter" since Twitter clients all use URL shortening services.&lt;br /&gt;
&lt;br /&gt;
If the URL shortening service sends the shortened URL as a referrer in the HTTP headers, and the web browser should do exactly that, then we can use Twitter's search interface to search on those shortened URLs when they pop up in our access logs. The obvious shortcoming is if nobody clicks on a particular shortened URL, it will never show up in the access logs and therefor we won't know about it.&lt;br /&gt;
&lt;br /&gt;
More brainstorming is needed. And probably some reading.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-2645229419663545606?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/2645229419663545606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/10/url-shortening-services.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2645229419663545606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2645229419663545606'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/10/url-shortening-services.html' title='URL Shortening Services'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-4631514008675143410</id><published>2009-09-03T13:27:00.012+10:00</published><updated>2009-09-09T22:49:08.075+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>SBCL and Command-line Common Lisp Apps</title><content type='html'>Ok, first things first: read &lt;a href="http://xach.livejournal.com/130040.html"&gt;Xach's steps&lt;/a&gt; to creating small Common Lisp projects. Without it, I was unable to find anything as straight-forward as that to explain a process for creating Lisp projects. There is a lot of very useful stuff in there.&lt;br /&gt;
&lt;br /&gt;
Second thing: I am not a Lisp expert so this may not be The One True Way to do things.&lt;br /&gt;
&lt;br /&gt;
Finished reading? Good. Ok. Xach's article is not aimed at creating utilities to be run from the command line, but in full Lisp environments, like SLIME. Xach's guide gives you all the information you need as far as laying out your Lisp code and setting up ASDF system files are concerned. The last bits and pieces you need are concerned with the shell environment. So, you will need:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Your code (obviously)&lt;/li&gt;
&lt;li&gt;An ASDF system file (from Xach's article)&lt;/li&gt;
&lt;li&gt;A Makefile to compile your code to .fasl and a .core (for SBCL)&lt;/li&gt;
&lt;li&gt;A shell script to run your .core file&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
The contents of the Makefile for a project named "my-project":&lt;br /&gt;
&lt;pre&gt;SBCL = /usr/local/bin/sbcl

all:
    $(SBCL) --eval "(require 'asdf)" --eval " \
        (progn \
         (asdf:oos 'asdf:load-op 'my-project) \
         (save-lisp-and-die \"my-project.core\"))"

clean:
    rm -rf *.fasl
    rm -rf *.core&lt;/pre&gt;
&lt;br /&gt;
This will compile all of the packages you defined in your ASDF system file into .fasl bytecode files and then save a .core file. Now all you need is a shell script to run the .core:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;#!/bin/sh

SBCL=/usr/local/bin/sbcl

$SBCL --core my-project.core --noinform \
    --eval "(progn (my-project:main) (quit))"&lt;/pre&gt;
&lt;br /&gt;
And that'll do it! This assumes that your code has an exported defun, 'main', as the entry point for your program. Now run the shell script and your application will run.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Edit:&lt;/b&gt; Xach mentioned in the comments that you can use the &lt;em&gt;:executable&lt;/em&gt; argument to &lt;em&gt;save-lisp-and-die&lt;/em&gt; to create an executable, thus removing the need for the wrapper script above.&lt;br /&gt;
&lt;br /&gt;
This is the build process I use for my little &lt;a href="http://github.com/ltriant/cl-mines/"&gt;cl-mines&lt;/a&gt; game, so you can check out the setup there if there is anything that was unclear.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-4631514008675143410?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/4631514008675143410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/09/sbcl-and-command-line-common-lisp-apps.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4631514008675143410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4631514008675143410'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/09/sbcl-and-command-line-common-lisp-apps.html' title='SBCL and Command-line Common Lisp Apps'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-6519967288121554153</id><published>2009-08-26T22:23:00.002+10:00</published><updated>2009-08-26T22:31:11.731+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><title type='text'>cl-mines - A Minesweeper Clone</title><content type='html'>I uploaded my Minesweeper clone, &lt;a href="http://github.com/ltriant/cl-mines/"&gt;cl-mines&lt;/a&gt; to GitHub a few days ago. It's just a simple, command-line Minesweeper game. It doesn't really have a proper build process yet.&lt;br /&gt;
&lt;br /&gt;
I've only tested it on SBCL, but there isn't any SBCL-specific code that I'm aware of and it is, by far, not the most complicated piece of Lisp code out there, so it should work with other Common Lisp implementations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-6519967288121554153?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/6519967288121554153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/cl-mines-minesweeper-clone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6519967288121554153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6519967288121554153'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/cl-mines-minesweeper-clone.html' title='cl-mines - A Minesweeper Clone'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-817403233166729480</id><published>2009-08-21T12:18:00.003+10:00</published><updated>2009-08-21T12:41:08.327+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='github'/><title type='text'>Releasing Some Code to GitHub</title><content type='html'>I'm going to be releasing a bunch of code to &lt;a href="http://github.com/ltriant"&gt;my GitHub&lt;/a&gt; over the next few weeks, after I clean up some of it and fix a few design issues and small bugs. This should include:
&lt;ul&gt;
&lt;li&gt;Minesweeper clone&lt;/li&gt;
&lt;li&gt;Command-line Twitter tools&lt;/li&gt;
&lt;/ul&gt;
I may also release my Cellular Automata simlator aswell. However, at the moment, it has performance issues due to the Common Lisp LTK libraries. I have also started designing a Tetris clone (to be written in either Python+PyGame or Perl+SDL). Any updates to that will be pushed to GitHub aswell.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-817403233166729480?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/817403233166729480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/releasing-some-code-to-github.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/817403233166729480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/817403233166729480'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/releasing-some-code-to-github.html' title='Releasing Some Code to GitHub'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-4663430857012722850</id><published>2009-08-02T21:41:00.005+10:00</published><updated>2009-08-02T21:48:36.903+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Cute Perl Gem to Get the Minimum/Maximum Value</title><content type='html'>Saw this little nugget on #perl@irc.perl.org the other night. It determines the minimum of two values:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;[$b, $a]-&gt;[$a &lt;= $b]&lt;/pre&gt;
&lt;br /&gt;
It takes advantage of the fact that Perl doesn't have a boolean return type for true or false, so the comparison operators return 1 or 0 for true and false, respectively, which are then used by this code to index the array ref.&lt;br /&gt;
&lt;br /&gt;
To get the maximum of the two values, just flip the operator to &gt;=&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-4663430857012722850?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/4663430857012722850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/cute-perl-gem-to-get-minimummaximum.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4663430857012722850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4663430857012722850'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/08/cute-perl-gem-to-get-minimummaximum.html' title='Cute Perl Gem to Get the Minimum/Maximum Value'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-63369021070672831</id><published>2009-07-16T21:44:00.004+10:00</published><updated>2009-07-16T21:54:13.260+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Net::Twitter::Lite 0.05</title><content type='html'>The latest version of &lt;a href="http://search.cpan.org/perldoc/Net::Twitter::Lite"&gt;Net::Twitter::Lite&lt;/a&gt; has pretty much made &lt;a href="http://lukesthoughtdump.blogspot.com/2009/06/tweeting-from-command-line-with-perl.html"&gt;my tweet script&lt;/a&gt; redundant! Or at least removed the need for half of the code: &lt;a href="http://gist.github.com/143950"&gt;http://gist.github.com/143950&lt;/a&gt; Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-63369021070672831?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/63369021070672831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/nettwitterlite-005.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/63369021070672831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/63369021070672831'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/nettwitterlite-005.html' title='Net::Twitter::Lite 0.05'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1384172425400201599</id><published>2009-07-14T22:16:00.003+10:00</published><updated>2009-07-14T22:39:54.442+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Following a Topic on Twitter with Net::Twitter</title><content type='html'>Last week I was keeping up to date with &lt;a href="http://en.wikipedia.org/wiki/Triple_J_Hottest_100_of_All_Time,_2009"&gt;Triple J's Hottest 100 of All Time for 2009&lt;/a&gt; and the hashtag to follow was #hottest100, so that's what I typed into &lt;a href="http://search.twitter.com/"&gt;search.twitter.com&lt;/a&gt; and kept refreshing every few minutes to see the latest thoughts as the countdown progressed. However, it very quickly became annoying to constantly refresh the search page to view the latest tweets. So I threw together this quick Perl script to display Growl notifications for the latest updates:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;#!/usr/bin/env perl

use warnings;
use strict;

use Config::ApacheFormat;
use Encode qw/encode/;
use HTML::Entities;
use Mac::Growl;
use Net::Twitter;

use constant {
    TWEETRC             =&gt; "$ENV{HOME}/.tweetrc",
    MAX_RESULTS_DISPLAY =&gt; 5,
    POLL_FREQUENCY      =&gt; 30
};

die "usage: tweet-follow &lt;query&gt;\n" unless @ARGV &gt; 0;

Mac::Growl::RegisterNotifications(
    'tweet-follow',
    ['tweet'],
    ['tweet']
);

my $num_results_display = MAX_RESULTS_DISPLAY;
my $poll_frequency      = POLL_FREQUENCY;

if ( -e TWEETRC ) { 
    my $config = new Config::ApacheFormat;
    $config-&gt;read(TWEETRC);
    my $block = $config-&gt;block('follow');
    $num_results_display = $block-&gt;get('max_display_results');
    $poll_frequency      = $block-&gt;get('poll_frequency');
}

my ($query) = @ARGV;
my $twitter = Net::Twitter-&gt;new( traits =&gt; [qw/API::Search/] );

my $since_id = 0;
my $max_id   = 0;
while (1) {
    my $response = $twitter-&gt;search(
        {   q   =&gt; $query,
            rpp =&gt; $num_results_display,
            $since_id ? ( since_id =&gt; $since_id ) : ()
        }   
    );  

    unless ( defined $response ) { 
        printf "error while following: %s\n",
            $twitter-&gt;get_error-&gt;{error};
        exit 1;
    }   

    for my $tweet ( @{ $response-&gt;{results} } ) { 
        next unless $tweet-&gt;{id} &gt; $since_id;

        $max_id = $tweet-&gt;{id} if $tweet-&gt;{id} &gt; $max_id;

        Mac::Growl::PostNotification(
            'tweet-follow',
            'tweet',
            decode_entities( $tweet-&gt;{from_user} ),
            encode( 'UTF-8', decode_entities( $tweet-&gt;{text} ) ) 
        );  
    }   

    $since_id = $max_id;
    sleep $poll_frequency;
}&lt;/pre&gt;
&lt;br /&gt;
Usage is simple:&lt;br /&gt;
&lt;pre&gt;tweet-follow hottest100&lt;/pre&gt;
&lt;br /&gt;
Add something like this to your &lt;em&gt;~/.tweetrc&lt;/em&gt; to tweak some basic settings:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;follow&gt;
    max_display_results 7
    poll_frequency 30
&amp;lt;/follow&gt;&lt;/pre&gt;
&lt;br /&gt;
The options are pretty self-explanatory:
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;max_display_results&lt;/em&gt; controls how many tweets to post Growl notifications for.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;poll_frequency&lt;/em&gt; configures how often, in seconds, to poll for, and display, new tweets.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
If only I could get Unicode characters to display properly in the Growl boxes. At the moment they just display as question marks for me.&lt;br /&gt;
&lt;br /&gt;
I made a design decision to only display the latest N tweets, rather than displaying the next N tweets since the last poll, otherwise if you are displaying 5 tweets every 30 seconds for a topic that receives 50 new tweets every 10 seconds (think #iranelection or celebrity deaths), the script will get far behind very quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1384172425400201599?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1384172425400201599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/following-topic-on-twitter-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1384172425400201599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1384172425400201599'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/following-topic-on-twitter-with.html' title='Following a Topic on Twitter with Net::Twitter'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-2030328867825737155</id><published>2009-07-08T20:08:00.003+10:00</published><updated>2009-07-08T22:53:14.922+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Unicode and Perl</title><content type='html'>Tonight I was having problems with different character sets while hacking together some code to display and colorize Twitter search results on the command line (will post code another time) and ended up finally, after all these years with Perl, reading up about Perl and unicode (see &lt;a href="http://search.cpan.org/perldoc/perlunicode"&gt;perlunicode&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc/perluniintro"&gt;perluniintro&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc/perlunifaq"&gt;perlunifaq&lt;/a&gt; and &lt;a href="http://search.cpan.org/perldoc/perlunitut"&gt;perlunitut&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://search.cpan.org/perldoc/Encode"&gt;Encode&lt;/a&gt; module makes dealing with different character encodings trivial. I wish I had known about it before. I remember using the &lt;a href="http://search.cpan.org/perldoc/bytes"&gt;bytes&lt;/a&gt; pragma a couple of years ago because it was the easiest and quickest solution and I was (am?) lazy, but it is recommended to &lt;a href="http://search.cpan.org/~rgarcia/perl-5.10.0/pod/perlunifaq.pod#What_about_the_use_bytes_pragma?"&gt;not use it&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-2030328867825737155?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/2030328867825737155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/unicode-and-perl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2030328867825737155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/2030328867825737155'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/unicode-and-perl.html' title='Unicode and Perl'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-4030285165657121825</id><published>2009-07-01T19:01:00.005+10:00</published><updated>2009-07-01T20:18:06.489+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler'/><title type='text'>Project Euler problem 28</title><content type='html'>&lt;strong&gt;DISCLAIMER: This post contains a solution to Project Euler problem 28. Go away if you don't want to know. DISCLAIMER 2: I am not the most mathematically minded person, so this may/will seem slow for pro mathematicians.&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://projecteuler.net/index.php?section=problems&amp;id=28"&gt;See here&lt;/a&gt; for the problem description.&lt;br /&gt;
&lt;br /&gt;
So I got around to solving problem 28 last night (14 more until I get to level 2!) and, like most problems, I quickly found out the reason why this problem is on Project Euler: there's a subtle and beautiful pattern hidden in the middle of what seems like a random math problem.&lt;br /&gt;
&lt;br /&gt;
The first pattern is that as the pyramid builds, the top right corners are always perfect squares of 1, 3, 5, 7 etc...&lt;br /&gt;
&lt;pre&gt;
43 44 45 46 47 48 &lt;strong&gt;&lt;em&gt;49&lt;/em&gt;&lt;/strong&gt;
42 21 22 23 24 &lt;strong&gt;&lt;em&gt;25&lt;/em&gt;&lt;/strong&gt; 26
41 20  7  8  &lt;strong&gt;&lt;em&gt;9&lt;/em&gt;&lt;/strong&gt; 10 27
40 19  6  &lt;strong&gt;&lt;em&gt;1&lt;/em&gt;&lt;/strong&gt;  2 11 28
39 18  5  4  3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31
&lt;/pre&gt;
So we start looping from 1 to 1001 by 2s.&lt;br /&gt;
&lt;br /&gt;
The other subtle pattern is that the gap between the corners also increments by 1, 3, 5, 7 etc... with each new layer of the pyramid. Therefor if we are at the top right corner which is &lt;em&gt;n&lt;sup&gt;2&lt;/sup&gt;&lt;/em&gt;, the top left corner is &lt;em&gt;n&lt;sup&gt;2&lt;/sup&gt; - n + 1&lt;/em&gt;, the bottom left corner is &lt;em&gt;n&lt;sup&gt;2&lt;/sup&gt; - 2n + 2&lt;/em&gt;, and the bottom right corner is &lt;em&gt;n&lt;sup&gt;2&lt;/sup&gt; - 3n + 3&lt;/em&gt;, which follows an easy summation pattern which we can represent with a simple Lisp function:&lt;br /&gt;
&lt;pre&gt;
(defun sum-corners (n)
  (loop for x from 0 to 3
     sum (+ (- (* n n)
               (* x n))
            x)))
&lt;/pre&gt;
Note: That can be simplified further into one equation, rather than a loop, if you like.&lt;br /&gt;
&lt;br /&gt;
And a simple loop, described earlier, to tie everything together:&lt;br /&gt;
&lt;pre&gt;
(defun euler-28 ()
  (1+ (loop for n from 3 to 1001 by 2
         sum (sum-corners n))))
&lt;/pre&gt;
Done. A simple problem disguised as something a little more difficult than it really is and has a couple of simple but cool patterns.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-4030285165657121825?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/4030285165657121825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/project-euler-problem-28.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4030285165657121825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/4030285165657121825'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/07/project-euler-problem-28.html' title='Project Euler problem 28'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-5987045811141252970</id><published>2009-06-20T20:12:00.004+10:00</published><updated>2009-06-20T20:26:04.436+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Vim-style Line Numbers in Emacs</title><content type='html'>Being a heavy Vim user throughout my university degree and now throughout work, I get very used to having the line numbers down the side (with "set numbers" in a &lt;em&gt;.vimrc&lt;/em&gt;) as I hack code. To get something like this in Emacs, there is &lt;em&gt;linum-mode&lt;/em&gt;.&lt;br /&gt;
&lt;br /&gt;
You can toggle linum-mode for any Emacs buffer with the command &lt;em&gt;M-x linum-mode&lt;/em&gt;. Or if you want to set it globally for every file you edit, add this to your &lt;em&gt;.emacs&lt;/em&gt; file:&lt;br /&gt;

&lt;pre&gt;(require 'linum)
(global-linum-mode 1)&lt;/pre&gt;

linum-mode should come pre-installed with Emacs 22 and beyond. It is also bundled with Aquamacs 1.7 (and maybe earlier...)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-5987045811141252970?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/5987045811141252970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/vim-style-line-numbers-in-emacs.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5987045811141252970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/5987045811141252970'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/vim-style-line-numbers-in-emacs.html' title='Vim-style Line Numbers in Emacs'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-8962513513760823169</id><published>2009-06-14T19:48:00.004+10:00</published><updated>2009-06-14T19:57:56.725+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Getting a Perl REPL in Emacs</title><content type='html'>Although Perl doesn't really have a REPL, you can use Perl's debug mode to obtain something as close to a REPL as you can get without installing extra software with the command &lt;em&gt;perl -de1&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
So when in Emacs (or XEmacs or Aquamacs or whatever), using the following Emacs commands in sequence will open Perl's debug mode inside a horizontally split window:

&lt;pre&gt;C-x 2
C-x o
M-x shell
perl -de1&lt;/pre&gt;
And away you go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-8962513513760823169?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/8962513513760823169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/getting-perl-repl-in-emacs.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8962513513760823169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8962513513760823169'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/getting-perl-repl-in-emacs.html' title='Getting a Perl REPL in Emacs'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-6789523236309613727</id><published>2009-06-11T07:26:00.005+10:00</published><updated>2009-06-11T07:33:52.872+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>When to use defparameter and defvar</title><content type='html'>Because I always forget:

&lt;pre&gt;&lt; gigamonkey&gt; Say you were running a genetic algorithm and you
              said (defparameter *populations* nil)
&lt; gigamonkey&gt; Then you run it for a few days and *populations*
              is full of thousands of populations you've
              generated. Then you change some code in the file
              and reload it. Ooops. You've just wiped out your
              *populations*.
&lt; gigamonkey&gt; (defvar *populations* nil) saves you from that.
&lt; gigamonkey&gt; Conversely if you have
              (defvar *mutation-rate* .01) and then you decide
              to tweak things and change the .01 to .001 and
              reload the file, you'll be confused when nothing
              changes.
&lt; gigamonkey&gt; In that case you should have used defparamater.
&lt; gigamonkey&gt; spelled right, of course.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-6789523236309613727?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/6789523236309613727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/when-to-use-defparameter-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6789523236309613727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/6789523236309613727'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/when-to-use-defparameter-and.html' title='When to use defparameter and defvar'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-1698341624837283900</id><published>2009-06-06T14:53:00.012+10:00</published><updated>2011-02-03T13:17:41.439+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Tweeting from the Command Line with Perl and Net::Twitter</title><content type='html'>&lt;p&gt;The &lt;a href="http://search.cpan.org/perldoc/Net::Twitter"&gt;Net::Twitter&lt;/a&gt; module implements the entire Twitter API. This gives us the ability to create Perl scripts, small and large, to interact with Twitter.&lt;/p&gt;

&lt;p&gt;Although &lt;a href="http://twitter.com/ltriant"&gt;I use Twitter&lt;/a&gt; a bit, I'm not that heavy a user that I need a massive application to tweet from. Instead I usually just use the web interface. But sometimes even that's too much if the tweet is short. Here's some code to tweet from the command line:&lt;/p&gt;

&lt;pre&gt;#!/usr/bin/env perl

use warnings;
use strict;
use Config::ApacheFormat;
use Net::Twitter;
use Term::ANSIColor;

use constant TWEETRC =&gt; "$ENV{HOME}/.tweetrc";

die "usage: tweet &amp;lt;message&amp;gt;\n" unless @ARGV == 1;

die "tweet: Unable to locate ~/.tweetrc file\n"
    unless -e TWEETRC;

my $tweet = shift;

if ( length $tweet &gt; 140 ) {
    print "error: tweet is longer than 140 characters\n";
    print color 'green';
    print substr( $tweet, 0, 140 );
    print color 'bold red';
    print substr( $tweet, 140 );
    print color 'reset';
    print "\n";
    exit 1;
}

my $config = new Config::ApacheFormat;
$config-&gt;read(TWEETRC);
$config-&gt;autoload_support(1);

my $username = $config-&gt;username;
my $password = $config-&gt;password;

my $twitter = Net::Twitter-&gt;new(
    {   username =&gt; $username,
        password =&gt; $password
    }
);

my $result = $twitter-&gt;update( { status =&gt; $tweet } );

unless ( defined $result ) {
    printf "error updating status: %s\n",
        $twitter-&gt;get_error-&gt;{error};
    exit 1;
}&lt;/pre&gt;
To use it, create a &lt;em&gt;.tweetrc&lt;/em&gt; file in your home directory. Add something like this:

&lt;pre&gt;username foo
password bar&lt;/pre&gt;

&lt;p&gt;Replace 'foo' and 'bar' with your Twitter username and password, respectively. Make sure you set permissions correctly so other users can't read your &lt;em&gt;.tweetrc&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And that's it. I place the script in my &lt;em&gt;~/bin&lt;/em&gt; directory, which is in my $PATH, under the name &lt;em&gt;tweet&lt;/em&gt; with executable privileges and then run it like this:

&lt;pre&gt;tweet "I am a BANANA!"&lt;/pre&gt;
Originally I didn't want to have to have to put quotes around the message, but shell meta-characters (like single quotes as an apostrophe) were getting in the way, so this was the safest alternative short of reading from standard input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; The code in this post has a problem which I have posted about &lt;a href="http://lukesthoughtdump.blogspot.com/2011/02/update-to-old-post.html"&gt;here.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-1698341624837283900?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/1698341624837283900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/tweeting-from-command-line-with-perl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1698341624837283900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/1698341624837283900'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/tweeting-from-command-line-with-perl.html' title='Tweeting from the Command Line with Perl and Net::Twitter'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-8088139784922569400</id><published>2009-06-03T20:29:00.008+10:00</published><updated>2009-06-06T13:25:30.872+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Checking Perl Syntax Within Vim</title><content type='html'>Sick of switching back and forth between your shell and Vim buffer fixing syntax errors and adding forgotten "use" statements? Running &lt;em&gt;perl -c&lt;/em&gt; is a handy command to run on your Perl source files to check for syntax errors. Here's a little key mapping to add to your &lt;em&gt;.vimrc&lt;/em&gt; file:

&lt;pre&gt;map ,pc &amp;lt;Esc&amp;gt;:! perl -c %&amp;lt;CR&amp;gt;&lt;/pre&gt;

Now type &lt;em&gt;,pc&lt;/em&gt; (mnemonic: &lt;strong&gt;p&lt;/strong&gt;erl -&lt;strong&gt;c&lt;/strong&gt;) in command mode to check the syntax of your Perl source file without having to switch windows.

It is a little annoying to have to do it multiple times (if there are many errors) since Vim swaps between the file you're editing and the shell to show the output, but it's definitely a step above manually swapping windows :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-8088139784922569400?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/8088139784922569400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/checking-perl-syntax-within-vim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8088139784922569400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/8088139784922569400'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/checking-perl-syntax-within-vim.html' title='Checking Perl Syntax Within Vim'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7625777308693137417.post-3597334122388557314</id><published>2009-06-03T20:10:00.000+10:00</published><updated>2009-06-03T20:18:38.402+10:00</updated><title type='text'>Yet Another Blog *sigh*</title><content type='html'>Ok. I've had many blogs before. On those blogs I've promised to blog regularly and failed miserably. This time I make no such promise to anyone (not even myself), that way I won't feel bad when I inevitably run out of things to write about.

But what am I going to write about? Well, I named the blog "Luke's Thought Dump" for that exact reason: a place to dump thoughts. Any little tricks I pick up (for Vim, Emacs, Perl, Python, Lisp, Linux, OS X or whatever), that I want to remember for some time in the future, will end up here, and I've already got a handful in mind that I've picked up since starting my new job back in February.

So that's it. I'll make a small post this weekend when I have a bit of time :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7625777308693137417-3597334122388557314?l=lukesthoughtdump.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://lukesthoughtdump.blogspot.com/feeds/3597334122388557314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/yet-another-blog-sigh.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3597334122388557314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7625777308693137417/posts/default/3597334122388557314'/><link rel='alternate' type='text/html' href='http://lukesthoughtdump.blogspot.com/2009/06/yet-another-blog-sigh.html' title='Yet Another Blog *sigh*'/><author><name>Luke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
