<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>This Ain&apos;t No Content</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/" />
    <link rel="self" type="application/atom+xml" href="http://noctilucent.org/blog/atom.xml" />
    <id>tag:noctilucent.org,2008-08-24:/blog//1</id>
    <updated>2010-06-04T02:28:36Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.32-en</generator>

<entry>
    <title>Some Editor Tricks</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2010/06/some-editor-tricks.html" />
    <id>tag:noctilucent.org,2010:/blog//1.136</id>

    <published>2010-06-04T01:38:16Z</published>
    <updated>2010-06-04T02:28:36Z</updated>

    <summary> Here&apos;s the scenario (fictional, but not too far removed from real life): I want to munge some data I have into code. Let&apos;s say I have this in my editor: The Comedy of Errors Much Ado About Nothing Twelfth...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>
Here's the scenario (fictional, but not too far removed from real life): I
want to munge some data I have into code.  Let's say I have this in my
editor:
</p>

<pre>
The Comedy of Errors
Much Ado About Nothing
Twelfth Night
</pre>

<p>
and the result I want is this:
</p>

<pre>
THE_COMEDY_OF_ERRORS = &quot;The Comedy of Errors&quot;
MUCH_ADO_ABOUT_NOTHING = &quot;Much Ado About Nothing&quot;
TWELFTH_NIGHT = &quot;Twelfth Night&quot;
</pre>

<p>
My editor of choice is vim and I like to run in a Unix (these days that usually
means Linux) environment.  Given those tools, here's one way to do it.
</p>

<p>
In command mode, I type <code>3yy</code> (<i>yank three lines</i>), move the
cursor to the line where I want to put them and hit <code>p</code> (for <i>put</i>).
</p>

<pre>
The Comedy of Errors
Much Ado About Nothing
Twelfth Night

The Comedy of Errors
Much Ado About Nothing
Twelfth Night
</pre>

<p>
I use the bang command to pipe the first three lines through
<code>sed 's/ /_/g'</code>.  (To pipe three lines through a shell command,
type <code>3!!</code> in command mode, then type the command at the colon
prompt at the bottom of the screen.)  This <code>sed</code> command replaces 
all spaces with underscores, leaving:
</p>

<pre>
The_Comedy_of_Errors
Much_Ado_About_Nothing
Twelfth_Night

The Comedy of Errors
Much Ado About Nothing
Twelfth Night
</pre>

<p>
I pipe the first three lines through <code>perl -pe 's/\w+/uc($&amp;)/e'</code>.
This forces all letters to uppercase, leaving:
</p>

<pre>
THE_COMEDY_OF_ERRORS
MUCH_ADO_ABOUT_NOTHING
TWELFTH_NIGHT

The Comedy of Errors
Much Ado About Nothing
Twelfth Night
</pre>

<p>
I pipe the last three lines through <code>awk '{ print &quot; = \&quot;&quot; $0 &quot;\&quot;&quot;}'</code>.  This inserts an equals sign and surrounds the
original lines with (simple) double quotes.
</p>

<pre>
THE_COMEDY_OF_ERRORS
MUCH_ADO_ABOUT_NOTHING
TWELFTH_NIGHT

 = &quot;The Comedy of Errors&quot;
 = &quot;Much Ado About Nothing&quot;
 = &quot;Twelfth Night&quot;
</pre>

<p>
At this point, it's a simple process to move the lines to their correct places
using a combination of <code>dd</code> (<i>delete line</i>) and
<code>p</code> (<i>put line</i>) and <code>J</code> (<i>join lines</i>) to
get my desired result.
</p>

<p>
Things that really help when using this kind of approach:
</p>

<ul>
 <li>an open shell window nearby to try one-liners on test data</li>
 <li>trustworthy multiple levels of undo/redo</li>
 <li>lots of practice with editor basics</li>
</ul>]]>
        
    </content>
</entry>

<entry>
    <title>Getting Back Online</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2010/05/getting-back-online.html" />
    <id>tag:noctilucent.org,2010:/blog//1.135</id>

    <published>2010-05-16T15:03:41Z</published>
    <updated>2010-05-16T15:50:21Z</updated>

    <summary>Recently, we had a lightning strike that hit a tree in the garden. We also got an electricity spike that looks like it came in through the phone line. That spike took out the DSL modem, the router and the...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>Recently, we had a lightning strike that hit a tree in the garden.  We also got an electricity spike that looks like it came in through the phone line.  That spike took out the <span class="caps">DSL </span>modem, the router and the motherboard on my <span class="caps">PC.</span></p>

<p>While recovering from that I made some mistakes that I'll summarize here.  Maybe other people can avoid those mistakes or maybe I'll remember better next time.</p>

<h3> Lesson One -- Buy a Surge Protector </h3>

<p>...*and use it*.  We had surge protectors on all the PC equipment.  The <span class="caps">DSL </span>modem was in another room and there was nothing between it and the phone jack.  Since the incident I've bought one of the power strips that includes the protector for the phone line.  It's too late for this time of course, but it's early in the year yet and we will have many storms during the summer.</p>

<h3>Keep the <span class="caps">DSL</span> Account Information</h3>

<p>... in an accessible place.  I was mostly okay here, but the password I had was wrong or out of date.</p>

<h3>Avoid "Wizard" Setups</h3>

<p>I bought a replacement modem in a store.  This was in part because I've had problems with deliveries of items requiring a signature before where I've had to drive to some remote depot to pick up the item.  I hooked it up, went through the setup "wizard" web interface and ran into an authentication problem because the password was wrong.</p>

