<?xml version="1.0"?>
<!-- name="generator" content="blosxom/2.0" -->
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">

<rss version="0.91">
  <channel>
    <title>Mike Schaeffer's Weblog   </title>
    <link>http://www.mschaef.com/blog</link>
    <description>Mike Schaeffer's Weblog</description>
    <language>en</language>

  <item>
    <title>A Better Workflow</title>
    <link>http://www.mschaef.com/blog/2009/09/12#better_workflow</link>
    <description>
It took long enough, but finally, I've taken the time to set up
a better workflow for this blog:

&lt;ul&gt;
&lt;li&gt;The master copy of the blog contents is no longer on the server. It's
    now on one of my personal machines.
&lt;li&gt;&lt;s&gt;I'm managing site history using &lt;a href=&quot;http://www.git-scm.com/&quot;&gt;&lt;tt&gt;git&lt;/tt&gt;
   &lt;/a&gt;.&lt;/s&gt; This was a nice idea, but &lt;tt&gt;git&lt;/tt&gt; and 
   &lt;a href=&quot;http://www.blosxom.com/&quot;&gt;&lt;tt&gt;blosxom&lt;/tt&gt;&lt;/tt&gt; have a fundamental difference
   of opinion on the importance of file datestamps. &lt;tt&gt;blosxom&lt;/tt&gt; relies on datestamps
   to assign dates to posts and &lt;tt&gt;git&lt;/tt&gt; deliberately updates datestamps to work with
   build systems. There are ways to reconcile the two, but it's not worth the time right now.
&lt;li&gt;Uploads to the server are done with
    &lt;a href=&quot;http://www.samba.org/rsync/&quot;&gt;&lt;tt&gt;rsync&lt;/tt&gt;&lt;/a&gt; invoked through
    a makefile. (ssh's public key authentication makes this blazingly fast and easy.)
&lt;/ul&gt;

Maybe now, I'll finally get around to writing a little more. &lt;i&gt;(Or, I could
investigate incorporating &lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;
Markdown&lt;/a&gt;, or the &lt;a href=&quot;http://baselinecss.com/&quot;&gt;Baseline CSS Framework&lt;/a&gt;,
or....)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fthis_blog%2Fbetter_workflow.txt;title=A%20Better%20Workflow%0D&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/this_blog/better_workflow.txt&amp;amp;title=A Better Workflow&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>iPhone</title>
    <link>http://www.mschaef.com/blog/2009/08/05#ten_months_with_an_iphone</link>
    <description>
I've been meaning to write this for months... after switching to an
iPhone last October I have some thoughts on the transition away from
Windows Mobile. Most of my detailed comments are complaints, so before
I continue, it's worth saying that I do think the iPhone is the best
smart phone you can buy. It is, by far, the best answer the industry
has come up with for this class of device. That said, it's more fun
(and potentially useful) to complain:

&lt;ul&gt;

&lt;li&gt; &lt;b&gt;Touch Screen&lt;/b&gt; - I remember shopping with my parents for a
car in the late 80's. One of the cars we looked at was a Buick Riveria
with a &lt;a href=&quot;http://en.wikipedia.org/wiki/File:Buick-TouchScreen-x.jpg&quot;&gt;
touch screen in the center console&lt;/a&gt;. It was cool, but since it lacked
tactile feedback, you had to be looking at it to use it. Flash forward 23
years, and you can replicate this experience in the palm of your hand,
for better or for worse.

&lt;li&gt; &lt;b&gt;'Ambient Information'&lt;/b&gt; - The phone does a poor job of
making inforation ambiently available. To see your next appointment,
you need to open the Calendar unless the reminder has already
displayed. (This could go on the home page.) To be notified of a new
e-mail, you need to unlock the phone and look at the home page. (This
could be a LED on the case.) As notifications build up, they wind up
truncated and incomplete, presumably so they can fit in an
artificially small box on the screen.

&lt;li&gt; &lt;b&gt;Portrait/Landscape&lt;/b&gt; - I wake up in the morning and want to
check e-mail before I get up.. I grab the phone off the nightstand,
look at the display, and it... switches to landscape mode. I'm driving
down the road and want to skip a track, so I grab the phone (eyes on
the road), put my finger in the general area where the 'forward'
button is, and it... switches to landscape mode. Landscape is useful
when you need it, and a usability menace when you don't. There needs
to be better control over when it engages and when it doesn't. (In
this case, physical buttons for skipping forward and backward among
tracks might be nice too... Buick ultimately dropped the touch screen
entirely, and modern cars with navigation tend to also offer physical
controls for key functions.)

&lt;li&gt; &lt;b&gt;e-Mail&lt;/b&gt; - I have two e-mail accounts set up on my phone:
personal and business. It takes five taps to switch between them. A
unified view would be nice. (A list of the union of all inboxes,
color-coded by in-box). An easier way to pick an in-box would be
almost as nice.

