<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Probably Programming</title>
    <link>http://probablyprogramming.com/</link>
    <description>Recent content on Probably Programming</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 28 Sep 2015 00:00:00 +0000</lastBuildDate>
    <atom:link href="http://probablyprogramming.com/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Well, this is embarrassing.</title>
      <link>http://probablyprogramming.com/2015/09/28/well-this-is-embarrassing/</link>
      <pubDate>Mon, 28 Sep 2015 00:00:00 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2015/09/28/well-this-is-embarrassing/</guid>
      <description>&lt;p&gt;Well, it turns out it&amp;rsquo;s been over 4 years since I last wrote a blog post. Whoops. Pretty much the entire time I&amp;rsquo;ve been occasionally telling myself &amp;ldquo;Oh yeah, I should start writing blog posts again.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Well, here we go. Yet another &amp;ldquo;I&amp;rsquo;m still alive&amp;rdquo; post. If you&amp;rsquo;re wondering what I&amp;rsquo;ve been doing, I recommend taking a look at the title of the site. After realizing I didn&amp;rsquo;t have enough savings to try to launch a product I took another job which ended up taking up all of my time and nearly killing myself with stress. After about a year at that job, I quit to join a small startup called Whoosh Traffic. A bit more than a year later, a while after &amp;ldquo;graduating&amp;rdquo; from the first &lt;a href=&#34;http://www.techstars.com/&#34;&gt;Techstars Austin&lt;/a&gt; class, &lt;a href=&#34;http://www.erica.biz/2014/dear-investors/&#34;&gt;Whoosh Traffic failed&lt;/a&gt; and just as I was about to miss a paycheck, &lt;a href=&#34;http://venturebeat.com/2014/05/21/ownlocal-acquires-whoosh-traffic-to-save-the-dying-local-newspaper-business/&#34;&gt;OwnLocal acquired Whoosh&lt;/a&gt; and I was brought on to help integrate the Whoosh software into OwnLocal&amp;rsquo;s stack.&lt;/p&gt;

&lt;p&gt;OwnLocal encourages a healthy work-life balance, and so I&amp;rsquo;ve actually started to have some amount of free time for the first time in years and I&amp;rsquo;ve started to want to actually use that free time for personal projects again instead of just playing video games (hey, it&amp;rsquo;s not called &amp;ldquo;Definitely Programming&amp;rdquo;), including this blog.&lt;/p&gt;

&lt;p&gt;As with most things, the hardest part for me is just getting started, so here I go&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>sated: a Programmer&#39;s Editor for you</title>
      <link>http://probablyprogramming.com/2011/03/20/sated-a-programmers-editor-for-you/</link>
      <pubDate>Sun, 20 Mar 2011 00:00:00 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2011/03/20/sated-a-programmers-editor-for-you/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update (2015-09-28):&lt;/strong&gt; I am no longer working on sated. A short
while after writing this post I ended up taking a job which involved
working on a text editor and so continuing work on sated would have
been a conflict of interests (and potentially caused my work on sated
to be the property of my employer at the time). So I stopped working
on sated, and now here I am, three jobs later, and I&amp;rsquo;ve started using
&lt;a href=&#34;https://atom.io/&#34;&gt;Atom&lt;/a&gt;, and while it&amp;rsquo;s not exactly what I had in
mind for sated, it is close enough that I&amp;rsquo;ve stopped using Emacs and
I don&amp;rsquo;t really have any plans to start up work on sated again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have begun work on &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;sated&lt;/a&gt;, a lightweight, extensible,
cross-platform text editor for programmers.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m taking a &amp;ldquo;lean startup&amp;rdquo; approach to this, and so I&amp;rsquo;m approaching
this as a small commercial venture. Currently, I am at an extremely
early stage of both software and business development. How early?
Well, right now, it&amp;rsquo;s just me, an iteration&amp;rsquo;s worth of tasks in
Pivotal Tracker, and a single &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;landing page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;sated-is-for-you-programmer:d3619159b70a6a963a5f17fbdcb7a4c8&#34;&gt;sated is for &lt;em&gt;you&lt;/em&gt;, programmer&lt;/h2&gt;

&lt;p&gt;sated is going to start as a basic core which only allows for two
things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Editing text files.&lt;/li&gt;
&lt;li&gt;Extending sated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This makes for a very natural Minimum Viable Product. Essentially, I
will have a simple framework for building a text editor, and power
users will have a way to get the editing experience which they want by
writing code to customize their copy of sated.&lt;/p&gt;

&lt;p&gt;Not everyone is a power user, of course, so the next step will be to
create optional modules which can be plugged in to the core editor,
ideally as easily as possible. Which modules get created will depend
on what feedback I get from users.&lt;/p&gt;

&lt;p&gt;One more key component I mentioned above is that sated will be
&amp;ldquo;cross-platform&amp;rdquo;. Many of the popular text editors out there today
only run on a single platform, which means that some users are forced
to switch to a different editor when they go from Windows to OS X to
Linux. By targeting all three platforms, users will be able to use the
same editor anywhere they go, perhaps even carrying a flash drive with
all three builds and their favorite plug-ins, so they can edit in
comfort even on computers which aren&amp;rsquo;t theirs.&lt;/p&gt;

&lt;h2 id=&#34;why-this-is-viable:d3619159b70a6a963a5f17fbdcb7a4c8&#34;&gt;Why this is viable&lt;/h2&gt;

&lt;p&gt;I know that there is a market for commercial programmer&amp;rsquo;s editors,
considering the continued existence of products like TextMate,
UltraEdit, the E Text Editor and others.&lt;/p&gt;

&lt;p&gt;I also know that a large number of users don&amp;rsquo;t pay for their text
editor; editors like Emacs and VIM both have huge followings, as do
several more &amp;ldquo;modern&amp;rdquo; free editors.&lt;/p&gt;

&lt;p&gt;The problem with most commercial editors is that they generally only
run on a single platform, or that they are not as customizable as a
user might like.&lt;/p&gt;

&lt;p&gt;The problem with most free editors is that they are extensions of
decades-old designs (Emacs and vi were both released in 1976), or they
are relatively new but designed with a more fixed set of features in
mind, or at the very least are difficult to extend. Emacs and VIM can
be customized nearly endlessly, but you have to deal with all the
cruft and eccentricities of their respective architectures.&lt;/p&gt;

&lt;p&gt;With sated, I&amp;rsquo;m starting with extensibility in mind, but also
simplicity. Those users who just want to try out an extension
shouldn&amp;rsquo;t have to open up a configuration file and edit it by
hand. However, users who want to will still be able to.&lt;/p&gt;

&lt;p&gt;Programmers tend to be busy people, and plenty of them have
demonstrated that it&amp;rsquo;s worth it to them to pay for someone else to
give them a good editor to work with. I&amp;rsquo;m confident that if I can make
an editor which is better in at least some way, that developers who
have more important things to do with their time will be willing to
pay for it.&lt;/p&gt;

&lt;h2 id=&#34;how-i-m-planning-on-making-money:d3619159b70a6a963a5f17fbdcb7a4c8&#34;&gt;How I&amp;rsquo;m planning on making money&lt;/h2&gt;

&lt;p&gt;There are a few possibilities I&amp;rsquo;m considering for revenue streams. In
true lean fashion I am not going to lock myself into only one way of
doing things.&lt;/p&gt;

&lt;p&gt;The simplest and most straightforward idea is to take the same
approach as other commercial editors: just sell the editor, with all
its bundled features, for a fixed price.&lt;/p&gt;

&lt;p&gt;Another alternative is to take an &amp;ldquo;app store&amp;rdquo; approach: sell the core
editor for a low price (or even give it away for free), but then have
bundles of functionality which are available for purchase, each for a
relatively small price.&lt;/p&gt;

&lt;p&gt;The app store approach also could have the benefit of eventually
allowing third parties to develop their own extensions and sell them
in the app store as well. There could be an interface in the editor to
find and purchase plug-ins for feature you might need.&lt;/p&gt;

&lt;p&gt;To start with, I think I will take the single-price route, just
because it&amp;rsquo;s simpler, both for me to implement and for users to know
what they are paying for. Version 1.0 will most likely be somewhere in
the $50 range, since that seems to be the standard price point in the
text editor market.&lt;/p&gt;

&lt;h2 id=&#34;how-i-got-here:d3619159b70a6a963a5f17fbdcb7a4c8&#34;&gt;How I got here&lt;/h2&gt;

&lt;p&gt;I found out recently that at the end of March, I will find myself
unemployed for the first time in nearly 4 years, but rather than
immediately trying to find a new job, I decided that it was time to
try and start a business of my own. Soon after making that decision, I
was helped along by discovering &lt;a href=&#34;http://www.appsumo.com/lean/&#34;&gt;AppSumo&amp;rsquo;s Lean Startup Bundle for
SXSW&lt;/a&gt;, and that was all the motivation I needed to get
started.&lt;/p&gt;

&lt;p&gt;For the next two months, my wife and I are living off of savings while
I work full time at getting sated off the ground. Two months is a lot
less time than people usually give themselves for this sort of thing,
but I plan on counting the time to my first release in weeks, not
months, and doing so on one hand.&lt;/p&gt;

&lt;p&gt;Not only has this bundle gotten me ~$6000 worth of stuff and services
for $99, it has also saved me the trouble of going out and finding
each of these services on my own. It&amp;rsquo;s fully possible that I may
decide some of them are not for me, but at least I&amp;rsquo;m not wasting time
now trying to decide that.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s what I&amp;rsquo;ve done so far with the bundle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set up my Pivotal Tracker account and filled in my first
iteration&amp;rsquo;s-worth of tasks (the basic editor).&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Set up SnapEngage on my &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;sated landing page&lt;/a&gt;. If you want to
talk to me about sated (in a live chat, or via email), you can go
there and do so right now.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Set up a UserVoice page where people can tell me what features they
want to see in sated. Do you have a feature you can&amp;rsquo;t live without in
a text editor? &lt;a href=&#34;http://sated.uservoice.com/&#34;&gt;Let me know!&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Set up Crazy Egg tracking on my &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;sated landing page&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Redeemed my 25,000-email credit from Postmark, in preparation for
the future need to send emails to customers.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Started through &amp;ldquo;Running Lean&amp;rdquo; and created my first Lean Canvas. I
love the idea of a business plan on a single page.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Grabbed my copies of The Venture Hacks Bible, Andrew Chen&amp;rsquo;s and
Sean Ellis&amp;rsquo;s ebooks, and have read some of each. That&amp;rsquo;s a lot of
stuff to read!&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Signed up for Udemy &amp;ldquo;Startup and Go&amp;rdquo; course and started my way
through. I have concluded that Adeo Ressi likes to curse a lot.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Signed up for my 3 months of Hacker Monthly.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Signed up for my copy of Eric Ries&amp;rsquo; &amp;ldquo;The Lean Startup&amp;rdquo;. I&amp;rsquo;ve been
following Eric&amp;rsquo;s blog for quite some time now, and I&amp;rsquo;m excited to
read the book as well.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Signed up for and gotten my $200 credit on Chargify. I will test
this out once I start taking payments.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Checked out Ask Your Target Market. Thought &amp;ldquo;hmm, this looks
familiar.&amp;rdquo; Remembered that I wrote the JavaScript for several of
their pages (the target demographic and write your survey pages),
while working for a previous company.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Started through the LaunchBit startup guide. They seem to be more
focused on the non-technical side of things, but so far it has helped
with planning from the business side of things.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Checked out Geckoboard, HipChat, Pandaform, Ginzametrics,
Kissmetrics, Slidedeck, Saucelabs, Feefighters, uTest,
Lessaccounting, 99designs, Batchbook, Textingly, Infochimps, WP
Engine, Server Density, Trada, and Zencoder. At the moment I don&amp;rsquo;t
think I really have much use for most of these (except perhaps the
metrics sites), but I did sign up with accounts for any of them that
didn&amp;rsquo;t require a credit card up front (all but one, I don&amp;rsquo;t recall
which), in case a need arises in the future.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;what-s-next:d3619159b70a6a963a5f17fbdcb7a4c8&#34;&gt;What&amp;rsquo;s next&lt;/h2&gt;

