Thursday, December 10, 2009

Befunge

A few years ago I had a look into my first esoteric programming language, Brainfuck. 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.

So for the few days this week that I was home sick, I looked into Befunge; an esoteric, stack language. Why? Because I could ;)

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.

Anyway, here's my first, and, so far, only, Befunge program:

v          v                 ,<
                        >:"z"`|
>"!raB ooF">:#@!_:"a"1-`|     >84*-v
           ^           ,<          <
It simply capitalises some text. Nothing special.

The things you do when you're sick at home...

Tuesday, December 8, 2009

Profiling Common Lisp Code

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 here. 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.

Thursday, November 19, 2009

Manually installing ASDF packages for SBCL

When I started getting back into Lisp earlier this year, after a bit of reading I quickly found out that ASDF was the more popular method for installing third-party packages. I also quickly found a problem though: simply typing (asdf-install:install 'package-name) 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 (cliki.net) 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?

In your home directory you should have a .sbcl directory. Inside this directory you should have two more directories: site and systems. To manually install a package:
  • Unzip/untar/checkout the source code into its own directory inside the site directory. For example, on my machine cl-ppcre is unpackaged into .sbcl/site/cl-ppcre-2.0.1/
  • Create a symlink from the ASDF system file to the systems directory. For example, .sbcl/site/cl-ppcre-2.0.1/cl-ppcre.asd is symlinked to .sbcl/systems/cl-ppcre.asd
That should be it. Now doing a (require 'cl-ppcre) in SLIME locates the ASDF system file in .sbcl/systems/ and loads the library as expected.

Note: If your SBCL doesn't look in systems for packages, you can check the asdf:*central-registry* variable for the correct directory.

Another note: If you prefer to install packages for the entire system rather than just your specific user, ASDF system symlinks live in /usr/local/lib/sbcl/site-systems (assuming you installed SBCL in /usr/local).

Last note, I promise: The obvious shortcoming of manually installing libraries is it won't automatically retrieve dependencies for you :(

Wednesday, October 21, 2009

Twitter shell tools

I've posted my current shell tools for interacting with Twitter here. Still a work in progress, obviously, but it's progressing none-the-less!

Thursday, October 15, 2009

URL Shortening Services

I'm currently brainstorming some ideas on determining who is linking to a domain that I own via shortened URLS (e.g. tr.im, is.gd, ow.ly 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.

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.

More brainstorming is needed. And probably some reading.

Thursday, September 3, 2009

SBCL and Command-line Common Lisp Apps

Ok, first things first: read Xach's steps 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.

Second thing: I am not a Lisp expert so this may not be The One True Way to do things.

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:

  • Your code (obviously)
  • An ASDF system file (from Xach's article)
  • A Makefile to compile your code to .fasl and a .core (for SBCL)
  • A shell script to run your .core file

The contents of the Makefile for a project named "my-project":
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

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:

#!/bin/sh

SBCL=/usr/local/bin/sbcl

$SBCL --core my-project.core --noinform \
    --eval "(progn (my-project:main) (quit))"

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.

Edit: Xach mentioned in the comments that you can use the :executable argument to save-lisp-and-die to create an executable, thus removing the need for the wrapper script above.

This is the build process I use for my little cl-mines game, so you can check out the setup there if there is anything that was unclear.

Wednesday, August 26, 2009

cl-mines - A Minesweeper Clone

I uploaded my Minesweeper clone, cl-mines 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.

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.

Friday, August 21, 2009

Releasing Some Code to GitHub

I'm going to be releasing a bunch of code to my GitHub over the next few weeks, after I clean up some of it and fix a few design issues and small bugs. This should include:
  • Minesweeper clone
  • Command-line Twitter tools
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.

Sunday, August 2, 2009

Cute Perl Gem to Get the Minimum/Maximum Value

Saw this little nugget on #perl@irc.perl.org the other night. It determines the minimum of two values:

[$b, $a]->[$a <= $b]

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.

To get the maximum of the two values, just flip the operator to >=

Thursday, July 16, 2009

Net::Twitter::Lite 0.05

The latest version of Net::Twitter::Lite has pretty much made my tweet script redundant! Or at least removed the need for half of the code: http://gist.github.com/143950 Enjoy!

Tuesday, July 14, 2009

Following a Topic on Twitter with Net::Twitter

Last week I was keeping up to date with Triple J's Hottest 100 of All Time for 2009 and the hashtag to follow was #hottest100, so that's what I typed into search.twitter.com 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:

#!/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             => "$ENV{HOME}/.tweetrc",
    MAX_RESULTS_DISPLAY => 5,
    POLL_FREQUENCY      => 30
};

die "usage: tweet-follow \n" unless @ARGV > 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->read(TWEETRC);
    my $block = $config->block('follow');
    $num_results_display = $block->get('max_display_results');
    $poll_frequency      = $block->get('poll_frequency');
}

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

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

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

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

        $max_id = $tweet->{id} if $tweet->{id} > $max_id;

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

    $since_id = $max_id;
    sleep $poll_frequency;
}