<p>For the record, the modem was a D-Link <span class="caps">DSL</span>-2320B.  After I ran through the "wizard" setup once, several of the original options were no longer available.  It turned out that this was the key to my problems.</p>

<p>Again, for the record, a way to configure the modem for <span class="caps">AT&amp;T DSL </span>that works is as follows:</p>


<ol>
<li>untick the "DSL Auto-connect" checkbox</li>
<li>leave the <span class="caps">VPI </span>setting at 0</li>
<li>leave the <span class="caps">VCI </span>setting at 35</li>
<li>choose <span class="caps">PPP</span>oE if connecting directly to a PC; choose Bridging if connecting to a home router</li>
<li>leave "Encapsulation Mode" as "LLC/SNAP <span class="caps">BRIDGING</span>"</li>
<li>leave <span class="caps">LAN </span>settings at default or change them to taste if you know what you're doing</li>
</ol>



<h3>Use the Pinhole Reset Button If You Run Into Trouble</h3>

<p>It's on the back of the modem and you press it with a pen or a pin for ten seconds to reset everything to factory defaults.  It seems that this is what it took to get the modem to really forget the original, incorrect password and use the new, reset password I was entering through the web interface.</p>

<h3>Beware of Premium Cost Services</h3>

<p>... unless you enjoy paying for someone you their script over the phone.  <span class="caps">AT&amp;T'</span>s initial phone support was actually pretty good -- I got through to a second level support person who knew what he was talking about and helpful, even though I was not using a supported modem.  When I called again a couple of days later, I allowed myself to be browbeaten into signing up for the Tech Connect service, at well over $100.  I figured I'd get even better support from a networking pro.  Instead I was connected to a newbie who clearly didn't know anything beyond the script.  After a long time going through the usual rigmarole of turning the modem off and on and checking the lights, the script eventually had me do the pinhole reset, which fixed the problem.</p>

<p>It's possible that, had I spent even more time on the phone and still not fixed the problem, I would have got to a second level of (paid) support.  As it was, I was left kicking myself for not trying this myself.</p>

<h3>The Internet is Your Friend</h3>

<p>... even when the problem is connecting to the Internet.  If I had made better use of other ways to connect, I could have saved myself some trouble.  After I got my initial connection, I figured out how to get the home router up and running with hints from forum postings.  (Basically, make the modem as stupid as it can be, just a bridge, and let the router take care of the <span class="caps">PPP</span>oE authentication.)</p>

<p>Phone support in general is slow and limited.  The world wide web is, for <span class="caps">DSL </span>troubleshooting as for other things, vast and quick to search.</p>

<h3> In Sum</h3>

<p>Don't do like I did.  First of all, protect yourself against lightning.  Don't rely on your provider for support beyond the basics (connection information etc.).</p>

<p>Oh, and if you do run into trouble, post so others can learn from your experience.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Sinatra Hints</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2010/04/sinatra-hints.html" />
    <id>tag:noctilucent.org,2010:/blog//1.134</id>

    <published>2010-04-14T15:26:32Z</published>
    <updated>2010-04-14T15:34:10Z</updated>

    <summary>I&apos;ve been caught by this for at least the second time: haml views and CSS files not being found in a brand new Sinatra app. The configuration is (to me) somewhat obscure, so I&apos;m documenting the fix here. To get...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>I've been caught by this for at least the second time: haml views and CSS files not being found in a brand new Sinatra app.  The configuration is (to me) somewhat obscure, so I'm documenting the fix here.</p>

<p>To get the <code>views</code> and <code>public</code> directories working properly, be sure to configure <code>app_file</code> (set to <code>nil</code> by default in <code>Sinatra::Base</code>):</p>

<pre><code>configure do
  set :app_file, __FILE__
end
</code></pre>

<p>To get static files working properly, configure <code>static</code> (set to <code>false</code> by default in <code>Sinatra::Base</code>):</p>

<pre><code>configure do
  set :app_file, __FILE__
  set :static, true