&lt;li&gt; &lt;b&gt;Large e-mails&lt;/b&gt; - By default, large e-mails are only
partially downloaded to the phone and there's a button at the bottom of
a one of these mails that lets you download the rest. Of course, once it
does, it then zips you back to the top of the mail, so you have to
manually scroll through the (remember, it's large) e-mail to get to where
you were reading. Argh.

&lt;li&gt; &lt;b&gt;Latency&lt;/b&gt; - Maybe a 3GS would fix this, but the phone seems
very slow to change modes and update the display. I find myself
continually waiting split-seconds for the thing to animate the transition
from one display to the next. I'm asking a lot here, but I don't care...
I use the thing most waking hours of most days.

&lt;li&gt; &lt;b&gt;App Store Rejections&lt;/b&gt; - This is a problem, it sucks for app
developers, and it won't matter to the success of the platform. The
vast majority of customers will never hear that Apple censored a
dictionary (!), and even if they did, it won't stop them from buying.
In the short term, my guess is that Apple will make whatever minimal
changes it needs to make to keep developers quiet &lt;i&gt;enough&lt;/i&gt;, and
the iPhone will continue to do very well.  Phone buyers don't care
enough about choice, and App developers will tend to always want to
code for the platform where they have the best shot at making money,
which is currently the iPhone.  In the long term, my guess is that a
lot more of this content will wind up on mobile web sites than through
the store. After all, a website can be an icon on the home page, avoid
the risk of Apple's rejecton, and also get to run on Android, Pre, and
Windows Mobile.

&lt;li&gt; &lt;b&gt;App Store&lt;/b&gt; - 25,000 applications on the site, and I might
look at 10 or 20 before deciding to make a purchase. The way the store
presents applications (controlled by Apple) has a huge impact on which
apps succeed and which apps fail. Even if the rejection problem
magically goes away, Apple still controls the horizontal and the
vertical. (A lot like Google's control over the fate of websites...)

&lt;li&gt; &lt;b&gt;Keyboard&lt;/b&gt; - After ten months, it's still tedious and
error-prone for me. It works, but just. Apple should provide a
keyboard layout that works like a Blackberry (or even T9) and trades
off multiple letters per key in exchange for larger keys.

&lt;li&gt; &lt;b&gt;Industrial Design&lt;/b&gt; - I love the way the phone looks and
feels, so I wrap it in a tacky add on case to 'protect it'. So does
most everybody else. Last I heard, good design was about making a
product that looks good &lt;b&gt;and&lt;/b&gt; works well. The rampant sales of
cases implies to me that something is missing with the 'works well'
part of that equation.

&lt;/ul&gt;

I do like the thing, and I wouldn't switch away, but it's far from
perfect. Let's hope it gets better.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fapple%2Ften_months_with_an_iphone.txt;title=iPhone&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/apple/ten_months_with_an_iphone.txt&amp;amp;title=iPhone&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Would you look at that...</title>
    <link>http://www.mschaef.com/blog/2009/04/16#linux-haters-blog-2</link>
    <description>
&lt;br&gt;

...the &lt;a href=&quot;http://linuxhaters.blogspot.com/&quot;&gt;Linux Hater&lt;/a&gt; is back....
&lt;a href=&quot;http://mobile.slashdot.org/article.pl?sid=09/04/04/228240&quot;&gt;and OpenMoko&lt;/a&gt; is not.

&lt;br&gt;&lt;br&gt;

I can't say that either of these things suprises me.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Flinux%2Flinux-haters-blog-2.txt;title=Would%20you%20look%20at%20that...&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/linux/linux-haters-blog-2.txt&amp;amp;title=Would you look at that...&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Why Lisp?</title>
    <link>http://www.mschaef.com/blog/2009/04/16#why_lisp</link>
    <description>
I recently was asked why I like Lisp. For me, it boils down to
the fact that Lisp makes it easy to control when your code is
evaluated. Most languages only let you evaluate code at
runtime. There are ways around this (C++ templates, &lt;tt&gt;cpp&lt;/tt&gt;,
code generation, etc.), but they all have severe limitations. In
contrast, Lisp makes it easy to run actual Lisp code at compile
time (macros) or even read time (reader macros). Combine that
with the fact that Lisp code is pretty easy to manipulate with
Lisp itself, and it becomes much easier to do things that are
usually restricted to language developers, which can be quite a
force multiplier. Just to illustrate, most of the language
features that C# has over Java (LINQ, properties, closures,
lambda syntax, &lt;tt&gt;yield return&lt;/tt&gt; etc.) could be added to Java
by 'ordinary developers' if Java somehow had these things I like
so much about Lisp.

&lt;br&gt;&lt;br&gt;

&lt;i&gt;But it doesn't...&lt;/i&gt;

&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Flisp%2Fwhy_lisp.txt;title=Why%20Lisp%3F&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/lisp/why_lisp.txt&amp;amp;title=Why Lisp?&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Experience and Dogma</title>
    <link>http://www.mschaef.com/blog/2009/02/12#experience_and_dogma</link>
    <description>
In the recent debate surronding the &lt;a
href=&quot;http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod&quot;&gt;SOLID
Principles&lt;/a&gt; of Object Oriented Design, the following two quotes
stood out.

&lt;br&gt;&lt;br&gt;

&lt;i&gt;&quot;Last week I was listening to a podcast on Hanselminutes, with Robert
Martin talking about the SOLID principles. ... And, when I was
listening to them, they all sounded to me like extremely bureaucratic
programming that came from the mind of somebody that has not written a
lot of code, frankly.&quot;

&lt;br&gt;&lt;br&gt;

&amp;mdash; &lt;a href=&quot;http://www.joelonsoftware.com/items/2009/01/31.html&quot;&gt;Joel Spolsky&lt;/a&gt;&lt;/i&gt;

&lt;br&gt;&lt;br&gt;

&lt;i&gt;&quot;Reading The Ferengi Programmer by Jeff Atwood really made me quite
concerned. Here.s clearly an opinion which to me seems not grounded in
sustained experience...&quot;

&lt;br&gt;&lt;br&gt;

&amp;mdash; &lt;a href=&quot;http://blog.dhananjaynene.com/2009/02/an-experienced-programmer-doesnt-use-solid-as-a-checklist-he-internalises-it/&quot;&gt;Dhananjay Nene&lt;/a&gt;&lt;/i&gt;

&lt;br&gt;&lt;br&gt;

Both of these are speculative slights on someone else's experience
level, either generally or with a particular bit of technology. Bad
rhetorical technique aside, my guess is that these are rooted in a
fundamental lack of trust that the other side might actually have a
well thought out reason for their point of view. This is an easy trap
to fall into, particularly in a field as subjective as software
design. Take the 'editor wars' as an example: which is better, Emacs,
vi, or a full featured IDE? I don't know the answer to this question,
but I do know that I can find people that will tell me I'm wrong for
prefering Emacs. Change the debate to something a bit more relevant,
something like the design of a large piece of software, and people get
even more vitriolic.

&lt;br&gt;&lt;br&gt;

At least part of the solution to this problem is plain, old trust. 
Think about a good developer that's moved into a lead role: it's easy 
to see how they might care enough about a particular design point to 
impose that on their team, either by implementing it themselves or by 
dictate. Where the trust comes in is in avoiding that trap. If I 
impose a choice on my team, I limit their ability to explore the 
design space themselves, take their own risks, and then potentially 
fail.  I also limit their ability to correct my own misconceptions... 
if I think I'm right enough to mandate a design, I also probably 
think I'm right enough to ignore you and do my own thing anyway. 
Ironically enough, this makes the combination of conviction and risk 
aversion its own risk, and potentially a big one without a 
counterbalance.  (From a personal level, if you go around imposing 
your will and/or ignoring points of view, you also lose the 
opporunity to learn from those around you.)

&lt;br&gt;&lt;br&gt;

And this is where the bit about rhetorical technique comes into play. 
As satisfying as it can be to say that somebody you disagree with 
&lt;i&gt;&quot;...has not written a lot of code, frankly.&quot;&lt;/i&gt;, it's really 
beside the point. It doesn't matter, even were it true. What matters 
more to reasonable discussions about engineering technique are 
specific and testable statements: something like &quot;Interface 
Segregation will help keep defect rates by promoting better unit 
tests.&quot; You may or may not agree with this statement, but it's more 
likely to lead to a relevant conversation than slights on experience 
or dogmatic declarations of opinion as fact. Several years ago I was 
told in no uncertain terms that I had made a design choice that 
'wasn't scalable'. I ran some tests and came back with some numbers 
that showed my choice satisfied our requirements. Who do you think 
won that debate, the buzzword or the numbers? Specifics and 
testability can count for a lot. Dogma, not so much.
 
&lt;br&gt;&lt;br&gt;

To be fair, most of the two blog posts I mention above are focused on 
meatier material than my quotes imply. I particularly liked Atwood's 
conclusion that &lt;i&gt;&quot;Rules, guidelines, and principles are gems of 
distilled experience that should be studied and respected. But 
they're never a substute [sic] for thinking critically about your 
work.&quot;&lt;/i&gt; For experienced developers, I expect that Nene would also 
agree. After all, he writes that &lt;i&gt;&quot;you have the experience on your 
side to generally make the right judgement calls and you are likely 
to anyway apply them under most of the cases.&quot;&lt;/i&gt; In a sense, both 
are arguing the same thing, namely that judgement ultimately drives 
the design process over strict adherence to a set of rules. The 
difference is that Nene takes it a few steps further and draws the 
conclusion that good developers produce good code, good code is 
SOLID, and Atwood's blog post is either useless or harmful. Maybe 
there are some valid points here, but they're obscured by a dogmatism 
that is more of a distraction than a productive way to think about 
software design.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fprogramming%2Fexperience_and_dogma.txt;title=Experience%20and%20Dogma&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/programming/experience_and_dogma.txt&amp;amp;title=Experience and Dogma&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>The End of 16-bit Windows</title>
    <link>http://www.mschaef.com/blog/2008/11/06#windows-31-end-of-life</link>
    <description>
In an era in which customers are almost begging Microsoft not to
discontinue Windows XP, I was suprised to see &lt;a
href=&quot;http://arstechnica.com/news.ars/post/20081105-microsoft-puts-windows-3-11-for-workgroups-out-to-pasture.html&quot;&gt;a
recent news story&lt;/a&gt; on the end of life of Windows for Workgroups
3.11 (WfWG).  If you're not completely up on the early history of
Windows, WfWG 3.11 was released in August of 1993, and was the last of
the major US-market versions of Windows without native Win32 support
out of the box. It was also one of a series of Windows releases in the
early 90's that turned Windows from 'the library you need to run
Excel' into a legitimate platform for general purpose computing.

&lt;br&gt;&lt;br&gt;

From it's introduction in 1985 until the release of Windows 3.0 in 1990, Windows was almost 
entirely composed of the same basic core: DOS for file access and system startup, and a 
collection of three DLL's (KERNEL, GDI, and USER) for memory management, device independant 
graphics, and the GUI widget library and window manager.  Atop the core sat programs 
written to the Windows API. All of this ran sharing the one 20-bit segmented address space 
provided by x86 real mode: with 640K usable memory.  If you were lucky, you might have had 
a LIM/EMS board that allowed a few MB of extra memory to be addressed through a 64KB window 
at the top of the addres space. If you were &lt;b&gt;really&lt;/b&gt; lucky, you might have had a 80386 
computer with a special program that let it pretend its extra memory worked like a LIM/EMS 
board. Needless to say, memory was tight, difficult to use, and dangerous to share it 
between multiple programs.

&lt;br&gt;&lt;br&gt;

The solution to this memory problem was initially to be OS/2. OS/2 was the operating system 
part of IBM's vast (and doomed) PS/2 program to recapture the PC space back from clone 
vendors. Like DOS, it was done in partnership with Microsoft, but IBM took a much more 
active role in the design and development of OS/2 than they did with DOS.  OS/2's most 
noteworthy feature was the fact that it was designed to run in 80286 'protected mode' 
rather than the 'real mode' of DOS and Windows. Protected mode, like its name implies, 
added memory protection between processes that made multi-tasking more reliable. Protected 
mode also widened the physical address space of the CPU from 20-bits to 24-bits, making it 
possible to directly address 16MB of memory without resorting to tricks like LIM/EMS 
paging. This was all good, but it was tempered by the fact that OS/2 was expensive to run 
and didn't run DOS programs very well, thanks to its choice of 80286 protected mode over 
80386. The only programs that could actually use the benefits of protected mode under OS/2 
were OS/2-specific software that nobody had.

&lt;br&gt;&lt;br&gt;

By the time 1988 rolled around, PC's with the capability of addressing more than 1MB of 
memory had been around since 1984, and there still wasn't a viable mainstream operating 
system that took advantage of this capability. This is when Windows got its big break: 
David Weise at Microsoft &lt;a 
href=&quot;http://blogs.msdn.com/larryosterman/archive/2005/02/02/365635.aspx&quot;&gt;figured out how 
to run Windows itself in Protected Mode&lt;/a&gt;, &lt;i&gt;along with unmodified Windows programs&lt;/i&gt;. 
Running existing software in protected mode was something of a holy grail, and Dr. Weise's 
idea ultimately resulted in Windows 3.0, released in 1990 to heady acclaim. Windows 3.0 
also included the V86 multitasker from the older Windows/386 product. This meant Windows 
3.0 could do things OS/2 could not do, like run multiple DOS programs at the same time and 
run them in graphical windows on the desktop.

&lt;br&gt;&lt;br&gt;

Windows 3.0 ended up being a runaway sales success, and after its release, the rest of the 
dominos fell fairly quickly. Microsoft's partnership with IBM effectively ended, with IBM 
getting a source licence to Microsoft products through the early 1990's. IBM ultimately 
used this license to develop a special version of Windows they bundled with OS/2 2.0 to let 
Windows programs run under OS/2 (&quot;a better Windows than Windows&quot; went the ad). Microsoft's 
own 32-bit OS/2 2.0 got dropped, and the work done on OS/2 NT (3.0) ultimately formed the 
basis for 1993's Windows NT and the Win32 API. The next version of 16-bit Windows, Windows 
3.1, dropped support for real mode entirely, and as it evolved into Windows 95, more and 
more system services were moved into 32-bit code. This 16/32-bit hybrid version of Windows 
lasted until Windows Me.  It was definately barouque, and ended up notoriously unreliable, 
but its evolution from 256K 8088's to 128MB Pentiums is to my eye one of the more 
impressive examples of evolutionary software engineering. I don't miss using these versions 
of Windows, but it's easy to miss the 'brave new world' spirit they embodied.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fhistory%2Fwindows-31-end-of-life.txt;title=The%20End%20of%2016-bit%20Windows&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/history/windows-31-end-of-life.txt&amp;amp;title=The End of 16-bit Windows&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Macintosh vs. PC Pricing, and missing the point.</title>
    <link>http://www.mschaef.com/blog/2008/08/18#mac_vs_pc_pricing_and_openness</link>
    <description>
Harry McCracken just wrote &lt;a 
href=&quot;http://technologizer.com/2008/08/14/are-macs-more-expensive-lets-do-the-math-once-and-for-all/&quot;&gt; 
a bit&lt;/a&gt; comparing the price of PC's to Macintosh's. Like most of these 
guys, he misses the point. Consider his methodology: &lt;i&gt;&quot;I chose a 
standard [Apple] MacBook configuration...Then I configured laptops as 
similarly as possible from the country's two largest PC 
manufacturers&quot;&lt;/i&gt;. The problem is that this methodology takes the set 
of Apple machines to be the set of valid configurations for comparison, 
excluding configurations that Apple does not offer. Just for the sake of 
a more full comparison, what does a MacBook cost with these 
configurations?

&lt;ul&gt;
&lt;li&gt;A TrackPoint.
&lt;li&gt;A numeric keypad.
&lt;li&gt;Two internal batteries.
&lt;li&gt;Two internal mouse buttons.
&lt;li&gt;A swappable drive bay.
&lt;li&gt;A docking station.
&lt;li&gt;A calibrated, high-gamut display and a digitizer.
&lt;li&gt;A display smaller than 13&quot; or bigger than 17&quot;.
&lt;li&gt;No keyboard.
&lt;li&gt;A convertable tablet configuration.
&lt;li&gt;Embedded on a PXI card.
&lt;liThe absolute highest performance.
&lt;li&gt;The absolute minimum cost.
&lt;/ul&gt;

Of course, none of these configurations are available from Apple. If you
need or want one of these options, you can't get it at any price from 
Apple. Similar comparisons can be made in the server and desktop PC 
spaces. 

&lt;br&gt;&lt;br&gt;

This is an unsuprising result. When you enlarge the playing field beyond 
Apple's relatively limited reach, it becomes even more apparant that 
these comparisons aren't 'Apple vs. PC' what they really are is 'Apple 
vs. The Entire Computer Industry'. Apple doesn't have the capability, 
desire, or brand to fare well in such a comparison: There are just too 
many market segments they don't address. Addressing all of these 
segments would leave them with a confusing product line, a highly taxed 
engineering group, and a muddled brand image.

&lt;br&gt;&lt;br&gt;

Part of the value of the PC platform is that it not subject to the 
limitations of being confined to one highly image-sensitive company. 
Part of the value of the PC is that it allows other vendors to enlarge 
the platform into new segments. Missing out on this is one of the costs 
of picking an Apple that is missing in most comparisons, including 
McCracken's.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fapple%2Fmac_vs_pc_pricing_and_openness.txt;title=Macintosh%20vs.%20PC%20Pricing%2C%20and%20missing%20the%20point.&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/apple/mac_vs_pc_pricing_and_openness.txt&amp;amp;title=Macintosh vs. PC Pricing, and missing the point.&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>The Linux Hater's Blog</title>
    <link>http://www.mschaef.com/blog/2008/08/12#linux-haters-blog</link>
    <description>
I have a new favorite blog, the &lt;a
href=&quot;http://linuxhaters.blogspot.com/&quot;&gt;Linux Hater's Blog&lt;/a&gt;. Some
anonymous Linux user has taken it upon himself to open a blog
dedicated to all of the many reasons why desktop Linux sucks (which it
does). While it's more than a little mean-spirited, this blog is the
dissenting voice of Linux. It is the conscience that, if heeded, will
make the Linux desktop a better place to work.

&lt;br&gt;&lt;br&gt;

For all of the problems with Linux, it is also the one major platform
that allows the motivated individual or company to actually address
those problems. The single biggest difference between the Linux
Hater's Blog and the (would-be) Windows and MacOS X Hater's Blogs is
that on the Linux blog, it's actually possible to do something about
the problems. Consider this: 18 years ago, there was no Linux, 12
years ago, there was no Gnome. In 1990, the Linux Hater's blog would
have one post: &lt;i&gt;&quot;It doesn't exist, go buy Windows.&quot;&lt;/i&gt; The reason I
mention this is that while it's easy to dismiss the benefits of open
source as purely theoretical (i.e.: &lt;i&gt;&quot;Have &lt;b&gt;you&lt;/b&gt; ever needed to
recompile your kernel?&quot;&lt;/i&gt;), the benefits of open source are the
entire reason it exists at all.

&lt;br&gt;&lt;br&gt;

To look at this in a bit more depth, consider the gnome-panel as an
example. Based on the copyright claims in the source code, gnome-panel
is itself a collaboration of &lt;a
href=&quot;http://en.wikipedia.org/wiki/Eazel&quot;&gt;Eazel&lt;/a&gt;, &lt;a
href=&quot;http://primates.ximian.com/~miguel/helix-history.html&quot;&gt;Helix
Code&lt;/a&gt;/Ximian/Novell, &lt;a href=&quot;http://www.sun.com/&quot;&gt;Sun
Microsytems&lt;/a&gt;, &lt;a href=&quot;http://www.redhat.com&quot;&gt;Red Hat&lt;/a&gt;, &lt;a
href=&quot;http://www.fsf.org&quot;&gt;The Free Software Foundation&lt;/a&gt;, &lt;a
href=&quot;http://ian.mckellar.org/&quot;&gt;Ian McKellar&lt;/a&gt;, James Wilcox, Rob
Adams, &lt;a href=&quot;http://live.gnome.org/VincentUntz&quot;&gt;Vincent Untz&lt;/a&gt;,
and &lt;a href=&quot;http://carlosgc.linups.org/&quot;&gt;Carlos Garcia
Campos&lt;/a&gt;. All of these contributors found things to change or fix,
'itches to scratch', and all of them changed or fixed the
gnome-panel. This is something that basically cannot happen in the
model of closed source software. If you want to change something in
MacOS X, you basically have three options: try to convince Apple it is
a worthwhile change by trying to present (giving up the rights to) a
business case justifying the feature, try to go to work for Apple in
the right group and convince them to let you implement your feature,
or reimplement the entire thing yourself.

&lt;br&gt;&lt;br&gt;

As a result of these kinds of trade offs, cross-organization collaboration 
in closed source is a lot harder to come by than in open source. Closed 
source essentially divides the stakeholders in a piece of software into 
two groups: those that can take responsibility for the softawre by making 
changes, and those that cannot and must either accept the changes as 
provided or work around them. In that sense, Free Software is the 
licencing model that brings to software the democratic ideals of personal 
responsibility and the sovereignty of the people. Like any democracy, in 
the short term it will have issues compared to more centralized forms of 
planning, but in the long term it will be a much more vibrant and 
productive place to be. This is also why the Linux Hater's Blog is so very 
important. To see why, continue the analogy with democracy a bit, and 
consider the process by which the United Stated adopted its constitution.

&lt;br&gt;&lt;br&gt;

After the U.S. Constitutional Convention in Philadelphia, there came the 
long and highly political process of states ratifying new form of 
government.  During this two year long debate, there were a series of 
papers, the Federalist Papers, written in support of the proposed 
Constutition. Less well known are the Anti-Federalist papers, a series of 
dissenting arguments &lt;i&gt;against&lt;/i&gt; ratification. This dissent primarily 
centered around the lack of a Bill of Rights, and ultimatly led to the 
incorporation of a Bill of Rights as the first ten amendments to the 
constitution. The dissent was not just criticism: open process and free 
debate allowed it to be a key part of the construction of the 
Constitution.

&lt;br&gt;&lt;br&gt;

This is a much grander version of what the Linux Hater's blog can do for 
Linux. By dissenting against the idea that Linux is already ready for the 
desktop (or the server), it also provides a list of weaknesses to fix.  
Unlike a Windows Hater's Blog, the freedoms of Linux allow this list of 
weaknesses to effectively become a to do list for anyone or any company 
with the motivation and time to do the work. It is therefore not a 
liabilty to Linux, but an asset that derives its value from the freedom at 
the core of Free Software. Ironically enough, because of this, the 'Linux 
Hater' could easily turn out to be one of Linux's best friends.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Flinux%2Flinux-haters-blog.txt;title=The%20Linux%20Hater%27s%20Blog&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/linux/linux-haters-blog.txt&amp;amp;title=The Linux Hater's Blog&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title> Does Openness Matter Anymore?</title>
    <link>http://www.mschaef.com/blog/2008//11#does_openness_really_matter</link>
    <description>
I was born in 1975. In the 'computer world', this means I grew up at
the tail end of the 8-bit era. By the time I was a teenager the market
was in the middle of deciding whether to go with PC's, the Apple
Macintosh, or &lt;a
href=&quot;http://en.wikipedia.org/wiki/DESQview#DESQview.2FX&quot;&gt;something
else&lt;/a&gt;. Microsoft basically cinched that deal in 1990 with the
release of &lt;a href=&quot;http://en.wikipedia.org/wiki/Windows_3.0&quot;&gt;Windows
3.0&lt;/a&gt;, the first relevant version. A PC running Windows 3.0 wasn't
as nice as a Macintosh, but it didn't matter. If you already had a PC,
you could buy Windows off the shelf for $89, retain all of your
existing hardware and software, and then experiment with the GUI when
you had the time. If typing &lt;tt&gt;win&lt;/tt&gt; at a DOS prompt took you down
the rabbit hole, clicking 'Exit Windows' took you right back to your
comfort zone.

&lt;br&gt;&lt;br&gt;

Windows 3.0 also had the benefit of a huge installed base of latent
and mostly unused hardware. A typical business PC in 1990 might have
been something like an &lt;a
href=&quot;http://en.wikipedia.org/wiki/Intel_80286&quot;&gt;80286&lt;/a&gt; with 2MB of
RAM, a 40MB disk, and an &lt;a
href=&quot;http://en.wikipedia.org/wiki/Enhanced_Graphics_Adapter&quot;&gt;EGA&lt;/a&gt;
(640x350x4bpp) bitmapped display. It would then be running DOS
software that basically couldn't address more than the first &lt;a
href=&quot;http://en.wikipedia.org/wiki/Conventional_memory&quot;&gt;640K&lt;/a&gt; of
memory, and tf you ever saw the bitmap display in use, it was probably
for a static plot of a graph. Compared to a Macintosh from the same
year, a PC looked positively like something from a totally different
generation. Windows 3.0 changed all this. It allowed you to switch
your 80286 into &lt;a
href=&quot;http://en.wikipedia.org/wiki/Protected_mode&quot;&gt;'Protected
Mode'&lt;/a&gt; to get at that extra memory. It provided a &lt;a
href=&quot;http://en.wikipedia.org/wiki/Graphics_Device_Interface&quot;&gt;graphics
API&lt;/a&gt; (with drivers!) and forced programs to use the bitmapped
display. It provided standard printer drivers that worked for &lt;b&gt;all
Windows programs&lt;/b&gt;. Basically, for $89 it took the hardware you
already had and made it look almost like the Macintosh that would
otherwise have cost you thousands of dollars. It was utterly
transforming.

&lt;br&gt;&lt;br&gt;

Almost 20 years later, the most interesting thing about this is the
relative timing of the hardware and its software support. Most of the
hardware in my 'typical 1990 PC' was introduced by IBM in its 1984
announcement of the &lt;a
href=&quot;http://www.vintage-computer.com/ibmpcat.shtml&quot;&gt;IBM PC AT&lt;/a&gt;.
The first attempt by IBM and Microsoft to support the 80286 natively
came three years later in 1987's release of &lt;a
href=&quot;http://en.wikipedia.org/wiki/OS/2&quot;&gt;OS/2&lt;/a&gt;. The first
286-native platform to reach mainstream acceptance came in 1990. Think
about that: it took 6 years for the open PC market to develop software
capable of fully utilizing the 80286.  The &lt;a
href=&quot;http://en.wikipedia.org/wiki/Intel_80386&quot;&gt;80386&lt;/a&gt; fared even
worse; The &lt;a
href=&quot;http://en.wikipedia.org/wiki/Compaq#Deskpro_386&quot;&gt;first 386
machine&lt;/a&gt; was released in 1986, and it didn't have a major
mainstream OS until either 1993 or &lt;a
href=&quot;http://en.wikipedia.org/wiki/Windows_95&quot;&gt;1995&lt;/a&gt; (depending on
whether or not you count &lt;a
href=&quot;http://en.wikipedia.org/wiki/Windows_NT_3.1&quot;&gt;Windows NT 3.1&lt;/a&gt;
as 'mainstream'). Thus, there were scores of 286 and 386 boxes that
did nothing more than execute 8086 code really, really fast (for the
time :-)). In modern terms, this is analogous to a vendor introducing
a hardware devide today and then delaying software support until 2018.