Usage is simple:
tweet-follow hottest100

Add something like this to your ~/.tweetrc to tweak some basic settings:

<follow>
    max_display_results 7
    poll_frequency 30
</follow>

The options are pretty self-explanatory:
  • max_display_results controls how many tweets to post Growl notifications for.
  • poll_frequency configures how often, in seconds, to poll for, and display, new tweets.

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.

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.

Wednesday, July 8, 2009

Unicode and Perl

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 perlunicode, perluniintro, perlunifaq and perlunitut).

The Encode module makes dealing with different character encodings trivial. I wish I had known about it before. I remember using the bytes pragma a couple of years ago because it was the easiest and quickest solution and I was (am?) lazy, but it is recommended to not use it.

Wednesday, July 1, 2009

Project Euler problem 28

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.

See here for the problem description.

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.

The first pattern is that as the pyramid builds, the top right corners are always perfect squares of 1, 3, 5, 7 etc...
43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20  7  8  9 10 27
40 19  6  1  2 11 28
39 18  5  4  3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31
So we start looping from 1 to 1001 by 2s.

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 n2, the top left corner is n2 - n + 1, the bottom left corner is n2 - 2n + 2, and the bottom right corner is n2 - 3n + 3, which follows an easy summation pattern which we can represent with a simple Lisp function:
(defun sum-corners (n)
  (loop for x from 0 to 3
     sum (+ (- (* n n)
               (* x n))
            x)))
Note: That can be simplified further into one equation, rather than a loop, if you like.

And a simple loop, described earlier, to tie everything together:
(defun euler-28 ()
  (1+ (loop for n from 3 to 1001 by 2
         sum (sum-corners n))))
Done. A simple problem disguised as something a little more difficult than it really is and has a couple of simple but cool patterns.

Saturday, June 20, 2009

Vim-style Line Numbers in Emacs

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 .vimrc) as I hack code. To get something like this in Emacs, there is linum-mode.

You can toggle linum-mode for any Emacs buffer with the command M-x linum-mode. Or if you want to set it globally for every file you edit, add this to your .emacs file:
(require 'linum)
(global-linum-mode 1)
linum-mode should come pre-installed with Emacs 22 and beyond. It is also bundled with Aquamacs 1.7 (and maybe earlier...)

Sunday, June 14, 2009

Getting a Perl REPL in Emacs

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 perl -de1

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:
C-x 2
C-x o
M-x shell
perl -de1
And away you go.

Thursday, June 11, 2009

When to use defparameter and defvar

Because I always forget:
< gigamonkey> Say you were running a genetic algorithm and you
              said (defparameter *populations* nil)
< gigamonkey> 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*.
< gigamonkey> (defvar *populations* nil) saves you from that.
< gigamonkey> 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.
< gigamonkey> In that case you should have used defparamater.
< gigamonkey> spelled right, of course.

Saturday, June 6, 2009

Tweeting from the Command Line with Perl and Net::Twitter

The Net::Twitter module implements the entire Twitter API. This gives us the ability to create Perl scripts, small and large, to interact with Twitter.

Although I use Twitter 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:

#!/usr/bin/env perl

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

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

die "usage: tweet <message>\n" unless @ARGV == 1;

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

my $tweet = shift;

if ( length $tweet > 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->read(TWEETRC);
$config->autoload_support(1);

my $username = $config->username;
my $password = $config->password;

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

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

unless ( defined $result ) {
    printf "error updating status: %s\n",
        $twitter->get_error->{error};
    exit 1;
}
To use it, create a .tweetrc file in your home directory. Add something like this:
username foo
password bar

Replace 'foo' and 'bar' with your Twitter username and password, respectively. Make sure you set permissions correctly so other users can't read your .tweetrc.

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

tweet "I am a BANANA!"
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.

UPDATE: The code in this post has a problem which I have posted about here.

Wednesday, June 3, 2009

Checking Perl Syntax Within Vim

Sick of switching back and forth between your shell and Vim buffer fixing syntax errors and adding forgotten "use" statements? Running perl -c 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 .vimrc file:
map ,pc <Esc>:! perl -c %<CR>
Now type ,pc (mnemonic: perl -c) 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 :)

Yet Another Blog *sigh*

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 :)