&lt;p&gt;Right now, I have a theory: people will be willing to pay for an
editor which will run everywhere and can become the exact editor they
want.&lt;/p&gt;

&lt;p&gt;My next step is to test that theory.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve already built my first MVP, the &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;sated landing page&lt;/a&gt;. It&amp;rsquo;s
not so much an actual product, but a way for me to gauge interest
before I even have a product to show.&lt;/p&gt;

&lt;p&gt;In between my attempts at getting people to tell me if my idea is
worthwhile, I am also going to start building the &lt;em&gt;real&lt;/em&gt; MVP: the
basic editor itself. This is a bit of a break from the usual lean
process, but since it&amp;rsquo;s only me, the only thing it will cost me is my
own time, and at the very worst I&amp;rsquo;ll end up with an editor that works
exactly how I want it to.&lt;/p&gt;

&lt;p&gt;If the feeling I get from the feedback I receive isn&amp;rsquo;t too
discouraging, the next step will be to see if people are willing to
put their money where their mouth is. Version 0.1 won&amp;rsquo;t have much to
it. It will be extremely basic, but it will have to potential to
become exactly the editor a given user wants.&lt;/p&gt;

&lt;p&gt;Even still, I can&amp;rsquo;t in good conscience charge $50 for what is
essentially a slightly-improved notepad, so here&amp;rsquo;s what I&amp;rsquo;m thinking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The price for any given release will be set proportionally to how
many version 1.0 features are included in that release.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Any customer who purchases a pre-1.0 release will receive any
subsequent releases, up to and including version 1.0, for no further
charge, as well as a discount on future major releases.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;With this in mind, version 0.1 will be released extremely soon,
with a price of less than $5. If the price of version 1.0 ends up
being $50, that&amp;rsquo;s a pretty good discount for early adopters&amp;hellip;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any questions, comments, suggestions, checks for large
sums of money, or anything else you wish to send my way, please get a
hold of me via either the &amp;ldquo;help&amp;rdquo; button or the &amp;ldquo;tell me what features&amp;rdquo;
link on the &lt;a href=&#34;http://sated.probablyprogramming.com&#34;&gt;sated landing page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post doubles as my entry into the &lt;a href=&#34;http://appsumo.com/leanchallenge&#34;&gt;AppSumo Lean Startup
Challenge&lt;/a&gt;, and will hopefully lead my winning. Of
course, I&amp;rsquo;d love to get one of the top prizes, as that would allow me
to continue working on sated full time for much longer than my
relatively small amount of savings, but any of the prizes would be
invaluable to helping sated become a success.&lt;/p&gt;

&lt;p&gt;If nothing else, having a link to this blog post on the contest voting
page will gain me some potential customers, and that by itself is
worth something.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Comic-Fu</title>
      <link>http://probablyprogramming.com/2010/02/09/comic-fu/</link>
      <pubDate>Tue, 09 Feb 2010 18:42:21 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2010/02/09/comic-fu/</guid>
      <description>&lt;div&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/2010/02/09/comic-fu&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2010/02/plancomestogether.png&#34; alt=&#34;saveplace&#34; title=&#34;I love it when a plan comes together!&#34; height=&#34;252&#34; width=&#34;425&#34;&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Angie has been slaving away working on &lt;a href=&#34;http://company-y.com&#34;&gt;Company-Y&lt;/a&gt; lately, and I think it&amp;rsquo;s coming along quite nicely.&lt;/p&gt;

&lt;p&gt;Yesterday I decided to give her a break by helping with the coloring of the latest page &lt;a href=&#34;http://company-y.com/2010/02/08/i-love-it-when-a-plan-comes-together/&#34;&gt;&amp;ldquo;I love it when a plan comes together&amp;rdquo;&lt;/a&gt;, and I realized that the coloring process could be greatly sped up if we could simply flood fill the various areas, rather than having to draw around the outline of the area before flood filling it.&lt;/p&gt;

&lt;p&gt;The comic is drawn in The GIMP. The lines are drawn on an transparent layer, and then the coloring is done on another layer below, so as not to mess up the lines. Since there are no boundaries on the lower layer, flood filling doesn&amp;rsquo;t work.&lt;/p&gt;

&lt;p&gt;So I tossed together a quick TinyLisp add-on which takes the current layer, duplicates it, thresholds on alpha level (gets rid of any pixels that aren&amp;rsquo;t within a certain opacity level), and puts the new layer below the current one. After that, flood filling can be done in the lower layer without any issues related to the antialiased/feathered edges of the lines.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a fairly simple script, though it took me a while to get it all working correctly (why the heck do all the GIMP built-ins return lists, making me have to (car &amp;hellip;) everywhere, instead of just the primitives?)&lt;/p&gt;

&lt;p&gt;Anyway, I was inspired, and came up with some ideas for some more time-saving add-ons to write, so I&amp;rsquo;ve started a &lt;a href=&#34;http://github.com/pib/Comic-Fu&#34;&gt;Comic-Fu project at GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to install it, simply download &lt;a href=&#34;http://github.com/pib/Comic-Fu/raw/master/make-fillable.scm&#34;&gt;make-fillable.scm&lt;/a&gt; and put it into your .gimp-2.6/scripts directory. It should then be in the Filters-&amp;gt;Comic-Fu menu the next time you start up the GIMP.&lt;/p&gt;

&lt;p&gt;p.s. I&amp;rsquo;m totally counting this as one of my programs for my 500 Programming Languages thing. I&amp;rsquo;ll do a write-up of TinyScheme at a later point.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>⚃ Rolling Dice with JS and Unicode ⚂</title>
      <link>http://probablyprogramming.com/2010/01/06/rolling-dice-with-js-and-unicode/</link>
      <pubDate>Wed, 06 Jan 2010 22:53:48 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2010/01/06/rolling-dice-with-js-and-unicode/</guid>
      <description>&lt;p&gt;I recently discovered the &lt;a href=&#34;http://blog.spang.cc/posts/configuring_Gnome_screensaver_for_unicode-screensaver/&#34;&gt;unicode xscreensaver hack&lt;/a&gt;, and have had it running on my secondary monitor for the heck of it. I found out that there are dice face symbols, and I was inspired to do something with them.&lt;/p&gt;

&lt;p&gt;So, I made a simple Unicode-dice roller in JavaScript. I know the same thing could be done in JS, but this way you can roll some numbers to paste into Twitter or something, if you feel like it.&lt;/p&gt;