&lt;br&gt;&lt;br&gt;

This is emblematic of the hugely diminishing value of an open device
platform in today's computer industry. In 1989, using a computer was
largely an exercise in getting the damn thing to work.  When those are
the issues you're worried about as a PC user, an open platform is
helpful because it enables a broader selection of vendors for parts
and software. If you've run out of slots for both your video board and
your bus mouse interface, you can always switch to an ATI video board
with a built-in mouse port. If you need a memory manager that supports
&lt;a href=&quot;http://docs.ruudkoot.nl/vcpi.doc&quot;&gt;VCPI&lt;/a&gt; to enable your &lt;a
href=&quot;http://osdev.berlios.de/v86.html&quot;&gt;V86&lt;/a&gt; multitasker, you can
always switch to something like &lt;a
href=&quot;http://en.wikipedia.org/wiki/QEMM&quot;&gt;QEMM/386&lt;/a&gt;. If you need
more memory to run your spreadsheet, you can go to AST Technolgies and
buy a &lt;a
href=&quot;http://www.borrett.id.au/computing/art-1989-01-02.htm&quot;&gt;LIM/EMS&lt;/a&gt;
board.  When you're worried about these kinds of issues, issues 'low
in the stack', the flexibility of choice provided by openness is
useful enough that you might be more willing to bear the costs of a
market slow to adopt new technologies.