end
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Notes on Talking with Slides</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/12/presentation-notes.html" />
    <id>tag:noctilucent.org,2009:/blog//1.133</id>

    <published>2009-12-30T18:23:57Z</published>
    <updated>2010-05-26T11:51:34Z</updated>

    <summary>I gave an internal company talk reporting on my trip to OOPSLA this year. Here are some notes on the experience. Things I Would Do Again Focus on some small, interesting topics The conference lasted for five days (including the...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>I gave an internal company talk reporting on my trip to <span class="caps">OOPSLA </span>this year.  Here are some notes on the experience.</p>

<h3>Things I Would Do Again</h3>

<h4>Focus on some small, interesting topics</h4>

<p>The conference lasted for five days (including the Sunday before the "official" start).  I attended mostly tutorials but also a limited number of conference talks.  Instead of trying to summarize everything I saw, I picked five topics that interested me.  In the end I only presented four.</p>

<h4>Avoid Wasting Time With Slideware</h4>

<p>This time I created my slides using something called <a href="http://meyerweb.com/eric/tools/s5/">S5</a>, so it was all one big <span class="caps">HTML </span>file.  This meant I was editing using a tool I know well (my favourite text editor, vim).  S5 has its quirks -- notably, it seems to behave differently in different browsers -- but the file format is relatively transparent and easy to modify.</p>

<h4>Allow Plenty of Time for Preparation</h4>

<p>I decided in advance that I was not going to rehash the material I had already seen.  I had a CD with the slides of the presentations I had seen.  Instead of copying those I researched the background and came up with my own take on the ideas.  This meant many evenings and weekends googling for and reading references.</p>

<h4>Break Up the Talk</h4>

<p>I gave four mini talks, not directly related to one another.  They varied in length and style.  There was a good chance that most people found at least one part interesting.</p>

<h4>Involve the Audience</h4>

<p>I did steal two questions from a "Jeopardy"-style quiz that the <span class="caps">OOPLSA </span>organizers staged one evening.  I started out the talk with these two questions.  If nothing else, it gave me a chance to ensure that at least a few people were awake. </p>

<h4>Put the Question on a Slide But Not the Answer</h4>

<p>One effective way to motivate the audience is to tweak their curiosity.  Putting the answers on the slides makes them complacent.  If the answer isn't on a slide they have to listen to get the answer.</p>

<h4>Move Material From Slides to Notes</h4>

<p>There is a strong temptation to make the slides an outline of the entire talk.  This has a powerful soporific effect on the audience.  The slides should be a small part of the talk, only drawing attention from time to time.</p>

<h3>Changes I Would Make If I Did It Again</h3>

<h4>Cut Ruthlessly</h4>

<p>This means fewer slides and less material on each slide.  I figured initially that a minute a slide ought to be about right on average.  I didn't run out of time but I did rush the last part of the talk with one eye on the clock.</p>

<h4>Avoid Abstraction and Generalities</h4>

<p>People tend to understand specific, concrete examples better than more general, abstract statements.  This seems to be even truer when they are listening to a talk.  Even worse, the general and abstract seems to send people to sleep (not literally but their attention drifts).</p>

<h4>Plan More Occasions to Engage the Audience</h4>

<p>This would give me a chance to wake them up if necessary.  It would also be a chance for me to see how much they are getting it.</p>

<h4>Make Sure I Understand Everything I Plan to Say</h4>

<p>Towards the end of my talk I came across a slide that included a point that didn't make sense to me when I read it in front of my audience.  I stumbled and it was noticed and I'm sure it cost me some credibility.  The emphasis is on <strong>everything</strong>.  This means reviewing everything, especially the stuff that's written last thing at night.  During the review, I want to make sure I agree with and can support with everything I plan to say.</p>

<h4>Break Up Monotony in the Slides</h4>

<p>I had very few images in my slides, mostly because I found the amount of work to create my own images burdensome and I found it hard to think of existing images that I could use that would be relevant.  In future I'll look into something like <a href="http://www.inkscape.org/">Inkscape</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Ruby Notes</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/12/ruby-notes.html" />
    <id>tag:noctilucent.org,2009:/blog//1.132</id>

    <published>2009-12-10T20:37:05Z</published>
    <updated>2010-02-08T17:42:38Z</updated>

    <summary>Mongo In order to install the mongo_ext gem, I had to first ruby1.8-dev package. Explicit Breakpoints Nice to examine a failing rspec test: just insert require &quot;rubygems&quot;; require &quot;ruby-debug&quot;; debugger at the relevant point in the code. (From an rspec...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<h2>Mongo</h2>

<p>In order to install the <code>mongo_ext</code> gem, I had to first
<a href="http://mentalized.net/journal/2006/01/24/no_such_file_to_load_mkmf/">ruby1.8-dev package</a>.</p>

<h2>Explicit Breakpoints</h2>

<p>Nice to examine a failing rspec test: just insert <code>require "rubygems"; require "ruby-debug"; debugger</code> at the relevant point in the code.  (From <a href="http://old.nabble.com/Debugging-trick.-td16776159.html">an rspec mailing list</a>)</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Custom Error Handling in Sinatra</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/11/custom-error-handling-in-sinatra.html" />
    <id>tag:noctilucent.org,2009:/blog//1.131</id>

    <published>2009-11-13T19:17:28Z</published>
    <updated>2010-01-17T12:57:43Z</updated>

    <summary>Quick note for future reference: Sinatra will ordinarily enable :raise_errors when :environment is :production. From my reading of the code, this causes Sinatra not to attempt to handle exceptions but to let them bubble up to the surrounding Rack container....</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>Quick note for future reference: </p>

<p>Sinatra will ordinarily enable <code>:raise_errors</code> when <code>:environment</code> is
<code>:production</code>.  From my reading of the code, this causes Sinatra not to
attempt to handle exceptions but to let them bubble up to the surrounding
Rack container.  In this situation, error-handling directives like</p>

<pre><code>error do
    @error_msg = request.env['sinatra.error']
    haml :error_page
end
</code></pre>

<p>have no effect.</p>

<p>In order to fix the problem, just explicitly <code>disable :raise_errors</code> in the
Sinatra application.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OOPSLA Thursday</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/10/oopsla-thursday.html" />
    <id>tag:noctilucent.org,2009:/blog//1.130</id>

    <published>2009-10-30T02:02:33Z</published>
    <updated>2009-10-30T02:06:19Z</updated>

    <summary>DSL -- A Programmer&apos;s View This was a survey of different techniques for implementing domain specific languages (DSLs) given by an academic. I thought it was a good blend of principles and practice, summarizing the advantages and disadvantages of different...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<h2>DSL -- A Programmer's View</h2>

<p>This was a survey of different techniques for implementing domain specific
languages (DSLs) given by an academic.  I thought it was a good blend of
principles and practice, summarizing the advantages and disadvantages of
different approaches.</p>

<p>Of the tools discussed, I had only seen ANTLR before.  There was also a
tool called SableCC that really seemed to offer little advantage over
ANTLR.  The main difference I saw was that you could embed little snippets
of your target language in ANTLR but not SableCC.</p>

<p>The core examples were done in Haskell and, although I'm barely familiar
with the language, I think it works really well in this kind of scenario
because its syntax is clean and therefore does not distract one from the
points being made.  Both the embedded parser (Parsec) and embedded
language worked well.</p>

<p>My recollection of the major points:</p>

<ul>
<li>compilers offer optimization and high performance (if you put enough
effort into them) but are very inflexible and the source tends to get "lost"
in compilation, leading to problems understanding the resulting system,
particularly if it needs to be debugged</li>
<li>interpreters are quite flexible and can be made to generate high quality
error messages customized for the domain; performance is often poor</li>
<li>DSLs implemented with either compilers or interpreters are hard to compose,
hard to decompose; on the other hand you can easily add new semantics for
the language just by writing a new compiler or interpreter for it</li>
<li>for the presenter, a very interesting option is "polymorphic embedding";
unfortunately he did not have time to present this, so I'll have to read
the slides when I get them</li>
</ul>

<p>That's it for OOPSLA for me this year.  Next year it's SPLASH in Reno.  I
haven't yet decided if I want to go again or try something else instead.</p>

<h2>Random Observations</h2>

<p>The Jeopardy-style quiz was interesting.  None of the three teams could
identify a design pattern projected as a diagram on the big screen.
Even the audience, which included big names from the pattern community,
had problems.  It looked a bit like the Proxy pattern, a bit like
Strategy.  It turned out to be the Bridge, which I think is a good choice
for a quiz. It is not one that ever struck me as one I'll be eager to
apply.  Perhaps it's a good interview question if you want to deliberately
make a candidate uncomfortable.</p>

<p>I finally did get to talk to some people informally on Wednesday, but for
an outsider, the "hallway track" seems pretty mythical.  I had the
impression there were cliques and tribes and I felt very much the outsider.
Perhaps this is an argument for going to the same conference multiple
times, though I could see the danger of it getting incestuous after a
while.  And OOPSLA has been going for decades now...</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OOPSLA Tuesday / Wednesday</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/10/oopsla-tuesday-wednesday.html" />
    <id>tag:noctilucent.org,2009:/blog//1.129</id>

    <published>2009-10-28T21:11:34Z</published>
    <updated>2010-02-06T14:33:43Z</updated>

    <summary>More tutorial notes Realtime Programming on the Java Platform This was an information-dense walkthrough of the realtime spec and how to use realtime implementations. The realtime spec makes no changes to the language as such, however it does require a...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>More tutorial notes</p>

<h2>Realtime Programming on the Java Platform</h2>

<p>This was an information-dense walkthrough of the realtime spec and how to
use realtime implementations.  The realtime spec makes no changes to the
language as such, however it does require a special version of the runtime
and the underlying OS and hardware must also support realtime.  Typically,
an application will get roughly a 30% reduction in throughput when it is
ported to realtime.</p>

<p>For real-world applications, it's infeasible to provide cast-iron
real-time guarantees.  However, for applications that justify it, a
system can be written (with a lot of effort) that meets realtime goals
(which will typically firm bounds on things like response times) with high
probability.</p>

<p>A lot of the effort goes into ensuring that non-realtime threads and
garbage collection do not interfere with realtime threads.  At the
highest level, you can define realtime threads that are not allowed to
read from the Java heap at all (any attempt causes a runtime exception).
These threads are only allowed to use specially defined storage that is
allocated before they run and is effectively immortal (and immune from
garbage collection).  The API for defining special memory contexts as
specified is more over-elaborate.</p>

<p>The Sun realtime Java product offers realtime garbage collection.  This
works by running GC as a realtime thread and ensuring that the GC
operation never needs to move objects.  Thus the GC can be pre-empted
at any time by a higher-priority thread with no corruption of heap
state.</p>

<p>Of note: apparently financial companies think they care about "soft" realtime until they understand they need to pay a penalty in throughput.  When they do, they nearly always decide they'll accept rare high latency in exchange for constantly high throughput.</p>

<h2>Erlang / OTP</h2>

<p>Really, OTP is an important part of the Erlang story.  Despite the name,
OTP has little to do with telephony and everything to do with abstracting
common usage scenarios.  There's a common pattern whereby the OTP module
(e.g. gen<em>server, gen</em>fsm) controls the lifecycle, and the application
code is implemented in callback functions that are called appropriately.
Thus, OTP can take care of setup and (particularly important) error
handling.  The OTP philosophy for handling errors is to kill the offending
process.  A supervisor process is then responsible for handling the crash,
often by restarting the process (in a known good state).  Application
design is largely about designing trees of supervisor and so-called
worker processes.</p>

<h2>Combinatorial Testing</h2>

<p>This was about the problem of choosing combinations of input parameters
(considered abstractly, so they could include things like machine state,
OS version, etc.)  Full coverage of all combinations is infeasible, but
you want to cover some combinations.  Covering all combinations of all
pairs turns out to be good enough in practice much of the time.  Surprisingly,
choosing even these is not a solved problem.  Various tools exist that
come up with reasonable but often varying results.  The presenter's
favourites were PICT and (as honorable mention) Jenny.  For all the
tools, the results they generate are pretty basic and some effort is
required to use them to generate actual test data.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OOPSLA Tuesday Morning</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/10/oopsla-tuesday-morning.html" />
    <id>tag:noctilucent.org,2009:/blog//1.128</id>

    <published>2009-10-28T01:57:05Z</published>
    <updated>2010-01-29T02:34:29Z</updated>

    <summary>It&apos;s an interesting being &quot;industry&quot; at a somewhat academic conference (although I think this is less academic than most). Less than quarter of attendees are from industry and they seem to be a very diverse bunch. Students and faculty are...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>It's an interesting being "industry" at a somewhat academic conference
(although I think this is less academic than most).  Less than quarter of
attendees are from industry and they seem to be a very diverse bunch.
Students and faculty are more cohesive groups, so I think they're easier
to cater to.</p>

<h2>The Keynote</h2>

<p>Barbara Liskov got well deserved applause for her reprise of her
Turing award acceptance speech, talking about her search for ways to raise the
level of abstraction in order to enhance the expressiveness of programs.
She put herself clearly in the Dijkstra camp, so she believes that
ease of reading source code (especially other people's code) is more
important than ease of writing it and she believes that we want to make
it easier for people to reason about the behaviour and correctness of the
code.</p>

<p>She talked about some of the papers that really influenced her research,
starting (if I recall correctly) with Dijkstra's famous "Goto Considered
Harmful" that was published as a letter to CACM (back when it was a
serious research journal).  It was interesting to see how there were
nuggets of insight and how much of a struggle it was for researchers
to come up with ideas we take for granted today, such as how to do
data abstraction with encapsulation.</p>

<p>The message I heard was that there are still many areas where the level
of abstraction we work with is still too low.</p>

<h2>Onward! Papers</h2>

<p>These lived up to my expectations -- vaguely plausible to borderline crazy.</p>

<p>Jonathan Edwards' work on Coherence (a language where statements inside a
"co-action" all run simultaneously from the point of view of the programmer)
looks brilliant.  We'd all like to be rid of ordering-related bugs in our code.
Unfortunately there's no implementation -- he says it's more important to get
the definition right first.  The idea of a "co-action" works perfectly in the
rigged example but how does it work for something that is more realistic?</p>

<p>"Traditional assignment considered harmful" seemed mostly
provocative, as it seemed to be saying a "swap values" operator would
be easier to work with than a traditional assignment operator.  A member
of the audience trenchantly argued that the thing on the right of
the assignment operator is an expression, not just a simple value (and
it seems to me that blows a huge hole in the argument).  </p>

<p>The "Silhouette" talk wins top marks for eccentric presentation style.
The professor made the slides in the presentation deck from one to the
next on behalf of the grad student presenter, but the presenter was in
a film (possibly Quicktime?) inside the slides.  It worked somewhat.  The
idea is to explore the concept of using shapes and the way they nest and
overlap to explore program design in a highly visual way.  It's extremely
fuzzy at the moment, so it's hard to judge if it might be worthwhile.
Every other visual programming metaphor has pretty much failed, but this
one at least looks a little different.</p>

<p>Finally, there was something called "PI", where PI is of course the
Greek letter.  This is a kind of a meta programming language, although
the presenter insisted on calling it a pattern language.  It was built
to scratch in itch (always a good sign) that the presenter ran into while
trying to build languages for domain experts.  It seems to be in the
Lisp/Scheme family in the sense that you type expressions at a prompt
and some expressions cause changes to the runtime.  However, it goes
much further in allowing new syntax to be added just by adding definitions
to be added to the grammar that PI understands.  It looks like a lot of
existing ideas packaged slightly differently, but from what I can tell
there is an implementation.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OOPSLA Monday</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/10/oopsla-monday.html" />
    <id>tag:noctilucent.org,2009:/blog//1.127</id>

    <published>2009-10-28T01:50:58Z</published>
    <updated>2010-07-24T21:30:05Z</updated>

    <summary>Some more notes on the tutorials I attended Smalltalk I was a bit disappointed in this tutorial. It never got much beyond installing an image and getting used to the syntax (which is admittedly a bit different from the curly...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>Some more notes on the tutorials I attended</p>

<h2>Smalltalk</h2>

<p>I was a bit disappointed in this tutorial.  It never got much beyond
installing an image and getting used to the syntax (which is admittedly
a bit different from the curly brace syntax I grew up with).  The slide
deck was the old-fashioned kind where every point has a bullet point.
I felt many of them could have been skimmed over with little loss.  I was particularly unhappy about getting several slides at the start about why I might be interested in learning about Smalltalk.  Isn't flying to Florida and paying to attend the tutorial
enough evidence to show that I am already interested?</p>

<p>The image used was Pharo (apparently a fork of the Squeak project)
and the meatier part of the tutorial was spent exploring the Class
Browser, Test Runner, inspectors and the Monticello Browser.</p>

<p>The presenter, James Foster, was obviously very knowledgeable about
Smalltalk but a little fuzzy on Java and other curly brace languages
he was comparing it with.  I mentioned that I had some exposure to
Ruby and he responded with a money quote from Ward Cunningham that
"I always expected Smalltalk to come back, I just didn't expect it
to be called Ruby".  Well, yes.</p>

<h2>Parameterized Unit Testing</h2>

<p>This should have been called "demo of the PEX tool".  At least two
other people who attended were annoyed because the tool could only be
used with C# in Windows.  Even though I do a lot of C# on Windows
these days I was somewhat concerned at licensing terms (pick academic
non-commercial or temporary evaluation).  Java barely got a mention:
apparently Junit4 has some support for parameterized unit tests and
Agitar has a product that can be used to generate values.</p>

<p>The tool itself is impressive.  You provide a unit test that takes
parameters for the input values.  It generates initial values (generally,
the simnplest possible) and uses profiler hooks to instrument
the bytecode at runtime to provide an extremely detailed trace of
actual execution.  The tool sees what paths are available at each
branch and which are taken.  It then uses a constraint solver to decide
what values to try to make the execution take other branches.  (The
constraint solver comes from research into theorem proving and it
understands restricted domains like integer arithmetic and simple
program constructs such as tuples and arrays.)  Within seconds it
generates thousands of runs with different test data and keeps only
those that caused a new execution path to be taken.</p>

<p>The amount of work required to get this functional is impressive.
For example, they built into the tool a formal understanding of
the semantics of every single byte code in the CLR (including what
exceptions it could throw, including arithmetic overflow, which is
possible if you configure Visual Studio the right way).</p>

<p>The question arises: if my unit test is going to get unknown (to me)
input values how can I make meaningful assertions about its behaviour?
In the tutorial, they presented some "patterns".  In many cases, it
boils down to identifying the group properties of your code: are there
inverse operations, commutative operations, etc?  If so, you can
build a sequence of operations that should always have the same result,
no matter what the input.  Others relate to seeing that state
invariants are preserved, for example if you insert something into
a collection, you always expect to find it there afterwards.</p>

<p>This kind of tool looks promising as a way to alleviate the tedious
task of coming up with plausible inputs.  It does come at a cost
to maintainability of unit tests.  It could be very useful in
generating regression tests.</p>

<p>It's just a shame that this is Microsoft only and, at that, not available
for production use unless Microsoft decides to include it in their
Visual Studio offering at some time in the future.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OOPSLA Day One</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/10/oopsla-day-one.html" />
    <id>tag:noctilucent.org,2009:/blog//1.126</id>

    <published>2009-10-26T23:49:23Z</published>
    <updated>2010-01-23T14:44:10Z</updated>

    <summary>My notes from the tutorials I attended on Sunday. Dependency Injection in Dynamic Languages Miško Hevery and an uncredited cohort named (I think) Coery, who seemed to be the Javascript expert. DI can make large programs in dynamic languages more...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>My notes from the tutorials I attended on Sunday.</p>

<h2>Dependency Injection in Dynamic Languages</h2>

<p>Miško Hevery and an uncredited cohort named (I think) Coery, who seemed to
be the Javascript expert.</p>

<p>DI can make large programs in dynamic languages more tractable.  The same
argument holds as for static languages: "wiring/construction" and business
logic are separate concerns.  By separating them you make the code easier
to read and modify.  Sometimes, when people say dynamic languages don't
scale to large programs, they really mean the way they're written.</p>

<p>The example program was tic-tac-toe in Javascript.  Even this small
application had a main method that was starting to get out of control and
consisted mainly of wiring.  The DI version reduced main to essentially
one line.</p>

<p>It turns out that DI is not all that hard to do in a dynamic language.</p>

<ul>
<li><p>You choose what you're going to use as your "lookup symbol".  This could be
a string or it could be more sophisticated, approximating the type information
you would get in a statically typed language, such as a Java interface.</p></li>
<li><p>You implement a chain of "providers", each of which knows about one kind
of dependency resolution and delegates to the next if it doesn't know how
to handle the request.  At the end of the chain is a dummy provider that just
errors out.</p></li>
</ul>

<p>If you're building your own DI, can build custom providers specific to your
domain.  In Javascript, for example, it makes sense to wire listeners, so
that the boilerplate code that usually is required falls away.</p>

<p>In the tutorial, they wrote a simple, short DI implementation in a couple of
dozen lines of Javascript, test driven using the neat JsTestDriver framework.</p>

<h2>Functional Programming in Object Oriented Code</h2>

<p>Phil Goodwin gave this talk.</p>

<p>You can, with enough effort, use almost all features of functional programming
in Java.</p>

<p>I found the ideas of how functional ideas could be incorporated into OO
code thought provoking.  OO and functional complement each other: one's
weaknesses are generally the other's strengths and vice versa.  Taking
an idea from Bertrand Meyer, you can use commands to change things (OO)
and use queries to find things out (functional).</p>

<p>Functional programming means reversing one common workflow in OO
programming.  In OO, you look for case statements and consider replacing
them with polymorphism.  In functional programming, you remove polymorphism
in favour of explicit case statements.  However, these case statements are
much more agnostic about what types they work with.</p>

<p>(The example library is written in Java.  A brave choice because, in many
ways, Java is terrible for functional programming.  Functions are not
first class values (and it's hard to fake it).   The type system is
concerned about values, whereas functional programming languages are more
concerned about the type of the functions.  (Besides, the lack of type
inferencing makes nesting of types painful and functional programming is
all about nesting.)</p>

<p>The Google collections framework is a helpful starting point: you get
the hooks with which you can use filter/map/reduce, etc..</p>

<p>Implementation: you can avoid blowing the stack using a trampoline to
provide tail recursion removal and continuations.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Writing An Effective Merge</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/08/writing-an-effective-merge.html" />
    <id>tag:noctilucent.org,2009:/blog//1.125</id>

    <published>2009-08-22T01:58:28Z</published>
    <updated>2010-05-15T23:37:32Z</updated>

    <summary>Recently I&apos;ve been implementing simple algorithms from scratch from memory. As an exercise, this has the advantage of being short, well-defined and (for me at least) challenging. For example, I found it surprisingly hard to write an effective merge of...</summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>Recently I've been implementing simple algorithms from scratch from memory.  As an exercise, this has the advantage of being short, well-defined and (for me at least) challenging.  For example, I found it surprisingly hard to write an effective merge of the kind needed for the mergesort algorithm.</p>

<p>The spec is <code>void merge(int[] a, int lo, int mid, int hi)</code>: two parts of the array are to be merged.  It's assumed the two parts are already sorted.  The two parts are adjacent; the first part includes the items from <code>lo</code> to <code>mid - 1</code>; the second is the items from <code>mid</code> to <code>hi - 1</code>.</p>

<p>Here's my first attempt, rushed out late at night.</p>

<pre><code>    private void merge(int[] a, int lo, int mid, int hi) {
        assert mid == lo + (hi - lo) / 2;
        List&lt;Integer&gt; result = new ArrayList&lt;Integer&gt;();
        int i = lo;
        int j = mid;

        while (i &lt; mid &amp;&amp; j &lt; hi) {
            int m = a[i];
            int n = a[j];
            if (m &gt; n) {
                result.add(n);
                j++;
            } else {
                result.add(m);
                i++;
            }
        }
        while (i &lt; mid) {
            result.add(a[i++]);
        }
        while (j &lt; hi) {
            result.add(a[j++]);
        }
        for (i = lo, j = 0; j &lt; result.size(); i++, j++) {
            a[i] = result.get(j);
        }
    }
}
</code></pre>

<p>It did the job, but oh my, how I didn't like it.  It's verbose and it creates this temporary list of O(n) size.  After some more work and several blind alleys, I came up with the following.  It's better, but still, it seems harder than it should be.  Oddly enough, I found it easier to implement quicksort from scratch than just the merge portion of mergesort.</p>

<pre><code>    private void merge(int[] a, int lo, int mid, int hi) {
        assert mid == lo + (hi - lo) / 2;
        int i = lo;
        int j = mid;
        while (i &lt; mid) {
            if (a[j] &lt; a[i]) {
                swap(a, i, j);
                j++;
            }
            i++;            
        }
        if (j &lt; hi) {
            while (a[j] &lt; a[i]) {
                swap(a, i, j);
                i++;
            }
        }
    }

    private void swap(int[] a, int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
</code></pre>

<p>Finally, the tests I wrote while working this out:</p>

<pre><code>public void testEmpty() {
    int [] a = new int[0];
    merge(a, 0, 0, 0);
    assertEquals(0, a.length);
}

public void testSingleValue() {
    int [] a = new int[] { 1 };
    merge(a, 0, 0, 1);
    assertArraysEqual(new int[] { 1 }, a);
}

public void testTwoValuesRequiringNoSwap() {
    int [] a = new int[] { 1, 2 };
    merge(a, 0, 1, 2);
    assertArraysEqual(new int[] { 1, 2 }, a);
}

public void testTwoValuesRequiringSwap() {
    int [] a = new int[] { 2, 1 };
    merge(a, 0, 1, 2);
    assertArraysEqual(new int[] { 1, 2 }, a);
}

public void testSimpleInterleavedMerge() {
    int [] a = new int[] { 1, 3, 2, 4 };
    merge(a, 0, 2, 4);
    assertArraysEqual(new int[] { 1, 2, 3, 4 }, a);
}

public void testMergeOfSubset() {
    int [] a = new int[] { 1, 3, 2, 4, 6, 5 };
    merge(a, 0, 2, 4);
    assertArraysEqual(new int[] { 1, 2, 3, 4, 6, 5 }, a);
}

public void testMergeOfAllEqual() {
    int [] a = new int[] { 1, 1, 1, 1 };
    merge(a, 0, 2, 4);
    assertArraysEqual(new int[] { 1, 1, 1, 1 }, a);
}

public void testMergeAllFromRight() {
    int [] a = new int[] { 3, 4, 1, 2 };
    merge(a, 0, 2, 4);
    assertArraysEqual(new int[] { 1, 2, 3, 4 }, a);
}

public void testMergeAllFromLeft() {
    int [] a = new int[] { 1, 2, 3, 4 };
    merge(a, 0, 2, 4);
    assertArraysEqual(new int[] { 1, 2, 3, 4 }, a);
}

public void testMergeUnevenNumber() {
    int [] a = new int[] { 3, 1, 2 };
    merge(a, 0, 1, 3);
    assertArraysEqual(new int[] { 1, 2, 3 }, a);
}

public void testMergeLargerList() {
    int [] a = new int[] { 5, 6, 7, 1, 2, 3, 4 };
    merge(a, 0, 3, 7);
    assertArraysEqual(new int[] { 1, 2, 3, 4, 5, 6, 7 }, a);
}
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Counting Unique Digits</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2009/08/counting-unique-digits.html" />
    <id>tag:noctilucent.org,2009:/blog//1.124</id>

    <published>2009-08-19T01:50:56Z</published>
    <updated>2009-08-19T03:42:36Z</updated>

    <summary><![CDATA[Here's a way to count the unique digits in a number using a mostly functional style. There's an API method, count_unique_digits: def count_unique_digits(n) if n &lt; 0 raise Exception.new("can only handle numbers &gt;= 0") end return count_unique_digits_iter([], 0, n) end...]]></summary>
    <author>
        <name>Christian</name>
        
    </author>
    
        <category term="Misc" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>Here's a way to count the unique digits in a number using a mostly functional style.  There's an API method, <code>count_unique_digits</code>:</p>

<pre><code>def count_unique_digits(n)
  if n &lt; 0
    raise Exception.new("can only handle numbers &gt;= 0")
  end
  return count_unique_digits_iter([], 0, n)
end
</code></pre>

<p>This calls the main method, <code>count_unique_digits_iter</code>.  This is recursive, passing intermediate results as parameters to itself.</p>

<pre><code>def count_unique_digits_iter(num_array, count, n)
  new_digit = n % 10
  new_digit_unique = ! num_array.include?(new_digit)
  increment = new_digit_unique ? 1 : 0
  if n &lt; 10
    return count + increment
  end
  if new_digit_unique
    num_array.push(new_digit)
  end
  return count_unique_digits_iter(num_array, count + increment, n/10)
end
</code></pre>

<p>Given the methods, here's a method to count how often digits repeat in all the integers in a range:</p>

<pre><code>def build_count_map(range)
  count_map = Hash.new(0)
  for i in range
    old_count = count_map[count_unique_digits(i)]
    count_map[count_unique_digits(i)] = old_count.succ
  end
  count_map
end
</code></pre>

<p>This counts all the digit repetitions of four digit numbers</p>

<pre><code>count_map = build_count_map(1000 .. 9999)
for count in count_map.keys.sort
  print "#{count}: #{count_map[count]}\n"
end
</code></pre>

<p>And here's the output:</p>

<pre><code>1: 9
2: 567
3: 3888
4: 4536
</code></pre>

<p>(In the first version of this post, I omitted the unit tests.)  Instead of a test framework, I used a homebrew checking method:</p>

<pre><code>def check_method(method, input, expected)
  if self.send(method, input) != expected
    raise Exception.new("#{method}(#{input}):\n" +
      "expected " + expected.inspect +
      " but got " + self.send(method, input).inspect + "\n")
  end
end
</code></pre>

<p>Which made it easy to plug in tests for <code>count_unique_digits</code></p>

<pre><code>def check_digits(input, expected)
  check_method(:count_unique_digits, input, expected)
end

check_digits(0, 1)
check_digits(1, 1)
check_digits(10, 2)
check_digits(11, 1)
check_digits(123, 3)
check_digits(999, 1)
check_digits(1000, 2)
</code></pre>

<p>and tests for <code>build_count_map</code></p>

<pre><code>def check_count_map(input, expected)
  check_method(:build_count_map, input, expected)
end

check_count_map(0 .. 0, {1 =&gt; 1})
check_count_map(0 .. 1, {1 =&gt; 2})
check_count_map(10 .. 20, {1 =&gt; 1, 2 =&gt; 10}) # only 11 has no repeated digits
check_count_map(10 .. 99, {1 =&gt; 9, 2 =&gt; 81}) # 11, 22, 33, ..., 99 are the doubles
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>An Alternative to Boolean Parameters</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2008/09/an-alternative-to-boolean-parameters.html" />
    <id>tag:noctilucent.org,2008:/blog//1.123</id>

    <published>2008-09-14T17:25:20Z</published>
    <updated>2010-02-01T02:11:35Z</updated>

    <summary><![CDATA[I'm always uneasy when I see boolean parameters, particularly in a public method signature.&nbsp; I think they're a minefield for misunderstanding because they're so information poor.&nbsp; Really, it's one bit of information, which is good for computers but terrible for...]]></summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[<p>I'm always uneasy when I see boolean parameters, particularly in a public method signature.&nbsp; I think they're a minefield for misunderstanding because they're so information poor.&nbsp; Really, it's one bit of information, which is good for computers but terrible for people.&nbsp; Until recently, I've always thought in terms of creating two methods for each boolean parameter.&nbsp; Sometimes this is good but sometimes not really.<br /><br />Yesterday, I came across a suggestion in <a href="http://java.sun.com/docs/books/effective/">Effective Java (2nd Ed.)</a> that I like: use Java 5 enums instead of booleans.  Two advantages</p>


<ol>
<li>the enum values can be made much more readable than true or false</li>
<li>the values can be extended if there are more than two scenarios in future</li>
</ol>

]]>
        
    </content>
</entry>

<entry>
    <title>Off the Index, Yay!</title>
    <link rel="alternate" type="text/html" href="http://noctilucent.org/blog/2008/09/off-the-index-yay.html" />
    <id>tag:noctilucent.org,2008:/blog//1.122</id>

    <published>2008-09-14T17:19:29Z</published>
    <updated>2010-04-10T15:59:23Z</updated>

    <summary><![CDATA[From what I can tell, this site no longer features in the big G's index, which means that my resume and this blog can no longer be found through a search.&nbsp; There's a sad side to this, because it means...]]></summary>
    <author>
        <name>Christian</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://noctilucent.org/blog/">
        <![CDATA[From what I can tell, this site no longer features in the big G's index, which means that my resume and this blog can no longer be found through a search.&nbsp; There's a sad side to this, because it means that my old posts, that some people did find helpful, can no longer be found.&nbsp; I don't think this is a big deal because, with the size and variety of the worldwide web, answers to questions can be found elsewhere.&nbsp; Besides, some of those posts are dated in terms of technology.&nbsp; I no longer use it and I doubt others do.<br /><br />The happy side is that I get to write what I want when I want without fearing an audience.&nbsp; This site may or may not get back into the index.&nbsp; (I suspect that upgrading the blog software and the associated churn probably caused a few dings, which wouldn't have helped after not adding any new non-content for a couple of years.)&nbsp; It matters not, one way or the other.&nbsp; The main thing for me is to get unblocked and not being in the index, I feel I have breathing room.<br /> ]]>
        
    </content>
</entry>

</feed>