&lt;script type=&#34;text/javascript&#34;&gt;
function roll(n) {
    var dice = [&#39;\u2680&#39;, &#39;\u2681&#39;, &#39;\u2682&#39;, &#39;\u2683&#39;, &#39;\u2684&#39;, &#39;\u2685&#39;];
    var results = &#39;&#39;;
    for (var i=0; i&lt;n; i++) {
        results += dice[Math.floor(Math.random()*6)] + &#39; &#39;;
    }
    return results;
}

function doRoll(countElem, resultElem) {
    document.getElementById(resultElem).innerHTML = 
        roll(parseInt(document.getElementById(countElem).value));
}
&lt;/script&gt;

&lt;p&gt;Enter number of Dice to roll:&lt;br&gt;&lt;input type=&#34;text&#34; id=&#34;dice-roll-number&#34; value=&#34;4&#34; /&gt;
&lt;input type=&#34;button&#34; onclick=&#34;doRoll(&#39;dice-roll-number&#39;, &#39;dice-roll-result&#39;)&#34; value=&#34;Roll!&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Result: &lt;span style=&#34;font-size: 64px; line-height: normal&#34; id=&#34;dice-roll-result&#34;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The code is extremely simple, calling Math.floor on the result of Math.random n times, then using a small table of the codepoints from U+2680 to U+2685 to build a string.&lt;/p&gt;

&lt;p&gt;Here is the code for anyone interested:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
    function roll(n) {
        var dice = [&#39;\u2680&#39;, &#39;\u2681&#39;, &#39;\u2682&#39;, &#39;\u2683&#39;, &#39;\u2684&#39;, &#39;\u2685&#39;];
        var results = &#39;&#39;;
        for (var i=0; i&amp;lt;n; i++) {
            results += dice[Math.floor(Math.random()*6)] + &#39; &#39;;
        }
        return results;
    }
    
    function doRoll(countElem, resultElem) {
        document.getElementById(resultElem).innerHTML = 
            roll(parseInt(document.getElementById(countElem).value));
    }
    &amp;lt;/script&amp;gt;
    
    Enter number of Dice to roll:&amp;lt;br&amp;gt;&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;dice-roll-number&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;button&amp;quot; onclick=&amp;quot;doRoll(&#39;dice-roll-number&#39;, &#39;dice-roll-result&#39;)&amp;quot; value=&amp;quot;Roll!&amp;quot; /&amp;gt;
    
    Result: &amp;lt;span style=&amp;quot;font-size: 64px; line-height: normal&amp;quot; id=&amp;quot;dice-roll-result&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>A save your place bookmarklet</title>
      <link>http://probablyprogramming.com/2009/12/01/save-your-place-bookmarklet/</link>
      <pubDate>Tue, 01 Dec 2009 02:10:38 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/12/01/save-your-place-bookmarklet/</guid>
      <description>&lt;div&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/2009/12/01/save-your-place-bookmarklet/&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/12/saveplace.jpg&#34; alt=&#34;saveplace&#34; title=&#34;saveplace&#34; width=&#34;425&#34; height=&#34;252&#34; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&#34;attribution&#34;&gt;&lt;a title=&#34;Some rights reserved&#34; href=&#34;http://creativecommons.org/licenses/by/2.0/deed.en&#34;&gt;&lt;img alt=&#34;cc icon attribution&#34; src=&#34;http://probablyprogramming.com/wp-content/uploads/2008/02/cc_icon_attribution_small.gif&#34;/&gt;&lt;/a&gt;(&lt;a href=&#34;http://www.flickr.com/photos/chitrasudar/2756691008/&#34;&gt;image source&lt;/a&gt;)&lt;/div&gt;

&lt;p&gt;I read a lot of web comics, and one of the things that happens when reading through the archives of a comic is that I lose my place in the history, so when I come back, I have to spend a lot of time searching to find where I left off.&lt;/p&gt;

&lt;p&gt;I wrote this simple set of bookmarklets to help me in this situation. The &amp;ldquo;save place&amp;rdquo; bookmarklet stuffs the current URL into a cookie (cookies are per site, so there will be one cookie for each site you use this on), and the &amp;ldquo;restore place&amp;rdquo; bookmarklet takes the URL out of the cookie (if it exists) and loads that page. The &amp;ldquo;clear place&amp;rdquo; bookmarklet clears the cookie.&lt;/p&gt;

&lt;p&gt;To use them, just drag the bookmarklets to your bookmark toolbar, or right-click on them and select &amp;ldquo;bookmark this link&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;javascript:(function(){var date = new Date();document.cookie=&#39;ppdc_saved_location=&#39;+escape(document.location)+&#39;; expires=&#39;+date.setTime(date.getTime()+22896000000)+&#39;; path=/&#39;})()&#34;&gt;Save Place&lt;/a&gt; | &lt;a href=&#34;javascript:void(document.location=(function(){var ca=document.cookie.split(&#39;;&#39;);for(var i=0;i&lt;ca.length;i++){var c=ca[i];while(c.charAt(0)==&#39; &#39;)c=c.substring(1,c.length);if(c.indexOf(&#39;ppdc_saved_location=&#39;)==0)return unescape(c.substring(20,c.length));}return document.location;})())&#34;&gt;Restore Place&lt;/a&gt; | &lt;a href=&#34;javascript:void(document.cookie=&#39;ppdc_saved_location=; expires=-1; path=/&#39;)&#34;&gt;Clear Place&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those who are interested, here&amp;rsquo;s the code in function form:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;    function savePlace() {
        var date = new Date();
        document.cookie=&#39;ppdc_saved_location=&#39;+escape(document.location)
            +&#39;; expires=&#39;+date.setTime(date.getTime()+22896000000)+&#39;; path=/&#39;;
    }
    
    function restorePlace() {
        document.location = (function() {
             var ca = document.cookie.split(&#39;;&#39;);
             for(var i=0;i&amp;lt;ca.length;i++) {
                 var c=ca[i];
                 while (c.charAt(0)==&#39; &#39;) c = c.substring(1,c.length);
                 if (c.indexOf(&#39;ppdc_saved_location=&#39;) == 0) 
                     return unescape(c.substring(20,c.length));
             }
             return document.location;
        })();
    }
    
    function clearPlace() {
        document.cookie=&#39;ppdc_saved_location=; expires=-1; path=/&#39;;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I based my code off the &lt;a href=&#34;http://www.quirksmode.org/js/cookies.html&#34;&gt;createCookie and readCookie functions from QuirksMode&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fun with bookmarklets and CSS3 transforms</title>
      <link>http://probablyprogramming.com/2009/11/26/fun-with-bookmarklets-and-css3-transforms/</link>
      <pubDate>Thu, 26 Nov 2009 00:52:04 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/11/26/fun-with-bookmarklets-and-css3-transforms/</guid>
      <description>&lt;p&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/2009/11/26/fun-with-bookmarklets-and-css3-transforms&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/11/transformcrop.png&#34; alt=&#34;Transform!&#34; title=&#34;Transform!&#34; width=&#34;425&#34; height=&#34;252&#34;  /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently read about the &lt;a href=&#34;http://www.w3.org/TR/css3-2d-transforms/#transform-property&#34;&gt;CSS transform property&lt;/a&gt;, and I was inspired to give it a try in a fun and mostly useless way.&lt;/p&gt;

&lt;p&gt;After a bit of fidding, I present to you the &amp;ldquo;Rotate!&amp;rdquo; bookmarklet (click it several times if it doesn&amp;rsquo;t work the first time):&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;javascript:(function() {var ds = document.getElementsByTagName(&#39;div&#39;);var d = ds[Math.round(Math.random()*ds.length)];function transform(r) {d.style.transform=d.style[&#39;WebkitTransform&#39;]=d.style[&#39;MozTransform&#39;]=&#39;rotate(&#39; + r + &#39;deg)&#39;;setTimeout(function() {transform(++r % 360);}, 100);}transform(1);})()&#34;&gt;Rotate!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simply drag the above link to your bookmarks toolbar, and whenever you get bored with a webpage, click that link, and see what happens!&lt;/p&gt;

&lt;p&gt;The code is pretty simple. It just gets a list of all the divs on the page, picks one of them at random, and starts rotating it. Click it multiple times, and it will rotate multiple times.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the code, formatted for your viewing pleasure:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;    (function() {
      var ds = document.getElementsByTagName(&#39;div&#39;);
      var d = ds[Math.round(Math.random()*ds.length)];
      function rotateHeaders(r) {
        d.style[&#39;WebkitTransform&#39;] = d.style[&#39;MozTransform&#39;] = &#39;rotate(&#39; + r + &#39;deg)&#39;;
        setTimeout(function() {rotateHeaders(++r % 360);}, 100);
      }
      rotateHeaders(1);
    })()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortuneately, this only works in Firefox and Webkit-based browsers at the moment..wait, no, that&amp;rsquo;s pretty much ok. You IE folks out there are used to things not working in your browser by now.&lt;/p&gt;

&lt;p&gt;With a couple small changes, you can make it scale instead: &lt;a href=&#34;javascript:(function() {var ds = document.getElementsByTagName(&#39;div&#39;);var d = ds[Math.round(Math.random()*ds.length)];function transform(r) {d.style.transform=d.style[&#39;WebkitTransform&#39;]=d.style[&#39;MozTransform&#39;]=&#39;scale(&#39; + r + &#39;)&#39;;setTimeout(function() {transform(++r % 10);}, 100);}transform(1);})()&#34;&gt;Scale!&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Simple Lisp Parser in Python</title>
      <link>http://probablyprogramming.com/2009/11/23/a-simple-lisp-parser-in-python/</link>
      <pubDate>Mon, 23 Nov 2009 02:59:15 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/11/23/a-simple-lisp-parser-in-python/</guid>
      <description>&lt;p&gt;A managed to sneak in a little time recently and write a simple &lt;a href=&#34;http://en.wikipedia.org/wiki/Sexp&#34;&gt;Lisp s-expression&lt;/a&gt; parser in Python.&lt;/p&gt;

&lt;p&gt;I started out with a version that just understands parentheses, atoms, and strings, but it was just a couple of extra lines to add in support for the quote &amp;ldquo;operator&amp;rdquo;, that I went ahead and threw that in there, too.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ll go ahead and go through it bit-by-bit here, though I think it&amp;rsquo;s pretty straightforward.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    from string import whitespace
    
    atom_end = set(&#39;()&amp;quot;\&#39;&#39;) | set(whitespace)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When any of these things are encountered while reading an atom, the atom should be ended. This means no need for whitespace betwen an atom and opening or closing parentheses or quotes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    def parse(sexp):
        stack, i, length = [[]], 0, len(sexp)
        while i &amp;lt; length:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rather than write this recursively, I am using a list as a stack and a simple while-loop to go through the contents of the string. I start with an empty list on the stack, which will hold the entire parsed sexp when the parsing is done.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    c = sexp[i]
            reading = type(stack[-1])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each character is put into c and the type of the current item being read is checked. Rather than using some variable to keep track of the current state of the parser, I just used a distinct Python type for each of the possible lisp types to be read: a list for a list, a string for a string, and a string inside a tuple for an atom. Using this system, I just have to check what type the top element in the stack is, and I&amp;rsquo;ll know what I&amp;rsquo;m currently reading.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    if reading == list:
                if   c == &#39;(&#39;: stack.append([])
                elif c == &#39;)&#39;: 
                    stack[-2].append(stack.pop())
                    if stack[-1][0] == (&#39;quote&#39;,): stack[-2].append(stack.pop())
                elif c == &#39;&amp;quot;&#39;: stack.append(&#39;&#39;)
                elif c == &amp;quot;&#39;&amp;quot;: stack.append([(&#39;quote&#39;,)])
                elif c in whitespace: pass
                else: stack.append((c,))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When reading a list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If an opening parenthesis is encountered, add a new list to the stack&lt;/li&gt;
&lt;li&gt;If a closing parenthesis is encountered, take the list from the top of the stack and append it to the next list down in the stack. Check if the last thing read was a quote, and if so, add this list as the parameter to the quote call.&lt;/li&gt;
&lt;li&gt;If an opening double-quote is encountered, add an empty string to the stack.&lt;/li&gt;
&lt;li&gt;If a single-quote is found, add a list with a quote symbol at the beginning of it.&lt;/li&gt;
&lt;li&gt;If c is whitespace, ignore it.&lt;/li&gt;
&lt;li&gt;Otherwise, start an atom with whatever other character was found.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    elif reading == str:
                if   c == &#39;&amp;quot;&#39;: 
                    stack[-2].append(stack.pop())
                    if stack[-1][0] == (&#39;quote&#39;,): stack[-2].append(stack.pop())
                elif c == &#39;\\&#39;: 
                    i += 1
                    stack[-1] += sexp[i]
                else: stack[-1] += c
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When reading a string:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a closing double-quote is found, end the string, and check for a previous quote call like above (it doesn&amp;rsquo;t really make sense to quote a string, but this isn&amp;rsquo;t really the place to check for that, is it?)&lt;/li&gt;
&lt;li&gt;If a backslash is found, put whatever the following character is in the string. This is a simplistic way to at least allow double-quotes to be escaped, but I don&amp;rsquo;t have anything allowing for more complex escape-strings in here yet.&lt;/li&gt;
&lt;li&gt;Anything else, add to the string.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    elif reading == tuple:
                if   c in atom_end: 
                    atom = stack.pop()
                    if atom[0][0].isdigit(): stack[-1].append(eval(atom[0]))
                    else: stack[-1].append(atom)
                    if stack[-1][0] == (&#39;quote&#39;,): stack[-2].append(stack.pop())
                    continue
                else: stack[-1] = ((stack[-1][0] + c),)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When reading an atom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the end of the atom has been reached, check if the atom is a number (this code just assumes that if the first character of the atom is numeric, that it&amp;rsquo;s a number). If it is, I cheat and use eval to get its value, if it&amp;rsquo;s not, I leave the atom as a tuple-wrapped string.&lt;/li&gt;
&lt;li&gt;Anything else, add as a character to the atom.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    i += 1
        return stack.pop()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At the end here, I just take whatever&amp;rsquo;s on top of the stack (which should be the only thing on the stack if a proper s-expression was passed in), and return that.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m going to continue working on and improving this parser, for use in another project of mine, so I will be adding more functionality.&lt;/p&gt;

&lt;p&gt;I was thinking of doing a s-expression to Python bytecode compiler, but someone already wrote one, and they even took the name I was going to use: &lt;a href=&#34;http://pypi.python.org/pypi/sexpy&#34;&gt;sexpy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think the first thing I&amp;rsquo;ll be adding is the capability for the parser to yield sub-sexps so the entire thing doesn&amp;rsquo;t need to be parsed in one go before returning anything. Another thing I&amp;rsquo;ll most likely add is some checking for invalid sexps, something I left out for clarity in my initial version.&lt;/p&gt;

&lt;p&gt;For those who are interested, here&amp;rsquo;s the &lt;a href=&#34;http://gist.github.com/240957&#34;&gt;complete version of sexp.py&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>IE7 Requires type=&#34;submit&#34; for &lt;button&gt; elements</title>
      <link>http://probablyprogramming.com/2009/10/30/ie7-requires-typesubmit-for-button-elements/</link>
      <pubDate>Fri, 30 Oct 2009 18:32:31 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/10/30/ie7-requires-typesubmit-for-button-elements/</guid>
      <description>&lt;p&gt;If you don&amp;rsquo;t specify &lt;strong&gt;type=&amp;ldquo;submit&amp;rdquo;&lt;/strong&gt; for a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element, IE7 (and probably IE6,  too) &lt;strong&gt;will do nothing&lt;/strong&gt; when that button is clicked (well, unless you have an onclick handler on that element, of course).&lt;/p&gt;

&lt;p&gt;The &lt;a href=&#34;http://www.w3.org/TR/1999/REC-html401-19991224/&#34;&gt;W3C HTML standard&lt;/a&gt; states that the default for a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element should be &amp;ldquo;submit&amp;rdquo;, but if you want it to work with IE7 or earlier, &lt;strong&gt;you&amp;rsquo;ll have to be explicit&lt;/strong&gt; about it.&lt;/p&gt;

&lt;p&gt;I lost some precious time on this fun bug. I was doing some form validation via the great &lt;a href=&#34;http://bassistance.de/jquery-plugins/jquery-plugin-validation/&#34;&gt;jQuery Validation plugin&lt;/a&gt; and for some reason, the form wasn&amp;rsquo;t validation in any IE earlier than IE 8.&lt;/p&gt;

&lt;p&gt;Of course, since it&amp;rsquo;s such a pain to debug IE, I had a heckuva time figuring out the source of the bug, because I just assumed it was some weird JavaScript quirk, and didn&amp;rsquo;t even consider that it could be something as simple as a &amp;ldquo;missing&amp;rdquo; element attribute.&lt;/p&gt;

&lt;p&gt;Ah well. Hopefully this will help somebody else avoid the same problem.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Walking Journal: 45 miles, starting a Twitter client chain</title>
      <link>http://probablyprogramming.com/2009/09/25/starting-a-twitter-client-chain/</link>
      <pubDate>Fri, 25 Sep 2009 03:37:22 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/09/25/starting-a-twitter-client-chain/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve been neglecting both walking and posting on here, though I&amp;rsquo;ve neglected posting more, obviously.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been very busy with work and side projects and my house trying to fall apart on me, so I&amp;rsquo;ve been out of free time lately.&lt;/p&gt;

&lt;p&gt;Anyway, my total is now up to 45 miles of walking. Not too much more than last time, really. I&amp;rsquo;ve gone on some walks around the neighborhood with Angie, and I&amp;rsquo;m not counting them, mostly because I don&amp;rsquo;t know how long they are, really.&lt;/p&gt;

&lt;p&gt;I decided I wanted to start a &amp;ldquo;chain,&amp;rdquo; where every day I do something to work toward a goal I&amp;rsquo;ve set for myself (yes, I mean other than the walking, though that can be a chain as well).&lt;/p&gt;

&lt;p&gt;Fortunately enough for me, I found &lt;a href=&#34;http://dontbreakthechain.com/&#34;&gt;Don&amp;rsquo;t Break The Chain&lt;/a&gt;, where you can keep track of one or more &amp;ldquo;chains&amp;rdquo; of things you want to do every day.&lt;/p&gt;

&lt;h3 id=&#34;the-twitter-client-chain:4801f1f98cf6f09e50c6cae84d356d78&#34;&gt;The Twitter Client Chain&lt;/h3&gt;

&lt;p&gt;So I&amp;rsquo;m creating a web-based Twitter client, as a project for me to try out all the different techniques and technologies that I want to use, but don&amp;rsquo;t have the chance to work with as much as I&amp;rsquo;d like during my day job. Also, ideally, it will at some point become a supplementary source of income.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s a quite a way off until I have more free time in a month or two, but for now, I will satisfy myself with making some small amount of progress on it each day (hopefully).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m writing this client in Erlang, using the awesome &lt;a href=&#34;http://nitrogenproject.com/&#34;&gt;Nitrogen web framework&lt;/a&gt; with the equally awesome &lt;a href=&#34;http://code.google.com/p/mochiweb/&#34;&gt;MochiWeb web server&lt;/a&gt;. My goals for this project include using &lt;a href=&#34;http://c2.com/cgi/wiki?TestDrivenDevelopment&#34;&gt;test driven development&lt;/a&gt; and &lt;a href=&#34;http://timothyfitz.wordpress.com/2009/02/10/continuous-deployment-at-imvu-doing-the-impossible-fifty-times-a-day/&#34;&gt;continuous deployment&lt;/a&gt; and fully embracing the mantra of &lt;a href=&#34;http://www.google.com/search?q=release%20early%2C%20release%20often&#34;&gt;&amp;ldquo;release early, release often&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The plan is to have something up and running on a server as soon as possible. By something, I mean even less than a full-featured twitter client. But as soon as something is up, I can start getting feedback, and see what I should work on next. If I&amp;rsquo;m creating a product for users, there&amp;rsquo;s no use in developing what I want.&lt;/p&gt;

&lt;p&gt;I need to develop what my users want.&lt;/p&gt;

&lt;p&gt;I started this chain up about a week ago, and broke it after the first day. Now I&amp;rsquo;m trying again.&lt;/p&gt;

&lt;h4 id=&#34;tests-and-pre-commit-hooks:4801f1f98cf6f09e50c6cae84d356d78&#34;&gt;Tests and pre-commit hooks&lt;/h4&gt;

&lt;p&gt;During my previous, one-day chain, I managed to get a test harness (using the &lt;a href=&#34;http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html&#34;&gt;EUnit Erlang unit test framework&lt;/a&gt;) set up which will find any modules ending with _tests, stopping at the first error.&lt;/p&gt;

&lt;p&gt;At the moment, I have a shell script which runs the tests. When it starts to take too long, I will switch over to an Erlang module which loops through, so I don&amp;rsquo;t get the startup times of the Erlang interpreter for each test. Or if anyone knows an easier way (perhaps there&amp;rsquo;s already a module that does that somewhere?).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;    #!/bin/bash
    
    for modfile in `ls ebin/*_tests.beam`
    do
        mod=`basename $modfile .beam`
        echo Running $mod:
        erl -noshell -pa ./ebin -s runtest main ${mod%.*}
        [ $? -eq 0 ] || exit 1
    done
    [ $mod ] || exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The runtest module consists of the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-erlang&#34;&gt;    -module(runtest).
    -export([main/1]).
    
    main(Mod) -&amp;gt;
        case eunit:test(Mod) of
            error -&amp;gt; halt(1);
            _ -&amp;gt; init:stop()
        end.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s all kind of thrown together, but the point is incremental improvement, so I&amp;rsquo;ll get back to it when/if I need to. Like I said, there&amp;rsquo;s probably something else out there that will do a better job at this than I did.&lt;/p&gt;

&lt;p&gt;So, today, my &amp;ldquo;chain link&amp;rdquo; was partially taking that script and setting it up to run from the GIT pre-commit script, and partially writing this blog post.&lt;/p&gt;

&lt;p&gt;Getting it set up to run as a pre-commit script just involved making sure it returns non-zero whenever there is a test error (or if no tests were run, which happens when make hasn&amp;rsquo;t been run yet).&lt;/p&gt;

&lt;p&gt;The pre-commit script itself (placed in .git/hooks/pre-commit and set executable) is pretty simple:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;    #!/bin/sh
    ./tests.sh
    if [ $? != 0 ]
    then
            echo &amp;quot;====================================&amp;quot;
            echo &amp;quot; Commit stopped due to test failure&amp;quot;
            echo &amp;quot;====================================&amp;quot;
            exit 1
    fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;script src=&#34;http://dontbreakthechain.com/share_js/pib/last-four/29377&#34; type=&#34;text/javascript&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
Chain length: 1!&lt;/p&gt;

&lt;h4 id=&#34;what-s-next:4801f1f98cf6f09e50c6cae84d356d78&#34;&gt;What&amp;rsquo;s next?&lt;/h4&gt;

&lt;p&gt;Next up, I&amp;rsquo;m acutally going to start on the meat of the project. Since I haven&amp;rsquo;t fully decided on what GUI library I want to use, nor what GUI testing framework I want to use, I&amp;rsquo;m going to start on the backend with code to manage user login info and queries (timeline searches, DMs, etc.).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve got some great ideas (I think) on ways to enhance the way people have conversations over Twitter (and eventually other mediums), so you can be sure that there will be more posts about this in the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Walking Journal: 9 miles, thunderstorm, etc.</title>
      <link>http://probablyprogramming.com/2009/08/27/walking-journal-9-miles-thunderstorm-etc/</link>
      <pubDate>Thu, 27 Aug 2009 00:08:45 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/08/27/walking-journal-9-miles-thunderstorm-etc/</guid>
      <description>

&lt;p&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://physicsdiet.com/Public.aspx?u=pib&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/weight-2009-08-26-2-300x225.png&#34; alt=&#34;weight-2009-08-26-2&#34; title=&#34;weight-2009-08-26-2&#34; width=&#34;300&#34; height=&#34;225&#34; class=&#34;aligncenter size-medium wp-image-527&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I walked at least 4 miles today. I&amp;rsquo;m not sure if I got too far over that, though, because a thunderstorm came through and killed the power before I could look at the exact amount on the treadmill. The last time I looked it was 4, so I&amp;rsquo;ll count it as that.&lt;/p&gt;

&lt;h3 id=&#34;thunderstorm:421fd3389dc66af6d797f5f203861a72&#34;&gt;Thunderstorm&lt;/h3&gt;

&lt;p&gt;I was excited when I first saw the clouds rolling in, because we haven&amp;rsquo;t gotten a good rain for &lt;em&gt;months&lt;/em&gt; now, and our lawn (as I mentioned in my last entry) is getting pretty brown.&lt;/p&gt;

&lt;p&gt;However, when lightning started striking across the street from me, I started to get a little worried. That, and the fact that my wall-mounted monitor was swaying back and forth. Fun fact: speakers make a nice crackly noise when lighting strikes close by.&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t think I&amp;rsquo;d seen lightning strike before. It was quite a sight to see. A bright flash, then a sort of green glow and a halo of sparks that drifted slowly away from the strike point. And it happened in the same place, three times in a row, a few minutes in between. &amp;ldquo;Never strikes the same place twice&amp;rdquo; my ass!&lt;/p&gt;

&lt;p&gt;After the storm had passed, we went outside to see how bad the damage was. Our South and street facing section of fence had been blown over into our yard, all of the fence posts simply snapped off. It takes a pretty strong wind to break a healthy 4x4, I think. We also lost the corrugated plastic roofing over half our back patio, and worst of all, the planter box with my ginger plants in it got blown over! Three out of four of the plants seem to be okay, but one of them got snapped off at the base of the stalk. We also found some roofing shingles in the back yard, so we&amp;rsquo;ll probably need to take a look at the roof when it&amp;rsquo;s light outside.&lt;/p&gt;

&lt;p&gt;We were lucky compared to some neighbors. One guy down the street got a huge tree (somewhere around 3 feet in diameter) through the roof of his station wagon, and partway through his PT Cruiser (it hit the station wagon first, so that took the brunt of the damage). He seemed in relatively good spirits despite the damage, telling us that he was going to  convert the station wagon into some sort of el Camino-type thing by cutting the damaged back half of the roof off. Perhaps all the beer he and his friend were drinking was helping him to stay in a good mood about it.&lt;/p&gt;

&lt;h3 id=&#34;500-languages-slowdown:421fd3389dc66af6d797f5f203861a72&#34;&gt;500 languages slowdown&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve been very busy with work and personal projects recently, and so I haven&amp;rsquo;t had much time for the 500 programming language project. I started learning about &lt;a href=&#34;http://programming.nu/&#34;&gt;Nu, a lispy, interpreted, object-oriented language built in objective-c&lt;/a&gt;. I got the interpreter compiled and working on my 64-bit Ubuntu machine, which took more work than I would have liked due to the fact that most of the development of Nu takes place on Macs. Anyway, there&amp;rsquo;s a &lt;a href=&#34;http://github.com/timburks/nunja/tree/master&#34;&gt;webserver for Nu, called Nunja&lt;/a&gt; and a &lt;a href=&#34;http://github.com/timburks/numarkdown/tree/master&#34;&gt;Nu markdown processor&lt;/a&gt;, so I was thinking I&amp;rsquo;d write a simple blog engine as my Nu program. Nu is looking like a really interesting programming language so far, so it might be one I come back and spend some more time on.&lt;/p&gt;

&lt;p&gt;But as I was saying, I haven&amp;rsquo;t had as much free time lately, so the posts have slowed down. Don&amp;rsquo;t let that fool you, though. I haven&amp;rsquo;t given up on the challenge, I&amp;rsquo;ve just accepted that it might be a while before I can be pumping out 5 languages a week. And it might, in fact, take me more than the 2 years I was originally thinking (dreaming) that it would take.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Walking Journal: 5 Miles</title>
      <link>http://probablyprogramming.com/2009/08/26/walking-journal-5-miles/</link>
      <pubDate>Wed, 26 Aug 2009 01:48:21 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/08/26/walking-journal-5-miles/</guid>
      <description>

&lt;p&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/weight-2009-08-26.png&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/weight-2009-08-26-300x225.png&#34; alt=&#34;weight-2009-08-26&#34; title=&#34;weight-2009-08-26&#34; width=&#34;300&#34; height=&#34;225&#34; class=&#34;aligncenter size-medium wp-image-519&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m starting a walking journal, to keep track of how far I walk each
day, and to give me something to post about more frequently. Despite
the fact that most of my posts on here are Probably about Programming,
this is still, in fact, a personal blog, so I think posting personal
things on here pretty much makes sense to me.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ll also use the walking journal as an actual journal, to talk about things other than walking. I can justify this by noting that I will, most likely be writing a lot of the journal while walking, so the name still works. I wrote most of this one while walking, so it works!&lt;/p&gt;

&lt;h3 id=&#34;walking-journal:8cbe3799023602d9e07d57d07aa8d49f&#34;&gt;Walking journal&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve walked 5 miles since deciding to start this morning, so that&amp;rsquo;s a good start, I suppose.&lt;/p&gt;

&lt;p&gt;Perhaps I&amp;rsquo;ll do a &lt;a href=&#34;http://100milestoachumby.blogspot.com/&#34;&gt;&lt;del&gt;100&lt;/del&gt;200 miles to a chumby&lt;/a&gt;-style thing with this. Though
I have an advantage with &lt;a href=&#34;http://www.flickr.com/photos/pib/2893071653/&#34;&gt;my walking desk&lt;/a&gt;, because I can walk and be
working at the same time. If I walked during my entire workday, I&amp;rsquo;d be
able to get 16 or so miles a day without a problem, and I&amp;rsquo;d have 100
miles in no time :), so maybe I&amp;rsquo;ll make my goal about losing weight
instead of a specific distance. 20 pounds to a &lt;a href=&#34;http://openpandora.org&#34;&gt;Pandora&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve redoubled my efforts at weight loss, and I&amp;rsquo;ve started both walking daily and tracking my weight again.&lt;/p&gt;

&lt;p&gt;You can join in on the fun and track my progress on &lt;a href=&#34;http://physicsdiet.com/Public.aspx?u=pib&#34;&gt;my Physics Diet profile&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like I&amp;rsquo;ve been slowly on an upward gain, but it&amp;rsquo;s just because I weighed myself before dinner, rather than before breakfast as I always did before, and it filled in the blanks since February, since I haven&amp;rsquo;t weighed myself since then. I&amp;rsquo;ve actually been holding pretty steady in weight, I think, so it&amp;rsquo;ll be good to break through this plateau and get my weight lower.&lt;/p&gt;

&lt;h3 id=&#34;school-s-started-again-in-round-rock:8cbe3799023602d9e07d57d07aa8d49f&#34;&gt;School&amp;rsquo;s started again in Round Rock&lt;/h3&gt;

&lt;p&gt;School is back in session. I guess no more sleeping in since the
children gather outside our bedroom window in the morning to wait for
the bus.&lt;/p&gt;

&lt;p&gt;On the plus side, I can once again go out on my front lawn in a bathrobe and yell at those &amp;ldquo;damn kids&amp;rdquo; to &amp;ldquo;get off my lawn!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;I could have done that during the summer, but I would have looked a little silly when all that was out there was dead grass.&lt;/p&gt;

&lt;h3 id=&#34;teeth-are-expensive:8cbe3799023602d9e07d57d07aa8d49f&#34;&gt;Teeth are expensive&lt;/h3&gt;

&lt;p&gt;I had a 9am (super early for me) dentist appointment today to get an
impression for a crown taken. Good god these teeth are costing me a
lot of money.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve used up all my COBRA dental insurance from my last
job, and from what I hear it&amp;rsquo;s nearly impossible to get private dental
insurance, so it&amp;rsquo;s going to all be out-of-pocket from now on.&lt;/p&gt;

&lt;p&gt;Since
with my current job I&amp;rsquo;m technically a &amp;ldquo;private contractor,&amp;rdquo; because
they have no offices in the US, they are just paying me what would
cover insurance (though it might not cover personal insurance after my
COBRA is over).&lt;/p&gt;

&lt;p&gt;Perhaps the way to go is really personal insurance in
the sense that I will put away that same money every month in case of
medical emergency.&lt;/p&gt;

&lt;p&gt;Or I could just have all my teeth removed and switch to an all-liquid diet. I&amp;rsquo;m sure Angie would love having a toothless 25-year-old husband. For sure.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Live List of the Most Popular Twitter Clients</title>
      <link>http://probablyprogramming.com/2009/08/21/live-list-of-the-most-popular-twitter-clients/</link>
      <pubDate>Fri, 21 Aug 2009 09:36:06 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/08/21/live-list-of-the-most-popular-twitter-clients/</guid>
      <description>&lt;p&gt;I just put up a &lt;a href=&#34;http://probablyprogramming.com/twitter_clients.html&#34;&gt;live list of the most popular Twitter clients&lt;/a&gt;. The contents of that page are updated every 60 seconds (the length of time twitter caches their public timeline).&lt;/p&gt;

&lt;p&gt;For some reason I woke up at 7 this morning, unable to get back to sleep, and I was randomly wondering how many Twitter clients were out there, and which were the most popular. So I decided to find out.&lt;/p&gt;

&lt;p&gt;After a bit of hacking around, I came up with the following Python script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    from urllib import urlopen
    from contextlib import closing
    import pickle
    import json
    
    try:
        clientlist = pickle.load(open(&#39;clientlist.pickle&#39;))
    except:
        clientlist = {}
    
    with closing(urlopen(&#39;http://twitter.com/statuses/public_timeline.json&#39;)) as f:
        json_str = f.read()
    
    tweets = json.loads(json_str)
    
    for tweet in tweets:
        source = tweet[&#39;source&#39;]
        clientlist[source] = clientlist.get(source, 0) + 1
    
    with open(&#39;clientlist.pickle&#39;, &#39;w&#39;) as f:
        pickle.dump(clientlist, f)
    
    total = 0
    for count in clientlist.itervalues():
        total += count
    
    with open(&#39;clientlist.html&#39;, &#39;w&#39;) as f:
        f.write(&#39;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Twitter Client list&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&#39;)
        f.write(&#39;&#39;.join([&#39;&amp;lt;h1&amp;gt;Twitter Client Popularity&amp;lt;/h1&amp;gt;&#39;,
                         &#39;&amp;lt;div style=&amp;quot;float: left; margin-right: 20px;&amp;quot;&amp;gt;Out of &amp;lt;em&amp;gt;&#39;, str(total), 
                         &#39;&amp;lt;/em&amp;gt; Twitter messages, the following were the clients used.&#39;]))
        f.write(&#39;&amp;lt;table&amp;gt;&amp;lt;thead&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Client&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Tweet Count&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;% of total&amp;lt;/th&amp;gt;&amp;lt;/thead&amp;gt;&amp;lt;tbody&amp;gt;&#39;)
    
        for (link, count) in sorted(clientlist.iteritems(), key=lambda item: item[1], reverse=True):
            f.write(&#39;&#39;.join([&#39;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&#39;, link, &#39;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&#39;, str(count), &#39;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&#39;, 
                             str(round(100.0 * count / total, 2)), &#39;&amp;lt;/td&amp;gt;&#39;]))
        
        f.write(&#39;&amp;lt;/tbody&amp;gt;&amp;lt;/table&amp;gt;&amp;lt;/div&amp;gt;&#39;)
    
        f.write(&#39;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&#39;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The script writes out a pickle file with the list of counts for each client, so multiple runs will generate a cumulative result (don&amp;rsquo;t run it more than once every 60 seconds, or you will add the same results in more than once).&lt;/p&gt;

&lt;p&gt;It then writes out an .html file with a nice sorted list of the most common Twitter clients (well, all the twitter clients it&amp;rsquo;s seen, sorted by most common first).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve set up a cron job on this server to update the file linked to above every minute, so as time goes on the list will become a more and more accurate representation of what people are using to tweet.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A brainfuck synthesizer</title>
      <link>http://probablyprogramming.com/2009/08/06/a-brainfuck-synthesizer/</link>
      <pubDate>Thu, 06 Aug 2009 03:47:26 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/08/06/a-brainfuck-synthesizer/</guid>
      <description>

&lt;p&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/2009/08/06/a-brainfuck-synthesizer/&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/waves.png&#34; alt=&#34;waves&#34; title=&#34;waves&#34; width=&#34;425&#34; height=&#34;282&#34; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my latest in my series of &lt;a href=&#34;http://probablyprogramming.com/2009/07/06/500-programming-languages/&#34;&gt;500 Programming Languages&lt;/a&gt;, I decided to write a (simple) synthesizer in brainfuck.&lt;/p&gt;

&lt;h3 id=&#34;introduction-to-brainfuck:effc81745af8ee345c04d11094bf5685&#34;&gt;Introduction to brainfuck&lt;/h3&gt;

&lt;p&gt;brainfuck is an esoteric programming language based on the idea of
making a language with the smallest possible compiler. Indeed, &lt;a href=&#34;http://probablyprogramming.com/2009/08/01/500-programming-languages-python/&#34;&gt;my
Python brainfuck
compiler&lt;/a&gt;
is only 30 lines of Python code, and I&amp;rsquo;m sure there are some
optimizations I could have done to make it shorter if that was my goal
with the whole thing.&lt;/p&gt;

&lt;p&gt;The only data structure you get is a single array (if it were infinite
you&amp;rsquo;d have a good representation of a Turing machine), and all you can
do is move around this array with a pointer, increment and decrement
values, input and output values, and loop.&lt;/p&gt;

&lt;p&gt;The entire language consists of 8 commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt; move the pointer forward one cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt; move the pointer back one cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;+&lt;/strong&gt; increment the current cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;-&lt;/strong&gt; decrement the current cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.&lt;/strong&gt; output the byte in the current cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;,&lt;/strong&gt; input a byte into the current cell&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[&lt;/strong&gt; move to the matching &lt;strong&gt;]&lt;/strong&gt; if the current cell is zero&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;]&lt;/strong&gt; loop back to the matching &lt;strong&gt;[&lt;/strong&gt; if the current cell is non-zero&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anything other characters in a program are ignored, and thus comments
can be inserted anywhere into the program. Just be careful not to type
proper English sentences with commas and periods, or you might get
some funny bugs until you realize what&amp;rsquo;s happening.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s really all there is to the language. There are a couple of
areas of behavior that aren&amp;rsquo;t standardized between interpreters,
relating to the size of the array, the cell size, and handling
end-of-file when inputing. Those are covered in more detail on the
&lt;a href=&#34;http://en.wikipedia.org/wiki/Brainfuck&#34;&gt;brainfuck Wikipedia&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;So, since this is such a simple language (to comprehend, not to write
in), and I already provided a working compiler in my previous post,
I&amp;rsquo;m going to do this post a little differently, and just cover the
process I went through in writing my first non-trivial brainfuck
program.&lt;/p&gt;

&lt;h3 id=&#34;the-idea:effc81745af8ee345c04d11094bf5685&#34;&gt;The idea&lt;/h3&gt;

&lt;p&gt;I tried to come up with an idea for a program you don&amp;rsquo;t normally see
implemented in brainfuck, and I&amp;rsquo;ve never seen anything done with
brainfuck and audio, so I decided to write a simple (non-interactive)
synthesizer.&lt;/p&gt;

&lt;h3 id=&#34;my-first-brainfuck-program:effc81745af8ee345c04d11094bf5685&#34;&gt;My first brainfuck program&lt;/h3&gt;

&lt;p&gt;To start out with, I wrote a program to just generate one second of
simple square wave, at 4kHz (the max for 8kHz sample-rate audio).&lt;/p&gt;

&lt;p&gt;With 8000Hz audio, there are 8000 bytes per second, so if the
wavelength is two bytes (one byte high, one byte low, makes a complete
single wave), that makes the frequency &lt;sup&gt;8000&lt;/sup&gt;&amp;frasl;&lt;sub&gt;2&lt;/sub&gt;, or 4000kHz. If I
doubled the wavelength, I&amp;rsquo;d get half the frequency, or 2000Hz.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bf&#34;&gt;    set counter to four thousand
    &amp;gt; ++++ four
    [ &amp;gt; +++++ +++++ times ten
      [ &amp;gt; +++++ +++++ times ten
        [ &amp;gt; +++++ +++++ times ten
          [ &amp;lt;&amp;lt;&amp;lt;&amp;lt; + &amp;gt;&amp;gt;&amp;gt;&amp;gt; - ]
          &amp;lt; -
        ]
        &amp;lt; -
      ]
      &amp;lt; -
    ]
    
    keep a zero value and generate a 255 value
    &amp;gt;&amp;gt; +++++ five
    [ &amp;gt; +++++ times 5
      [ &amp;gt; +++++ +++++ times ten
        [ &amp;lt;&amp;lt;&amp;lt; + &amp;gt;&amp;gt;&amp;gt; - ]
        &amp;lt; -
      ]
      &amp;lt; -
    ]
    &amp;lt; +++++ plus five (255 total)
    
    &amp;lt;&amp;lt;
    [
      &amp;gt;&amp;gt; . output 255
      &amp;lt; .  output 0
      &amp;lt;
      - decrement counter
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This demonstrates how even generating a large number in brainfuck is
quite a chore. I had to use four nested loops and four different cells
to calculate 4*10*10*10. Still, it&amp;rsquo;s better than having 4000 plusses
at the beginning of my program.&lt;/p&gt;

&lt;p&gt;The way loops are done in brainfuck reminds me of doing loops in
assembly language. In fact, brainfuck in general reminds me of
assembly language, but without all those convenient opcodes you&amp;rsquo;re
used to. :)&lt;/p&gt;

&lt;h3 id=&#34;what-s-your-frequency-brainfuck:effc81745af8ee345c04d11094bf5685&#34;&gt;What&amp;rsquo;s your frequency, brainfuck?&lt;/h3&gt;

&lt;p&gt;Next, I wanted to generate a lower frequency, working my way toward
taking user input to determine frequency.&lt;/p&gt;

&lt;p&gt;I picked the A below middle C, which has a nice, even frequency of
220Hz. When you divide 8000 by 220, you come up with a wavelength of
approximately 36. Half low and half high makes that 18 bytes per half,
so I needed to update the previous program to output 18 bytes of each
value instead of just one byte per value.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bf&#34;&gt;    222 waves of 36 bytes each equals 8000 samples for 1 second of audio
    &amp;gt; +++++ +++++ +++++ +++++ ++  22
    [ &amp;gt; +++++ +++++ times ten
      [ &amp;lt;&amp;lt; + &amp;gt;&amp;gt; - ]
      &amp;lt; -
    ]
    ++ plus 2 more
    
    &amp;gt;&amp;gt; +++++ five
    [ &amp;gt; +++++ times 5
      [ &amp;gt; +++++ +++++ times ten
        [ &amp;lt;&amp;lt;&amp;lt; + &amp;gt;&amp;gt;&amp;gt; - ]
        &amp;lt; -
      ]
      &amp;lt; -
    ]
    &amp;lt; +++++ plus five (255 total)
    
    &amp;lt;&amp;lt;
    [
      &amp;gt;&amp;gt;&amp;gt;
      +++++ +++++ +++++ +++ eighteen up and down = 220Hz
      [
        &amp;lt; . output 255 byte
        &amp;gt; - subtract from counter
      ]
      +++++ +++++ +++++ +++ eighteen up and down = 220Hz
      [
        &amp;lt;&amp;lt; . output 0 byte
        &amp;gt;&amp;gt; - subtract from counter
      ]
      &amp;lt;&amp;lt;&amp;lt;
      -
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This version adds two extra loops and an extra cell to generate
eighteen 255s and eighteen zeroes for each iteration of the loop.&lt;/p&gt;

&lt;h3 id=&#34;like-midi-but-crappier:effc81745af8ee345c04d11094bf5685&#34;&gt;Like MIDI, but crappier&lt;/h3&gt;

&lt;p&gt;So, the next and final step was to allow input of notes to play, and
the lengths to play each of those notes.&lt;/p&gt;

&lt;p&gt;I found a helpful reference on the &lt;a href=&#34;http://www.phy.mtu.edu/~suits/notefreqs.html&#34;&gt;frequencies of musical
notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Due to the fact that brainfuck only allows you to read a single byte
at a time, and because it made the program simpler over all, I decided
to have the two values input for each note represent the length, in
waves, and the length of each half-wave. This allowed me to use the
basic structure of the previous program, and to support a wider range
of frequencies without having to handle multiple-byte input for notes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bf&#34;&gt;    generate the 255 byte for output
    &amp;gt;&amp;gt;&amp;gt; +++++ five
    [ &amp;gt; +++++ times 5
      [ &amp;gt; +++++ +++++ times ten
        [ &amp;lt;&amp;lt;&amp;lt; + &amp;gt;&amp;gt;&amp;gt; - ]
        &amp;lt; -
      ]
      &amp;lt; -
    ]
    &amp;lt; +++++ plus five (255 total)
    &amp;lt;&amp;lt;
    
    , read in the length of the first note (in waves)
    &amp;gt; , read in the length of each half wave
    [
      &amp;lt;
      [
        &amp;gt;
        [-&amp;gt;&amp;gt;+&amp;gt;+&amp;gt;+&amp;lt;&amp;lt;&amp;lt;&amp;lt;] copy the value to two cells for use in the following loops plus an extra copy
        &amp;gt;&amp;gt;&amp;gt;&amp;gt;[-&amp;lt;&amp;lt;&amp;lt;&amp;lt;+&amp;gt;&amp;gt;&amp;gt;&amp;gt;] copy the value back to the original location
        &amp;lt;&amp;lt;
        [
          &amp;lt; . output 255 byte
          &amp;gt; - subtract from counter
        ]
        &amp;gt; goto next counter
        [
          &amp;lt; . output 0 byte (zeroed by the last loop)
          &amp;gt; - subtract from counter
        ]
        &amp;lt;&amp;lt;&amp;lt;&amp;lt;
        -
      ]
      , read in the length of the next note (in waves)
      &amp;gt; , read in the length of each half wave
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since the half-wave length is input from the user, I can&amp;rsquo;t simply
re-generate the value each time through the main loop, so I had to
make extra copies of the value, and then re-copy the value back to its
original input location, since it&amp;rsquo;s zeroed out when it&amp;rsquo;s copied to the
other location.&lt;/p&gt;

&lt;p&gt;Like I said, it&amp;rsquo;s harder than assembly language.&lt;/p&gt;

&lt;p&gt;Now all you have to do is fire up your favorite hex editor and create a binary file with a list of lengths and notes (for example &lt;a href=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/mary.notes&#34;&gt;mary.notes&lt;/a&gt;), and save the output from the program into a file (for example, &lt;a href=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/mary.raw&#34;&gt;mary.raw&lt;/a&gt;), and you will have your very own brainfuck-generated music!&lt;/p&gt;

&lt;p&gt;In an 8-bit unsigned 8kHz mono raw PCM file. Linux users can use aplay to play this file. It just so happens the default format is the same as the output of this file. This also means you can pipe the output of this program directly into aplay, as well.&lt;/p&gt;

&lt;p&gt;All you need now is some sort of front-end which will interactively
take keyboard input and translate it into notes, and you could use
this for live performances. (note: you probably don&amp;rsquo;t want to use this
for live performances)&lt;/p&gt;

&lt;h3 id=&#34;learning-more-about-brainfuck:effc81745af8ee345c04d11094bf5685&#34;&gt;Learning more about brainfuck&lt;/h3&gt;

&lt;p&gt;I learned everything I know about brainfuck from the &lt;a href=&#34;http://en.wikipedia.org/wiki/Brainfuck&#34;&gt;brainfuck
Wikipedia page&lt;/a&gt;, and so can
you!&lt;/p&gt;

&lt;h3 id=&#34;conclusion:effc81745af8ee345c04d11094bf5685&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This is probably not a language you want to use, like, ever.&lt;/p&gt;

&lt;p&gt;Unless you&amp;rsquo;re a huge nerd, like myself.&lt;/p&gt;

&lt;p&gt;Then you might want to, just for the fun of it.&lt;/p&gt;

&lt;p&gt;If it doesn&amp;rsquo;t sound like fun to you, then you can safely say you&amp;rsquo;re
less of a nerd than me.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>500 Programming Languages: Python</title>
      <link>http://probablyprogramming.com/2009/08/01/500-programming-languages-python/</link>
      <pubDate>Sat, 01 Aug 2009 12:53:46 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/08/01/500-programming-languages-python/</guid>
      <description>

&lt;p&gt;&lt;a class=&#34;postimage&#34; href=&#34;http://probablyprogramming.com/2009/08/01/500-programming-languages-python/&#34;&gt;&lt;img src=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/sillywalks.jpg&#34; alt=&#34;sillywalk&#34; title=&#34;sillywalk&#34; width=&#34;425&#34; height=&#34;282&#34; /&gt;&lt;/a&gt;
&lt;div class=&#34;attribution&#34;&gt;&lt;a title=&#34;Some rights reserved&#34; href=&#34;http://creativecommons.org/licenses/by/2.0/deed.en&#34;&gt;&lt;img alt=&#34;cc icon attribution&#34; src=&#34;http://probablyprogramming.com/wp-content/uploads/2008/02/cc_icon_attribution_small.gif&#34;/&gt;&lt;/a&gt;(&lt;a href=&#34;http://www.flickr.com/photos/schoffer/196079076/&#34;&gt;image source&lt;/a&gt;)&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Python is one of my favorite programming languages. It&amp;rsquo;s almost always
the first one that I reach for when I have a programming task I&amp;rsquo;d like
to try out, and often enough, it&amp;rsquo;s the final language of that task,
too.&lt;/p&gt;

&lt;h3 id=&#34;introduction-to-python:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Introduction to Python&lt;/h3&gt;

&lt;p&gt;On the &lt;a href=&#34;http://python.org/&#34;&gt;official Python website&lt;/a&gt;, Python is
described as &amp;ldquo;a dynamic object-oriented programming languages that can
be used for many kinds of software development.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;They also claim that &amp;ldquo;Many Python programmers report substantial
productivity gains and feel the language encourages the development of
higher quality, more maintainable code.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;I am inclined to agree.&lt;/p&gt;

&lt;p&gt;Though Python is a true &amp;ldquo;everything is an object&amp;rdquo; OO language, you can
do more than just Object-Oriented programming with it. You can do
plain-ol&amp;rsquo; procedural programming, functional programming,
Object-Oriented programming, and probably some other types of
programming if you wanted.&lt;/p&gt;

&lt;p&gt;One of the nicest things about Python is the &amp;ldquo;batteries included&amp;rdquo;
approach, which means that Python comes with a ton of modules that do
a large amount of what you want to do, right out of the box (or
tarball, or installer&amp;hellip;I don&amp;rsquo;t know if you can actually get Python in
a box). Does your app need to write a &lt;a href=&#34;http://docs.python.org/library/cgi.html&#34;&gt;cgi
app&lt;/a&gt;?  Or even better, a
&lt;a href=&#34;http://docs.python.org/library/wsgiref.html&#34;&gt;wsgi app&lt;/a&gt;?
&lt;a href=&#34;http://docs.python.org/library/httplib.html&#34;&gt;Web&lt;/a&gt;
&lt;a href=&#34;http://docs.python.org/library/urllib2.html&#34;&gt;client&lt;/a&gt;?  &lt;a href=&#34;http://docs.python.org/library/simplehttpserver.html&#34;&gt;Web
server?&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Yep, it has all those, and many, many more.&lt;/p&gt;

&lt;p&gt;There are many, &lt;a href=&#34;http://docs.python.org/tutorial/index.html&#34;&gt;more thorough introductions to
Python&lt;/a&gt; out there, so I
won&amp;rsquo;t attempt to cover the language in too much more depth, but I will
show you a couple of things that really capture the spirit of Python:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18) 
    [GCC 4.3.3] on linux2
    Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.
    &amp;gt;&amp;gt;&amp;gt; from __future__ import braces
      File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1
    SyntaxError: not a chance
    &amp;gt;&amp;gt;&amp;gt; import this
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren&#39;t special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you&#39;re Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it&#39;s a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let&#39;s do more of those!
    &amp;gt;&amp;gt;&amp;gt; import __hello__
    Hello world...
    &amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;my-del-first-del-python-program:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;My &lt;del&gt;First&lt;/del&gt; Python Program&lt;/h3&gt;

&lt;p&gt;This is far from my first program in Python. I first discovered Python
when I was in High School, so possibly as early as 1999-2000. I had
discovered &lt;a href=&#34;http://www.blender.org/&#34;&gt;Blender, a free 3D editing
application&lt;/a&gt;, and it had Python embedded
within it, for use in creating extensions and scripting games for the
built-in game engine. Back then, I still thought I was going to be a
video game developer, so I made some effort to learn Python so I could
write games in Blender.&lt;/p&gt;

&lt;p&gt;Anyway, enough history. :)&lt;/p&gt;

&lt;p&gt;For this program, I implemented a
&lt;a href=&#34;http://en.wikipedia.org/wiki/Brainfuck&#34;&gt;Brainfuck&lt;/a&gt;-to-Python
compiler. I won&amp;rsquo;t go into Brainfuck right now because I will be doing
a post on it next.&lt;/p&gt;

&lt;p&gt;This program is nowhere near demonstrating all of, or even a large
number of, Python&amp;rsquo;s features, but it does demonstrate how easy it is
to write a quick-and-easy program.&lt;/p&gt;

&lt;p&gt;I threw this compiler together in less than 5 minutes, and it
functioned properly on my first try (the &lt;a href=&#34;http://en.wikipedia.org/wiki/Brainfuck#Hello_World.21&#34;&gt;Brainfuck hello world from
Wikipedia&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The only addition I had to make later was handling the case of
end-of-file on the input.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    def compile(program):
        indent = 4
        code = [
            &#39;def compiled(input=None, output=None):&#39;,
            &#39;    import sys&#39;,
            &#39;    if not input: input = sys.stdin&#39;,
            &#39;    if not output: output = sys.stdout&#39;,
            &#39;    i = 0&#39;,
            &#39;    a = [0]*30000&#39;
            ]
        commands = {
            &#39;&amp;gt;&#39;: &#39;i += 1&#39;,
            &#39;&amp;lt;&#39;: &#39;i -= 1&#39;,
            &#39;+&#39;: &#39;a[i] += 1&#39;,
            &#39;-&#39;: &#39;a[i] -= 1&#39;,
            &#39;.&#39;: &#39;output.write(chr(a[i]))&#39;,
            &#39;,&#39;: &#39;a[i] = ord(input.read(1) or &amp;quot;\0&amp;quot;)&#39;,
            &#39;[&#39;: &#39;while a[i]:&#39;,
            &#39;]&#39;: &#39;&#39;
            }
        for command in program:
            line = commands.get(command, None)
            if line: code.append((&#39; &#39; * indent) + line)
    
            if command == &#39;[&#39;:   indent += 4
            elif command == &#39;]&#39;: indent -= 4
        exec &#39;\n&#39;.join(code)
        return compiled
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This function takes a string containing BF code as its one argument
and returns a function which will run that code when called.&lt;/p&gt;

&lt;p&gt;The function returned will have two optional arguments, input and
output, which are expected to be file-like objects (at least
implementing read and write, respectively), which allows for passing
in specific input and/or handling the output from within a python
program.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s kind of a dirty way to do it, building Python source, an then
running it with &lt;em&gt;exec&lt;/em&gt;, but it gets the job done. I could also save
the function to a compiled .pyc file, so you could later import it
directly, but that would require a bit more code and ruin the
simplicity of it all. I could also have generated input for my &lt;a href=&#34;http://probablyprogramming.com/2008/04/18/ppya-python-assembler/&#34;&gt;Python
assembler&lt;/a&gt;,
and used that to generate a compiled .pyc file, but like I said, I was
going for simplicity here, and encouraging people to learn Python, not
necessarily Python bytecodes.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/bf.py&#34;&gt;download the Brainfuck-to-Python Compiler&lt;/a&gt; if you&amp;rsquo;d like.
You can &lt;a href=&#34;http://probablyprogramming.com/wp-content/uploads/2009/08/bf.py&#34;&gt;download the Brainfuck-to-Python Compiler&lt;/a&gt; if you&amp;rsquo;d like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;continue on to learn more about Python&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&#34;anatomy-of-a-python-program:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Anatomy of a Python program&lt;/h3&gt;

&lt;h4 id=&#34;modules:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Modules&lt;/h4&gt;

&lt;p&gt;Python is organized in modules and (optionally) packages. A module is
simply a file which contains some amount of Python code. A package is
simply a directory which contains some number of modules.&lt;/p&gt;

&lt;p&gt;You can import modules with the &lt;em&gt;import&lt;/em&gt; statement, which runs the
code in the module, and then imports any objects the module defines
into the current context (generally under some namespace, see the
&lt;a href=&#34;http://docs.python.org/tutorial/modules.html&#34;&gt;Python Modules
documentation&lt;/a&gt; for more
details on the import statement).)&lt;/p&gt;

&lt;p&gt;The code in a module can be at the module-level, outside of any
functions, or it can be contained in functions and classes. Code at
the module level is run immediately when the module is imported.&lt;/p&gt;

&lt;p&gt;For short scripts, it&amp;rsquo;s usually fine to write code at the module
level. For more complex modules, it&amp;rsquo;s common practice to put all the
code into functions, and then conditionally invoke that function if
the module is run directly.&lt;/p&gt;

&lt;p&gt;For example, to extend my BF compiler above to be invoked directly
from the commandline, I added the following code to the end of the bf
module:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    def cmd_line():
        import sys
        if len(sys.argv) &amp;lt; 2:
            print(&#39;usage: %s bf_file\n&#39; % sys.argv[0])
        else:
            try:
                with file(sys.argv[1]) as f:
                    bf_fn = compile(f.read())
            except IOError, msg:
                print(&amp;quot;couldn&#39;t read file %s: %s\n&amp;quot; % (sys.argv[1], msg))
    
            bf_fn()
    
    if __name__ == &#39;__main__&#39;: cmd_line()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The cmd_line function is just a regular function. The real magic
happens on the last line there. At the module level, &lt;strong&gt;name&lt;/strong&gt; will be
set to &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo; if the current module is the one which was run
directly.&lt;/p&gt;

&lt;p&gt;If a module is imported from any other module, &lt;strong&gt;name&lt;/strong&gt; is set to the
name of the module.&lt;/p&gt;

&lt;h4 id=&#34;python-shell:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Python Shell&lt;/h4&gt;

&lt;p&gt;You can also run Python code directly, one line at a time, from the
python shell. The shell comes up if you just run Python directly
without specifying a module for it to run.&lt;/p&gt;

&lt;p&gt;Python makes a great calculator, random-number picker, interactive
prototyping tool, etc.&lt;/p&gt;

&lt;p&gt;Often when I&amp;rsquo;m playing around with an idea for how to do something,
I&amp;rsquo;ll just open up the Python shell and play around until I get it
working how I&amp;rsquo;d like, then I will commit the code to an actual file.&lt;/p&gt;

&lt;h3 id=&#34;installing-and-running-python:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Installing and Running Python&lt;/h3&gt;

&lt;p&gt;There&amp;rsquo;s a nice &lt;a href=&#34;http://docs.python.org/using/index.html&#34;&gt;guide to installing and running
Python&lt;/a&gt; on various systems at
Python.org, so I won&amp;rsquo;t spend time repeating what they&amp;rsquo;ve got there.&lt;/p&gt;

&lt;h3 id=&#34;learning-more-about-python:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Learning more about Python&lt;/h3&gt;

&lt;p&gt;A good place to start is &lt;a href=&#34;http://docs.python.org/tutorial/&#34;&gt;the Python
tutorial&lt;/a&gt;, and there&amp;rsquo;s a lot to
learn from the links on the &lt;a href=&#34;http://python.org/doc/&#34;&gt;Python
Documentation&lt;/a&gt; page.&lt;/p&gt;

&lt;h3 id=&#34;conclusion:d6db9f21acbdd134e0967a30d8c276a8&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Python is a great language, for both new programmers and experienced
programmers who want to try a language that is probably way nicer than
what they&amp;rsquo;re used to programming in, especially if what you&amp;rsquo;re used to
programming in is PHP. Heck, even &lt;a href=&#34;http://terrychay.com/blog/article/learning-programming.shtml&#34;&gt;Terry Chay recommends Python as a
learning
language&lt;/a&gt;,
and he&amp;rsquo;s known to be a &lt;a href=&#34;http://terrychay.com/blog/article/category/web-development/php&#34;&gt;strong supporter of PHP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In conclusion, if you haven&amp;rsquo;t yet, give Python a try. You won&amp;rsquo;t regret it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The 500 Programming Language Challenge</title>
      <link>http://probablyprogramming.com/2009/07/27/500-programming-language-challenge/</link>
      <pubDate>Mon, 27 Jul 2009 17:15:43 +0000</pubDate>
      
      <guid>http://probablyprogramming.com/2009/07/27/500-programming-language-challenge/</guid>
      <description>

&lt;p&gt;Are you a programmer? If so, then I have a challenge for you. I want
you to become a programming linguist.&lt;/p&gt;

&lt;p&gt;While making (somewhat slow so far) progress on my goal to &lt;a href=&#34;http://probablyprogramming.com/2009/07/06/500-programming-languages/&#34;&gt;program in
500 programming
languages&lt;/a&gt;,
it occurred to me that this could be a much more interesting project if
I got more people involved.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m still aiming for my goal of writing about and in 500 different
programming languages, but here&amp;rsquo;s my challenge to other programmers:&lt;/p&gt;

&lt;h3 id=&#34;write-500-different-programs-in-500-different-programming-languages:186b20511600b217acaef27bd735703e&#34;&gt;Write 500 different programs, in 500 different programming languages.&lt;/h3&gt;

&lt;p&gt;That&amp;rsquo;s it, that&amp;rsquo;s the whole challenge, well, with a couple of rules, I
suppose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The 500 programs must be written after reading this post. No fair
counting them if you&amp;rsquo;ve already (somehow) written 500 programs in
500 different languages, so they have to be new.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The programs need to be semi-non-trivial. Something a little more
advanced than &amp;ldquo;Hello, world.&amp;rdquo; To use one of my previous programs as
an example, an implementation of the game of life is a
semi-non-trivial program. Ideally the example will demonstrate some
of the strengths of the language, as well.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;They languages used need to be &lt;em&gt;different languages&lt;/em&gt;. It doesn&amp;rsquo;t
count if you write in 500 different dialects of Basic, for example.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Share your results with the world. Either post them on your own
blog or put them on github, or whatever, just get them out there so
other programmers can see and learn from them.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Deadline: there isn&amp;rsquo;t one. Since this is a fairly long-term
project, and I know varying people have varying amounts of free
time for such a thing, I&amp;rsquo;m not putting any sort of cap on this. I&amp;rsquo;m
shooting for 3 years or less to completion, but it could just as
easily be a ten-year goal, or a one-year goal for someone
particularly insane/enthusiastic.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Winner: there also isn&amp;rsquo;t one. The idea is to encourage as many
people as possible to do this. However, there is sure to be some
recognition for the first one to accomplish the goal. I mean,
seriously, how many people have written in 500 different
programming languages?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, it&amp;rsquo;s ok if you write some of them in languages you&amp;rsquo;ve written in
before, but you need to write a new program, and it needs to at the
very least do something more interesting than &amp;ldquo;Hello, world&amp;rdquo; or &amp;ldquo;99
Bottles of beer&amp;rdquo;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;d love to see people take this challenge to an interesting extreme,
such as writing a programming that does the same thing in 500
different languages, or writing only in esoteric programming
languages.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ll put up a gallery and perhaps do interviews with/profiles of any
developers who participate in the challenge.&lt;/p&gt;

&lt;h3 id=&#34;become-a-programming-linguist:186b20511600b217acaef27bd735703e&#34;&gt;Become a Programming Linguist&lt;/h3&gt;

&lt;p&gt;In my mind, there are 3 different kinds of programmers: the
single-language programmer, the typical programmer, and the polyglot
programmer.&lt;/p&gt;

&lt;h4 id=&#34;the-single-language-programmer:186b20511600b217acaef27bd735703e&#34;&gt;The single-language programmer&lt;/h4&gt;

&lt;p&gt;This programmer is either very picky, very new to programming, or not
someone who programs for a living. The latter two are acceptable, the
former one really isn&amp;rsquo;t.&lt;/p&gt;

&lt;p&gt;I would neither like to work with someone who refuses to program in
anything but Haskell nor someone who refuses to program in anything
but Visual Basic (though out of the two I&amp;rsquo;d pick the Haskell
programmer).&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re new to programming, or don&amp;rsquo;t plan on doing it much, it&amp;rsquo;s
acceptable to only know one language, but if you even only plan on
writing Ruby On Rails or PHP web-apps for the rest of your life, you
should probably at least know JavaScript and SQL as well.&lt;/p&gt;

&lt;h4 id=&#34;the-typical-programmer:186b20511600b217acaef27bd735703e&#34;&gt;The typical programmer&lt;/h4&gt;

&lt;p&gt;This programmer has learned a few programming languages, perhaps the
Ruby/PHP, JS, and SQL mentioned above. This programmer knows
everything they need to do their current job, and hopefully enough to
do it *&lt;em&gt;well&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The typical programmer isn&amp;rsquo;t &lt;em&gt;too&lt;/em&gt; afraid to pick up a new language
when they feel a need to do so. Generally this need is brought up by
work demands or growing tired of the language they use primarily.&lt;/p&gt;

&lt;p&gt;Still, this programmer tends to stay away from &amp;ldquo;weird&amp;rdquo; programming
languages, be they functional, stack-based, or simply something with
an odd syntax compared to what they are used to. Such languages seem
like they would be too much work to learn, without any practical
benefit for this programmer who already has a good list of languages
that do what they need.&lt;/p&gt;

&lt;p&gt;With this self-inflicted limitation, the typical programming is truly
missing out on some profound, powerful knowledge that they could gain
if they even just took a little time to &lt;em&gt;understand&lt;/em&gt; these foreign
paradigms, let alone actually program in them.&lt;/p&gt;

&lt;h4 id=&#34;the-polyglot-programmer:186b20511600b217acaef27bd735703e&#34;&gt;The polyglot programmer&lt;/h4&gt;

&lt;p&gt;This programmer loves programming, and more importantly, loves
programming languages.&lt;/p&gt;

&lt;p&gt;The polyglot programmer doesn&amp;rsquo;t let as trivial a thing as &amp;ldquo;not needing
to&amp;rdquo; prevent them from learning a new programming language. They seek
out new paradigms and techniques and revel in their ability to apply
what they learn from one language to a language they already know,
thus making them a better programmer.&lt;/p&gt;

&lt;p&gt;This programmer understands that there is a reason for every
programming language design decision (even if that reason is &amp;ldquo;we
didn&amp;rsquo;t think about it too much&amp;rdquo;), and can&amp;rsquo;t wait to try out a new
language feature they&amp;rsquo;ve as-yet not encountered.&lt;/p&gt;

&lt;p&gt;A polyglot programmer can apply for jobs that a typical programmer can
only scoff at for requiring &amp;ldquo;one of those weird programming languages&amp;rdquo;
that they could never be bothered to learn, and they can more quickly
learn a new language that their current job might require because they
have a better understanding of programming languages in general.&lt;/p&gt;

&lt;p&gt;A programming linguist is basically a very-well-versed polyglot
programmer, one who can pick up a new language in a day if there is
any good documentation for it&lt;/p&gt;

&lt;h3 id=&#34;the-goal:186b20511600b217acaef27bd735703e&#34;&gt;The goal&lt;/h3&gt;

&lt;p&gt;The goal here isn&amp;rsquo;t to learn and become an expert at all of the 500
different programming languages. The goal is to be exposed to 500
different programming languages, to glean a bit of knowledge, to open
one&amp;rsquo;s mind to new ways of looking at and solving problems, and to
ultimately become a better programmer.&lt;/p&gt;

&lt;p&gt;It doesn&amp;rsquo;t matter if after this, you never touch any of the 500
languages ever again, just the act of coming to understand the
language enough to write a program in it will have altered your mind
enough to make a lasting impact, especially for languages which are
different from the &amp;ldquo;norm&amp;rdquo; of what you are used to.&lt;/p&gt;

&lt;div class=&#34;pitch&#34;&gt;Will you accept this challenge? &lt;br /&gt;&lt;br /&gt;
If so, let me know in the comments or an email.&lt;br /&gt;&lt;br /&gt;
If not, let me know why not. I&#39;d love to hear from you either way.
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>