&lt;br&gt;&lt;br&gt;

Of course, price is also a factor.  In 1988, Byte magazine ran a
review of Compaq's Deskpro 386s. This was their first &lt;a
href=&quot;http://www.borrett.id.au/computing/art-1989-01-02.htm&quot;&gt;80386SX&lt;/a&gt;
machine, a desktop computer designed to be a cheaper way to run
80386-specific software. The cost of the review machine was something
like $15,000.  In 2007 dollars, this would buy you a nice, reasonably
late-model BMW 3-series. A year later in 1989, my family bought a
similar machine from  ALR, which cost around $3,000. Thus isn't
nearly as bad, but it's still around $5,200 in 2007, which basically
means that a mid-range 1989 PC is priced at the very top end of the
2007 PC market. With monetary costs that high, that other benefit of
openness, price competition, becomes a much bigger deal. Compaq ended
up suffering badly as competition drove the price of the market to
where it is today.

&lt;br&gt;&lt;br&gt;

In the intervening 20 years, both of these circumstances have changed
dramtically. PC's, both Windows and Macintosh, are well enough
integrated that nothing needs to be done to get them to run aside from
unpacking the box.  &lt;a
href=&quot;http://en.wikipedia.org/wiki/NeXTSTEP&quot;&gt;NeXTStep&lt;/a&gt;, which in
1994 required a fancy $5,000 PC bought from a custom vendor to run
well, will shortly be able to run (with long-range, high-speed
wireless!) on a &lt;a href=&quot;http://www.apple.com/iphone/&quot;&gt;$200&lt;/a&gt;
handheld bought at your local shopping mall. Our industry has moved up
&lt;a
href=&quot;http://en.wikipedia.org/wiki/Maslow%27s_hierarchy_of_needs&quot;&gt;Maslow's
hierarchy of needs&lt;/a&gt; from expensive, unreliable hardware, run by the
dedicated few to cheap, reliable hardware, run by disinterested
many. We can now concentrate on more interesting things than just
getting the computer to work, and tt is with this shift that the some
of the unique value of openness has been lost. Unfortunately, &lt;i&gt;the
costs have been retained&lt;/i&gt;, there is no countervening force in the
market that's forcing open platforms to move any faster.

&lt;br&gt;&lt;br&gt;

Personally, I believe this bodes very well for Apple's latest attempt
to own the smartphone space. There will only be one vendor and one
price for the iPhone, but the platform will be able to move faster to
adopt new technolgies, and integrate them more tightly, because
there's only one kind of hardware to run on. The fewer hardware
configurations and stricter quality control guidelines will make it
easier (and more mandatory) that developers produce high quality
software. The fact that entry into the software market is controlled,
doesn't matter, because there are still more eligable developers than
the platform actually needs. The net result of all this is that Apple,
again, has a product that looks 'next generation', but the pricing and
openness factors that cost them that advantage in the early 90's are
no longer there. It's a good time to be involved in the iPhone,
methinks.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fgeneral%2Fdoes_openness_really_matter.txt;title=%20Does%20Openness%20Matter%20Anymore%3F&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/general/does_openness_really_matter.txt&amp;amp;title= Does Openness Matter Anymore?&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>defmacro and coupling.</title>
    <link>http://www.mschaef.com/blog/2008/04/10#defmacro-coupling</link>
    <description>
A few months ago, I ran into a problem with a macro that seriously
changed my opinions on how they should be used. It all comes down to
the fact that macro are incorporated into compiler output. Two pieces
of code that look nicely decoupled in the source text can end up very
entwined with each other, once they are compiled.

&lt;br&gt;&lt;br&gt;

To illustrate, I'll use the macro in question, something I once used
to accept a sort of simulated 'multiple return value' in a dialect of
Scheme. This is a low level example, something from my hobby work, but
it can apply equally well to other uses of macros.

&lt;pre class=&quot;syntax&quot;&gt;
(defmacro (values-bind form vars . body)
  (with-gensyms (form-rv-sym)
    `(let ((,form-rv-sym ,form))
       (list-let ,vars (if (%values-tuple? ,form-rv-sym)
                           (slot-ref ,form-rv-sym 'v)
                           (list ,form-rv-sym))
         ,@body))))
&lt;/pre&gt;

This macro expands code like this:

&lt;pre class=&quot;syntax&quot;&gt;
(values-bind (returns-2-args 'foo) (arg-1 arg-2)
   (+ arg-1 arg-2))
&lt;/pre&gt;

Into code that looks like this:
&lt;pre class=&quot;syntax&quot;&gt;
(let ((#:form-rv-sym-69@00beeec4 (returns-2-args 'foo)))
   (list-let (arg-1 arg-2) (if (%values-tuple? #:form-rv-sym-69@00beeec4)
                              (slot-ref #:form-rv-sym-69@00beeec4 'v)
                              (list #:form-rv-sym-69@00beeec4))
     (+ arg-1 arg-2)))
&lt;/pre&gt;

And then, the compiler compiles that form and drops the result into
the output file, which now contains several pretty deep assumptions
about the simulated multiple value protocol it needs to honor:

&lt;br&gt;&lt;br&gt;

&lt;list&gt;
&lt;li&gt;Values are returned in a single value that satifies
    &lt;tt&gt;%values-tuple?&lt;/tt&gt;.
&lt;li&gt;Values are extracted from a tuple with a call to &lt;tt&gt;slot-ref&lt;/tt&gt;
    for slot &lt;tt&gt;v&lt;/tt&gt;.
&lt;li&gt;Values are stored within slot as a list.
&lt;/list&gt;

&lt;br&gt;

While the source text that uses &lt;tt&gt;values-bind&lt;/tt&gt; doesn't need to
know any of these details, the compiler output does. This results in
compiler output that is very closely tied to the value protocol;
Compiler output that is likely to be incompatible with any changes to
that protocol.

&lt;br&gt;&lt;br&gt;

In many development scenarios, this doesn't matter.  Within a single
project, if compiled file A comes to depend on assumptions embedded in
macros from file B, it's less of an issue: both files are usually
compiled at the same time. If both files can't be simultaneously
compiled, things start to go wrong. I ran into this issue myself when
trying to change the multiple value protocol I was using in my
compiler. My core library was built with the old protocol, my new
library was to be built with the new protocol, and the two could not
interoperate for the brief period of time necessary to produce a
compiled version of the new library. There are several possible
approaches to solving this, but but one I took was the two step of
building a new 'old' library that can handle &lt;b&gt;both&lt;/b&gt; protocols,
using it to compile a version that works only with the new protocol,
and then switching over completely. It was a mess, and a mess I
created myself with a macro that expanded into something that assumed
way too much. The better approach, the approach that I switched to,
is this:

&lt;pre class=&quot;syntax&quot;&gt;
(define (call-with-values proc vals)
  (apply proc (%values-&gt;list vals)))

(defmacro (values-bind form vars . body)
  `(call-with-values (lambda ,vars ,@body) ,form))
&lt;/pre&gt;

This expands the above code to something more palatable:

&lt;pre class=&quot;syntax&quot;&gt;
(call-with-values (lambda (arg-1 arg-2)
                     (+ arg-1 arg-2))
                  (returns-2-args 'foo))
&lt;/pre&gt;

The only assumption this makes in the compiled output is that there's
a function &lt;tt&gt;call-with-values&lt;/tt&gt; that calls its first argument
with values passed in as its second argument. All of the gory details,
which could easily be the same three from my list, are hidden behind
function calls and dynamic linkage. This is actually the
representation that made the two-step cutover approach
plausible. Switching to this version of the &lt;tt&gt;values-bind&lt;/tt&gt; macro
removed assumptions about the value protocol from every call site, and
made it easy to switch.


&lt;br&gt;&lt;br&gt;

The upshot of this is something that's, I'm sure, pretty common
knowledge in Lisp/Scheme circles: macros are best when limited to
syntax, with the underlying functionality implemented in a more
functional interface. The functional interface keeps things more
decoupled, even when compiled, and leaves your software more
managable. It also provides a second way to 'get at' the
functionality provided by the underlying code. With the function/macro
split, the macro expansionn can be avoided entirely, in the case
when you already have a closure that contains the code you need
to run.
 
&lt;br&gt;&lt;br&gt;

One more brief example, a bit higher up the 'stack' in the
language environment is the transformation of this macro:

&lt;pre class=&quot;syntax&quot;&gt;
(defmacro (with-output-to-string . code)
  (with-gensyms (saved-output-port-sym output-string-sym)
    `(let ((,saved-output-port-sym (current-output-port))
           (,output-string-sym (open-output-string)))
       (unwind-protect (lambda ()
                         (set-current-output-port ,output-string-sym)
                         ,@code
                         (get-output-string ,output-string-sym))
                       (lambda ()
                         (set-current-output-port ,saved-output-port-sym))))))
&lt;/pre&gt;

Into this macro/function pair:

&lt;pre class=&quot;syntax&quot;&gt;
(define (call-with-output-to-string fn)
  (let ((saved-output-port (current-output-port))
        (output-string (open-output-string)))
    (unwind-protect (lambda ()
                      (set-current-output-port output-string)
                      (fn)
                      (get-output-string output-string))
                    (lambda ()
                      (set-current-output-port saved-output-port)))))

(defmacro (with-output-to-string . code)
  `(call-with-output-to-string (lambda () ,@code)))
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Flisp%2Fdefmacro-coupling.txt;title=defmacro%20and%20coupling.&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/lisp/defmacro-coupling.txt&amp;amp;title=defmacro and coupling.&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Renaming SVN Users on Windows</title>
    <link>http://www.mschaef.com/blog/2008/02/22#renaming-svn-users-on-windows</link>
    <description>
The instructions I gave earlier on &lt;a 
href=&quot;http://www.mschaef.com/blog/tech/programming/renaming-svn-users.html&quot;&gt;Renaming 
SVN Users&lt;/a&gt; work only when the SVN repository is hosted on a machine that can run 
SVN hooks written in Unix style shell script. On a conventional Windows machine, one 
without Cygwin, MSYS, or similar, you have to switch to writing hooks in something 
like Windows batch language. 

&lt;br&gt;&lt;br&gt;

If all you want to do is temporarily rename users, then you can just create an empty 
file named &lt;tt&gt;pre-revprop-change.cmd&lt;/tt&gt; in your repository under &lt;tt&gt;hooks\&lt;/tt&gt;. 
The default return code from a batch file is success, which SVN interprets as a 
&lt;b&gt;all&lt;/b&gt; revision 
property changes, all the time, by anybody. If you want to implement an actual policy, 
Philibert Pérusse has posted a &lt;a 
href=&quot;http://svn.haxx.se/users/archive-2006-03/0107.shtml&quot;&gt;template script&lt;/a&gt; online.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fprogramming%2Frenaming-svn-users-on-windows.txt;title=Renaming%20SVN%20Users%20on%20Windows&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/programming/renaming-svn-users-on-windows.txt&amp;amp;title=Renaming SVN Users on Windows&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>CAR, CDR, and Lisp...</title>
    <link>http://www.mschaef.com/blog/2008/02/14#car-cdr</link>
    <description>
A couple weeks ago, I got into a brief &lt;a href=&quot;http://www.reddit.com&quot;&gt;reddit&lt;/a&gt; &lt;a
href=&quot;http://reddit.com/info/677u6/comments/c031w9f&quot;&gt;discussion&lt;/a&gt; on the relative merits
of Lisp's &lt;a
href=&quot;http://www.lisp.org/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html&quot;&gt;&lt;tt&gt;car&lt;/tt&gt; and
&lt;tt&gt;cdr&lt;/tt&gt;&lt;/a&gt; functions. Given a Lisp list, applying &lt;tt&gt;car&lt;/tt&gt; to the list returns
the first element of the list and applying &lt;tt&gt;cdr&lt;/tt&gt; to the list returns a list of
every element excluding the first.  For someone new to Lisp (as we all were once), these
names can be a bit awkward. However, like many other aspects of the language, there is
more to &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; than meets the eye.

&lt;br&gt;&lt;br&gt;

The first implementation of Lisp was done by &lt;a
href=&quot;http://en.wikipedia.org/wiki/Steve_Russell&quot;&gt;Steve Russell&lt;/a&gt; on an &lt;a
href=&quot;http://en.wikipedia.org/wiki/IBM_704&quot;&gt;IBM 704&lt;/a&gt;. The 704 was a 36-bit vacuum tube
machine that IBM started selling in 1954. By the time it was discontinued in 1960, they
had sold a total of 123 of the machines, each capable of a whopping 40,000 calculations
per second. Russell's original 1959 implementation of Lisp on this machine took advantage
of the fact that the 704's instruction set had special capabilities for accessing two
distinct 15 bit fields of a 36 bit value loaded into a machine register: the
&lt;b&gt;a&lt;/b&gt;ddress and &lt;b&gt;d&lt;/b&gt;ecrement fields.  In &lt;a
href=&quot;http://www.iwriteiam.nl/HaCAR_CDR.html&quot;&gt;Russell's own words&lt;/a&gt;: &lt;i&gt; &quot;Because of an
unfortunate temporary lapse of inspiration, we couldn't think of any other names for the 2
pointers in a list node than 'address' and 'decrement', so we called the functions CAR for
'Contents of Address of Register' and CDR for 'Contents of Decrement of Register'.&quot;&lt;/i&gt;
Interestingly enough, he continues with this: &lt;i&gt;&quot;After several months and giving a few
classes in LISP, we realized that 'first' and 'rest' were better names, and we (John
McCarthy, I and some of the rest of the AI Project) tried to get people to use them
instead. ... Alas, it was too late! We couldn't make it stick at all. So we have CAR and
CDR. &quot;&lt;/i&gt; So there you have it: &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt;, two of the most famous and
widely used functions of Lisp and its descendents, owe their names to a bizarre quirk of a
computer architecture that's been obsolete for close to fifty years. For the record,
here's a source listing for the original 704 implementataion of &lt;tt&gt;car&lt;/tt&gt; taken from &lt;a
href=&quot;ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-006.pdf&quot;&gt;MIT AI Lab Memo
6&lt;/a&gt;:

&lt;pre class=&quot;syntax&quot;&gt;
LXD JLOC, 4
CLA 0,4
PAX 0,4
PSX 0,4
&lt;/pre&gt;

But the story of &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; doesn't stop there.  In the 1960's and
early 70's, the &lt;a href=&quot;http://www.utexas.edu&quot;&gt;University of Texas at Austin&lt;/a&gt; ran a
computer called a &lt;a href=&quot;http://en.wikipedia.org/wiki/CDC_6600&quot;&gt;CDC 6600&lt;/a&gt;. The 6600
was one of &lt;a href=&quot;http://en.wikipedia.org/wiki/Seymour_Cray&quot;&gt;Seymour Cray&lt;/a&gt;'s first
big supercomputer designs, and was the fastest computer in the world for a time.  It had a
60-bit machine word and an 18-bit address space, so you can probably see where this is
going.  The designers of UT's Lisp for the CDC 6600 added a third field to &lt;tt&gt;cons&lt;/tt&gt;
cells, giving them each three pointers, the &lt;a
href=&quot;http://groups.google.com/group/alt.folklore.computers/browse_thread/thread/a1c2c48abe467f3c/b6217d9e521e043d?hl=en&amp;lnk=st&amp;q=car+cdr+csr+cdc+6600+lisp#b6217d9e521e043d&quot;&gt;&lt;tt&gt;car&lt;/tt&gt;,
&lt;tt&gt;cdr&lt;/tt&gt;, and &lt;tt&gt;csr&lt;/tt&gt;&lt;/a&gt;. I'm sure the third pointer was useful for implementing
things like trees of nodes and lists of key/value pairs, although apparantly not useful
enough to stick around. Two pointer cons cells are a better fit for modern hardware, and
two two pointer cons cells can represent everything that a single three pointer cons cell
can represent.

&lt;br&gt;&lt;br&gt;

Back at MIT in the 70's, and before things like &lt;a
href=&quot;http://www.lisp.org/HyperSpec/Body/mac_defstruct.html&quot;&gt;&lt;tt&gt;defstruct&lt;/tt&gt;&lt;/a&gt;, &lt;a
href=&quot;http://www.multicians.org/lcp.html&quot;&gt;Maclisp&lt;/a&gt; took the idea of multi-pointer cons
cells to what must be its logical extreme: &lt;a
href=&quot;http://www.maclisp.info/pitmanual/hunks.html&quot;&gt;hunks&lt;/a&gt;. A Maclisp hunk was a
structure like a cons cell that could hold an arbitrary number of pointers, up to total of
512. Each of these slots in a hunk was referred to as a numbered &lt;tt&gt;cxr&lt;/tt&gt;, with a
numbering scheme that went like this: &lt;tt&gt;( cxr-1 cxr-2 cxr-3 ... cxr-&lt;i&gt;n&lt;/i&gt; cxr-0
)&lt;/tt&gt;. No matter how many slots were in the hunk, &lt;tt&gt;car&lt;/tt&gt; was equivalent to &lt;tt&gt;(cxr
1 &lt;i&gt;hunk&lt;/i&gt;)&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; was equivalent to &lt;tt&gt;(cxr 0 &lt;i&gt;hunk&lt;/i&gt;)&lt;/tt&gt;. This is
a nice generalization of the basic idea of a cons cell, but modern Lisps offer other ways
to structure data that are both possibly more useful and more readable: structures for a fixed 
collection of named slots, hash tables for a variable collection of named slots, and vectors
for a collection of numbered slots.

&lt;br&gt;&lt;br&gt;

After these historical blind alleys, it's interesting to think about why &lt;tt&gt;car&lt;/tt&gt; and
&lt;tt&gt;cdr&lt;/tt&gt; still persist fifty years after McCarthy and Russell roamed the halls of MIT
evangelising &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt;. Common Lisp does at least have
&lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; as part of the standard. However, when I was taught Lisp
in the mid-90's, I was encouraged to primarily favor the older &lt;tt&gt;car&lt;/tt&gt; and
&lt;tt&gt;cdr&lt;/tt&gt;. I remember two primary reasons for this. The first was that existing code
favored &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt;, so it was important to be able to read code written
in that style. The second reason was that &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; impose a
particular meaning on the fields of a cons cell that may or may not be appropriate. In the
common case of a linear list, &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; work rather well. If you
call &lt;tt&gt;first&lt;/tt&gt; on the list, you get the first element, if you call &lt;tt&gt;rest&lt;/tt&gt;, you
get the rest. In the case of a cons cell as a node of an association list, they work less
well, unless, that is, you can figure out a reason why &lt;tt&gt;first&lt;/tt&gt; makes sense as
'key', and &lt;tt&gt;rest&lt;/tt&gt; makes sense as 'value'.

&lt;br&gt;&lt;br&gt;

Some of this confusion stems from the fact that most Lisps, despite the name &lt;b&gt;Lis&lt;/b&gt;t
&lt;b&gt;P&lt;/b&gt;rocessing, don't have an official list data type. What they have instead is a two
element cons cell and a set of conventions in the library, reader, and writer for using
the to make linear lists. In a sense, this is a lot like strings in C. C doesn't have a
string type, what it has instead is a pointer to character data (&lt;tt&gt;char *&lt;/tt&gt;) and a
set of library conventions for using blocks of memory as strings of characters. This
laxness on the part of both languages comes with the advantages and disadvantages you'd
expect from letting the deatils of an underlying implementation leak through. In the case
of C 'strings', the representation lends itself both to things like Rob Pike's beautiful
&lt;a href=&quot;http://cm.bell-labs.com/cm/cs/tpop/grep.c&quot;&gt;regex implementation&lt;/a&gt; in &lt;a
href=&quot;http://cm.bell-labs.com/cm/cs/tpop/&quot;&gt;The Practice of Programming&lt;/a&gt; and a seemingly
never ending series of buffer overrun attacks. In the case of Lisp cons cells, it provides
both an incredibly flexible data structure, and confusion over such basic notions as
the 'first', 'second', and 'rest' of a list.

&lt;br&gt;&lt;br&gt;

If something as baroque as 'car' actually makes more sense than 'first' because 'first'
doesn't match up well to underlying abstraction, it might them make sense to
reconsider the underlying implementation. Some modern Lisps like &lt;a
href=&quot;http://clojure.sourceforge.net/&quot;&gt;Clojure&lt;/a&gt; do just that; A Clojure 'list' isn't a
string of cons cells, but rather an instance of a JVM object that implements the
interface &lt;tt&gt;ISeq&lt;/tt&gt;:

&lt;pre class=&quot;syntax&quot;&gt;
public interface ISeq extends IPersistentCollection{
   Object first();
   ISeq rest();
   ISeq cons(Object o);
}
&lt;/pre&gt;

Clojure's user-visible &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; functions ultimately call into
their like-named methods in &lt;tt&gt;ISeq&lt;/tt&gt;:

&lt;pre class=&quot;syntax&quot;&gt;
static public Object first(Object x){
	ISeq seq = seq(x);
	if(seq == null)
		return null;
	return seq.first();
}

// ...

static public ISeq rest(Object x){
	ISeq seq = seq(x);
	if(seq == null)
		return null;
	return seq.rest();
}
&lt;/pre&gt;

A noteworthy difference between this and a 'conventional' Lisp is the return type of
&lt;tt&gt;rest&lt;/tt&gt;: it's another &lt;tt&gt;ISeq&lt;/tt&gt;, rather than a &lt;tt&gt;Object&lt;/tt&gt;. Because of this,
the 'CDR' of a Clojure cons cell has a new constraint: it is constrained to be another
sequence, increasing greatly the likelihood that 'rest' really is 'the rest'. While
this could be done even if &lt;tt&gt;rest&lt;/tt&gt; returned an &lt;tt&gt;Object&lt;/tt&gt;, constraining
rest to be a sequence eliminates a number of edge cases in the language that arise
when you allow the rest of a list to be something other than a list itself. This altered 
representation also fits in nicely with Clojure's host JVM: there's nothing that says
&lt;tt&gt;ISeq&lt;/tt&gt; has to be implemented by a two-element pointer. Indeed, Closure 
&lt;a href=&quot;http://reddit.com/r/programming/info/68sll/comments/c036rc6&quot;&gt;
&lt;i&gt;&quot;also implements first and rest for vectors, strings, arrays, maps, Java Iterables,
lazily calculated and infinite sequences etc.&quot;&lt;/i&gt;&lt;/a&gt;  All these implementations of
&lt;tt&gt;ISeq&lt;/tt&gt; make it easier for Clojure sequences to interoperate with Java,
and it makes it easier to build a sequence library that works on all kinds of sequences.
What's lost with this choice is the ability to use a cons cell as an informal two-element
structure.  Even then, this style of &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; could co-exist
with implementations of &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; that work the 'old way'.

&lt;br&gt;&lt;br&gt;

So in the end, maybe &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; are all right. They aren't the best
names in the world, but they fit nicely the semantics of a unrestricted two-pointer
cons cell. For those cases where you really are finding the first and rest of a 
list of cons cells, it is easy to use the &lt;tt&gt;first&lt;/tt&gt; and &lt;tt&gt;rest&lt;/tt&gt; functions in
lieu of &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt;. Then, for dialects like Clojure, your code is
automatically portable to other sequence types. If you're using cons cells as a
ad hoc structure, then you can either use &lt;tt&gt;car&lt;/tt&gt; and &lt;tt&gt;cdr&lt;/tt&gt; and accept those
names as  historical baggage of the second oldest major programming language, or
investigate some of  the other more modern ways of structuring data in Lisp programs. &lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Flisp%2Fcar-cdr.txt;title=CAR%2C%20CDR%2C%20and%20Lisp...&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/lisp/car-cdr.txt&amp;amp;title=CAR, CDR, and Lisp...&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>A correction and another blog.</title>
    <link>http://www.mschaef.com/blog/2008/02/14#correction_and_blog</link>
    <description>
&lt;list&gt;
&lt;li&gt;There was a copy/paste error in the version of &lt;a 
  href=&quot;http://www.mschaef.com/blog/tech/programming/ant-up.html&quot;&gt;ant-up&lt;/a&gt; 
  I posted a while ago. It has now been corrected.
&lt;li&gt;I ran across &lt;a href=&quot;http://www.adamhoughton.com&quot;&gt;Adam Houghton's
   blog&lt;/a&gt; the other day. It looks pretty interesting and there's 
   software to download (which is more than I can say right now). The blog 
   seems to currently focus on Apple/Java/AJAX related content. The iPhone
   based javadoc viewer looks particularly interesting, for those of us 
   not interested in carrying around a library.
&lt;li&gt;Also, on a totally different note is &lt;a 
    href=&quot;http://www.autoblog.com/&quot;&gt;Autoblog&lt;/a&gt;, a 'professional' blog
    covering automotive news. It's updated fairly often too.
&lt;/list&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fgeneral%2Fcorrection_and_blog.txt;title=A%20correction%20and%20another%20blog.&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/general/correction_and_blog.txt&amp;amp;title=A correction and another blog.&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Renaming historical users (svn:author's) in SVN repositories</title>
    <link>http://www.mschaef.com/blog/2008/02/11#renaming-svn-users</link>
    <description>
I've been keeping track of the vCalc source code in an SVN
repository since May of 2005. While I'm the only person who has
ever committed code into the repository, I've developed vCalc on
three or four machines, with different usernames on each
machine. Since SVN records usernames with each commit, these
historical usernames show up in each &lt;a
href=&quot;http://svnbook.red-bean.com/en/1.0/re15.html&quot;&gt;&lt;tt&gt;svn
log&lt;/tt&gt;&lt;/a&gt; or &lt;a
href=&quot;http://svnbook.red-bean.com/en/1.0/re02.html&quot;&gt;&lt;tt&gt;svn
blame&lt;/tt&gt;&lt;/a&gt;. &lt;tt&gt;svn blame&lt;/tt&gt; is particularly bad because it
displays a code listing with the username prepended to each line
in a fixed width gutter. With some usernames longer than others,
usernames that are very long can exceed the width of the gutter
and push the code over to the right.  Fortunately, changing
historical usernames isn't that hard, if you have administrator
rights on your SVN repository.

&lt;br&gt;&lt;br&gt;

SVN stores the name of a revision's committer in a &lt;a
href=&quot;http://svnbook.red-bean.com/en/1.4/svn.advanced.props.html&quot;&gt;revision
property&lt;/a&gt; named &lt;tt&gt;svn:author&lt;/tt&gt;. If you're not familar
with the term, a revision property is a blob of out of band data
that SVN attaches to the revision. In addition to the author of a
commit, they're also used to store the commit log message, and,
via SVN's &lt;a
href=&quot;http://svnbook.red-bean.com/en/1.0/re23.html&quot;&gt;&lt;tt&gt;propset&lt;/tt&gt;&lt;/a&gt;
and &lt;a
href=&quot;http://svnbook.red-bean.com/en/1.0/re21.html&quot;&gt;&lt;tt&gt;propget&lt;/tt&gt;&lt;/a&gt;
commands, user-provided custom metadata for the
revision. Changing the name of a user associated with a commit
basically amounts to using &lt;tt&gt;propset&lt;/tt&gt; to update the
&lt;tt&gt;svn:author&lt;/tt&gt; property for a revision. The command to do
this is structured like so:

&lt;pre class=&quot;syntax&quot;&gt;
svn propset svn:author --revprop -r&lt;i&gt;rev-number&lt;/i&gt; &lt;i&gt;new-username&lt;/i&gt; &lt;i&gt;repository-URL&lt;/i&gt;
&lt;/pre&gt;

If this works, you are all set, but what is more likely to happen
is the following error:

&lt;pre class=&quot;syntax&quot;&gt;
svn: Repository has not been enabled to accept revision propchanges;
ask the administrator to create a pre-revprop-change hook
&lt;/pre&gt;

By default, revision property changes are disabled. This makes
sense if you are at all interested in using your source code
control system to satisfy an auditing requirement. Changing the
author of a commit would be a great way for a developer to cover
their tracks, if they were interested in doing something
underhanded. Also, unlike most other aspects of a project managed
in SVN, &lt;i&gt;revision properties have no change tracking&lt;/i&gt;: They
are the change tracking mechanism for everything else.  Because
of the security risks, enabling changes to revision properties
requires establishment of a guard hook: an external procedure
that is consulted whenever someone requests that a revision
property be changed. Any policy decisions about who can change
what revision property when are implemented in the hook
procedure.

&lt;br&gt;&lt;br&gt;

Hooks in SVN are stored in the &lt;tt&gt;hooks/&lt;/tt&gt; directory under
the repository toplevel. Conveniently, SVN provides a sample
implementation on the hook we need to implement in the shell script
&lt;tt&gt;pre-revprop-change.tmpl&lt;/tt&gt;, but the sample implementation
also has strict defaults about what can be changed, allowing only
the log message to be set:

&lt;pre class=&quot;syntax&quot;&gt;
if [ &quot;$ACTION&quot; = &quot;M&quot; -a &quot;$PROPNAME&quot; = &quot;svn:log&quot; ]; then exit 0; fi

echo &quot;Changing revision properties other than svn:log is prohibited&quot; &amp;gt;&amp;2
exit 1
&lt;/pre&gt;

The sample script can be enabled by renaming it to
&lt;tt&gt;pre-revprop-change&lt;/tt&gt;. It can be made considerably more lax
by adding an &lt;tt&gt;exit 0&lt;/tt&gt; before the lines I list above. At
this point, the property update command should work, although if
you're at all interested in the security of your repository, it
is best to restore whatever revision property policy was in place
as soon as possible.
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fprogramming%2Frenaming-svn-users.txt;title=Renaming%20historical%20users%20%28svn%3Aauthor%27s%29%20in%20SVN%20repositories&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/programming/renaming-svn-users.txt&amp;amp;title=Renaming historical users (svn:author's) in SVN repositories&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Excel, CR/LF, and CSV</title>
    <link>http://www.mschaef.com/blog/2008/02/01#cr-lf</link>
    <description>
I've spent a fair amount of time lately working with code that generates 
Comma Seperated Value files for loading into Excel.  You'd think the 
format would be trivial, but &lt;a 
href=&quot;http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm#EmbedBRs&quot;&gt;not quite&lt;/a&gt;. One 
additional subtlety, one not covered in that 'specification', is Excel's inconsistent handling 
of end of line markers. As it turns out, if Excel loads a CSV file that contains a quoted, 
multi-line value, it expects a different line feed convention within the quoted value than the 
usual CR/LF. A CR embedded in a quoted field renders as a box, rather than as part of a newline. 
To suppress the box, CSV files for Excel need to be written with a LF-only convention within 
quoted values. Even then, Excel will not automatically expand rows containing a multi-line 
value. That has to be done manually.

&lt;br&gt;&lt;br&gt;

Internally, Excel seems to follow the same LF-only convention that this issue with CSV files 
seems to imply.  Taking the &lt;tt&gt;CODE(...)&lt;/tt&gt; of each character in a manually entered 
multi-line cell value, shows only one charater, a LF, at each line break. My guess is that the 
quotes in a CSV file just act as a signal to turn off &lt;b&gt;all&lt;/b&gt; special character handling, not 
just handling that signals new rows and cells. Either way, it's more than a little irritating 
that Excel compatible CSV files with multi-line values have to have two seperate end of line 
conventions.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fexcel%2Fcr-lf.txt;title=Excel%2C%20CR%2FLF%2C%20and%20CSV&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/excel/cr-lf.txt&amp;amp;title=Excel, CR/LF, and CSV&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  <item>
    <title>Still not tested... still not working... sort of...</title>
    <link>http://www.mschaef.com/blog/2008/01/21#still_not_tested</link>
    <description>
Another one along the lines of &lt;a 
href=&quot;http://www.mschaef.com/blog/tech/programming/not_tested_not_working.html&quot;&gt;My 
last post&lt;/a&gt;. I tried to compile this source file today, using the 
compiler in my little Lisp:

&lt;pre class=&quot;syntax&quot;&gt;
(define (values . args) (%panic &quot;roh roh&quot;))

(define (test x) (+ x 1))
&lt;/pre&gt;

I got the following result:

&lt;pre class=&quot;syntax&quot;&gt;
d:\test&gt;vcsh -c test.scm
;;;; VCSH, Debug Build (SCAN 0.99 - Dec 17 2007 16:47:30)

; Info: Loading Internal File: fasl-compiler
; Info: Package 'fasl-compiler' created
; Info: Loading Internal File: fasl-write
; Info: Package 'fasl-write' created
; Info: Loading Internal File: fasl-compiler-run
; Info: Package 'fasl-compiler-run' created
; Info: stack limit disabled!
Fatal Error: roh roh @ (error.cpp:168)
&lt;/pre&gt;

Needless to say, fatal errors still aren't any good. However, this one is 
a bit more interesting than a simple type checking problem. The function 
&lt;tt&gt;%panic&lt;/tt&gt; is the internal function used to signal fatal errors from 
Lisp code. The first definition above redefines &lt;tt&gt;values&lt;/tt&gt;, the 
function to return multiple return values, so that it always panics with a 
fatal error. This is the kind of thing that, if done in a running 
environment, would break things almost immediately.

&lt;br&gt;&lt;Br&gt;

But, the compiler is slightly different.... it isolates the program being 
compiled from the compiler itself. This is done to keep redefinitions that 
might break the currently running compiler from doing just that. 
Redefinitions by the compiled program are only supposed to be visible to 
the compiled program. Since the above program never itself invokes 
&lt;tt&gt;values&lt;/tt&gt;, it should never hit the call to &lt;tt&gt;%panic&lt;/tt&gt;... except 
that it does.

&lt;br&gt;&lt;br&gt;

What's happening here lies in the processing of the second definition. The 
definition itself is transformed a couple times by macroexpansion, first 
to this:

&lt;pre class=&quot;syntax&quot;&gt;
(%define test (named-lambda test (x) (+ x 1)))
&lt;/pre&gt;

And then, basically, to this:

&lt;pre class=&quot;syntax&quot;&gt;
(%define test (%lambda ((name . test) (lambda-list x)) (x) (+ x 1)))
&lt;/pre&gt;

The second macroexpansion step is the step that looks for optional 
arguments, and the internal function that parses lambda lists for optional 
arguments returns three values using &lt;tt&gt;values&lt;/tt&gt;. This invocation of 
&lt;tt&gt;values&lt;/tt&gt; happens in the environment of the program being compiled, 
so it hits the new &lt;tt&gt;%panic&lt;/tt&gt;-invoking definition and the whole show 
grinds to a halt. The 'easy' fix, ensuring that macro expansion is 
isolated from potentially harmful redefinitions, won't work. Macro 
expansion has to happen in the user environment, so that macros can see 
function definitions that they might rely upon.

&lt;br&gt;&lt;br&gt;

I don't have a unit test for the user/compiler seperation logic, so I 
thought when I started this blog post I was going to say something like: 
'look, something else fundamentally broken, and without a test case'. 
That's interesting, but if you need convincing to write unit tests, you're 
probably already lost. What I actually learned while researching this post 
is a bit more subtle: it's a fundamental problem, but it's more about the 
design than the code itself.  While the design I have for user/compiler 
seperation seems to work most of the time, it's not adequate to solve this 
kind of problem. I'm not yet exactly sure what the solution is, but it 
won't necessarily involve a missing unit test.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://reddit.com/submit?url=http%3A%2F%2Fwww.mschaef.com%2Fblog%2Ftech%2Fprogramming%2Fstill_not_tested.txt;title=Still%20not%20tested...%20still%20not%20working...%20sort%20of...&quot;&gt;reddit this!&lt;/a&gt; &lt;a href=&quot;http://www.digg.com/submit?url=http://www.mschaef.com/blog/tech/programming/still_not_tested.txt&amp;amp;title=Still not tested... still not working... sort of...&amp;amp;phase=2&quot;&gt;Digg Me!&lt;/a&gt;</description>
  </item>
  </channel>
</rss>