<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Irate Nate's weblog</title><link>http://www.method-combination.net/blog/</link><description>debugging life</description><language>en-us</language><generator>clog version 3b</generator><dc:creator>froydnj@gmail.com</dc:creator><dc:rights>Copyright 2004 Nathan Froyd</dc:rights><item><title>re-reading robert jordan</title><link>http://www.method-combination.net/blog/archives/2010/05/08/re-reading-robert-jordan.html</link><pubDate>Sat, 08 May 2010 14:44:00 CDT</pubDate><description>&lt;P&gt;I was in an airport bookstore last week and picked up one of the
newer &lt;CITE&gt;Wheel of Time&lt;/CITE&gt; books.  I opened it to a random page
and read:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Nynaeve crossed her arms under her breasts and
sniffed.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Yes, well, shocking.  I stopped reading after &lt;CITE&gt;Winter's
Heart&lt;/CITE&gt;, but I have found something that almost makes me want to start
reading them again.  It's Leigh Butler's &lt;A HREF=&quot;http://www.tor.com/index.php?option=com_content&amp;view=blog&amp;id=11741&quot;&gt;Wheel of Time Re-Read&lt;/A&gt;, wherein she, well, re-reads Jordan's epic,
complete with varying amounts of breezy, pop-culture commentary on each
bit.  My favorite bit so far, having only &amp;ldquo;re-read&amp;rdquo; &lt;CITE&gt;The Shadow Rising&lt;/CITE&gt;, was an musing on Mat as the classic American
hero.&lt;/P&gt;&lt;P&gt;She's in the middle of &lt;CITE&gt;The Path of Daggers&lt;/CITE&gt; right now.
I find myself strongly tempted to re-read all of the novels--and read
the new ones--through the lens of this blog.  I haven't looked at the
inspiration for this project, &lt;A HREF=&quot;http://www.tor.com/index.php?option=com_content&amp;view=blog&amp;id=9473&quot;&gt;the &lt;CITE&gt;Lord of the Rings&lt;/CITE&gt; re-read&lt;/A&gt;, but I suspect that one
would be equally compelling.&lt;/P&gt;</description><category>books</category><category>wheel of time</category></item><item><title>analogical thinking</title><link>http://www.method-combination.net/blog/archives/2010/05/05/analogical-thinking.html</link><pubDate>Wed, 05 May 2010 08:26:00 CDT</pubDate><description>&lt;P&gt;We were riding around in the car this past weekend and Becca was
complaining that Ally was so enamored with everything she did.  Tricia
was attempting to explain that this is because Ally thinks Becca is so
cool and someone to look up to.  Tricia told Becca, &amp;ldquo;She thinks
you're the cat's meow!&amp;rdquo;&lt;/P&gt;&lt;P&gt;Becca thought about that for a second, and Ally piped up with,
&amp;ldquo;You're the dog's woof!&amp;rdquo;&lt;/P&gt;&lt;P&gt;Hooray!  My child is thinking analogically!  This feels like a big
step.  We compliment Ally on her observation.&lt;/P&gt;&lt;P&gt;To which Ally responds, &amp;ldquo;You're the pooping dog's
poop!&amp;rdquo;&lt;/P&gt;&lt;P&gt;OK, still thinking analogically, but...&lt;/P&gt;</description><category>children</category><category>family</category><category>humor</category></item><item><title>functional language proponents</title><link>http://www.method-combination.net/blog/archives/2010/04/28/functional-language-proponents.html</link><pubDate>Wed, 28 Apr 2010 15:55:00 CDT</pubDate><description>&lt;P&gt;Seen on &lt;A HREF=&quot;http://lambda-the-ultimate.org/node/3924&quot;&gt;an
LtU thread&lt;/A&gt;:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Actually, I think one of the reasons FP proponents are
more convinced of the superiority of functional programming than is
necessarily warranted is due to their high degree of applicability to
writing compilers, where almost all I/O is input to a function at one
end and output at the other end, where the input and output are defined
in specifications, where there is an unambiguously correct mapping from
source to target, where the data is inherently tree structured, where
the structure of the computation involves recursive pattern matching and
transformation, where there is virtually no dynamic code loading
necessary, etc. It's a match made in heaven; and if all you do is geek
on languages and compilers - especially in an academic context - of
course it's self-evident that functional programming is superior to
everything else.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;How true, how true.&lt;/P&gt;</description><category>languages</category><category>programming</category><category>lisp</category></item><item><title>pwnat</title><link>http://www.method-combination.net/blog/archives/2010/04/27/pwnat.html</link><pubDate>Tue, 27 Apr 2010 15:21:00 CDT</pubDate><description>&lt;P&gt;Cool tool of the day: &lt;A HREF=&quot;http://samy.pl/pwnat/&quot;&gt;pwnat&lt;/A&gt;.  From the description:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;pwnat, pronounced &amp;ldquo;poe-nat&amp;rdquo;, is a tool
that allows any number of clients behind NATs to communicate with a
server behind a separate NAT with *no* port forwarding and *no* DMZ
setup on any routers in order to directly communicate with each
other. The server does not need to know anything about the clients
trying to connect.&lt;/P&gt;&lt;P&gt;Simply put, this is a proxy server that works behind a NAT,
even when the client is behind a NAT, without any 3rd party.&lt;/P&gt;&lt;P&gt;There is no middle man, no proxy, no 3rd party, no UPnP/STUN/ICE
required, no spoofing, and no DNS tricks.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;The above page also features a description of how it works.  Very
cool.&lt;/P&gt;</description><category>networking</category><category>programs</category><category>tools</category></item><item><title>commentary on peter pan</title><link>http://www.method-combination.net/blog/archives/2010/04/18/commentary-on-peter-pan.html</link><pubDate>Sun, 18 Apr 2010 21:23:00 CDT</pubDate><description>&lt;P&gt;I have meant to blog about &lt;A HREF=&quot;http://www.firstthings.com/onthesquare/2009/12/sympathy-for-hook58-toward-a-christening-of-peter-pan&quot;&gt;Sympathy for Hook: Toward a Christening of &lt;CITE&gt;Peter Pan&lt;/CITE&gt;&lt;/A&gt;
ever since I read it several months ago. Even re-reading it today, it
stirred up the same mix of emotion (&amp;ldquo;cool!&amp;rdquo;, melancholy,
thoughtfulness) that it did originally. To whet your appetite:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Peter Pan is about the death of children, long a
daunting challenge to both simple faith and learned soteriology. It is,
however, equally about deadly parental neglect--about not wanting or
loving children. It is all too timely for our era of selfishly infertile
and casually feticidal adults. Perhaps we miss Peter Pan's central
themes in part because child death post partum has become far rarer than
it was a century ago. We also may miss them, at least in part, because
we dismiss as mere caricature the story's main adult character, Captain
Hook: We fail to recall and give due weight to the tradition, which goes
back to the play's first staging, under Barrie's direction, that Hook be
played by the same actor who plays Mr. Darling, a flawed
father. Mr. Darling and Hook are, in fact, the same character, operating
respectively in this world and in Barrie's limbus puerorum,
Neverland. Although, as G.B. Shaw noted, Peter Pan &amp;ldquo;is ostensibly
a holiday entertainment for children but really a play for grown-up
people,&amp;rdquo; appreciation of its burden for grown-ups requires
attention to its main adult character. Appreciation of Peter Pan
requires sympathy for Hook.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Recommended reading, particularly for parents and doubly so for
fathers.&lt;/P&gt;&lt;P&gt;Tricia and I started reading Peter Pan this past summer and were
somewhat taken aback at the tone and violence in the book (thanks,
Disney!). But this essay makes me think that completing the book will
definitely be worthwhile. Now to find the road trip to read to each
other...&lt;/P&gt;</description><category>literature</category><category>commentary</category><category>family</category></item><item><title>financial regulation</title><link>http://www.method-combination.net/blog/archives/2010/04/12/financial-regulation.html</link><pubDate>Mon, 12 Apr 2010 15:36:00 CDT</pubDate><description>&lt;P&gt;Eliot Spitzer &lt;A HREF=&quot;http://bostonreview.net/BR35.2/spitzer.php&quot;&gt;on the need for
government financial regulation&lt;/A&gt;:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;When I was Attorney General of New York, we
investigated what I refer to as the &quot;analyst cases.&quot; The cases were
about investment banking. To understand them, all you need to know about
investment banking is that the business has two sides: you have supposed
analysts, who recommend stocks for investors to buy, and you have
underwriters, who sell IPOs, secondary offerings, and other things that
raise capital for the companies. We argued that there is an inherent
conflict of interest when you have people in the same business who are
both recommending a stock to retail investors--saying, &quot;this is a great
stock, buy it&quot;--and doing the underwriting. The more successful the
underwriting, the more fees it will generate, and the more favorable the
analysis, the more likely the underwriting will succeed.&lt;/P&gt;&lt;P&gt;This is clearly a conflict of interest. In fact, Jack Grubman, the
telecom analyst banned from the securities industry in 2002, brilliantly
encapsulated this whole era: what used to be viewed as a conflict of
interest, he said, is now viewed as &quot;synergy.&quot; Think about that. What
used to be viewed as a conflict of interest--hence dangerous to people,
something to warn them about--is turned into something that creates
value. This was the way we masked the problem. In the analyst cases, we
didn't discover the conflict of interest: everyone understood it and had
accepted it for a long time. But at the attorney general's office, we
called it what it was...&lt;/P&gt;&lt;P&gt;The lawyers for Merrill came into my office. Now, when you're a
white-collar defense lawyer, you argue in the alternative. First you say
the emails were taken out of context. Then you say: &quot;you don't fully
understand them.&quot; Then you say, &quot;no, they were fabricated.&quot; Then you say
the person doesn't really speak on behalf of the company. And then you
check the limits on your insurance. I was a white-collar defense
attorney for a number of years, so I know the drill.&lt;/P&gt;&lt;P&gt;They didn't make any of those arguments. They came to me and said,
in essence, &quot;Eliot, you're right. Absolutely right about the conflicts,
the tensions, the problems. But we are not as bad as our competitors.&quot;
That was their defense to the charge that they were defrauding their
customers and the marketplace. When I asked to hear more about it, they
said, &quot;let me tell you about Goldman and Citi.&quot; I've turned defendants
over the years, but these guys were the easiest flip I've ever done.&lt;/P&gt;&lt;P&gt;There is a very important point here: the people at Merrill Lynch
understood that their business model was problematic. They understood
that there was something wrong with recommending stocks that they didn't
think were any good. But they had to choose between ethics and profits,
and they made the choice that harmed individuals and undercut the
integrity of the market. And then they said it wasn't up to them to
enforce the rules of transparency. Somebody else should do it.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;</description><category>finance</category><category>politics</category></item><item><title>greenspun makefiles</title><link>http://www.method-combination.net/blog/archives/2010/04/09/greenspun-makefiles.html</link><pubDate>Fri, 09 Apr 2010 22:23:00 CDT</pubDate><description>&lt;P&gt;Greenspun's Tenth Rule:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Any sufficiently complicated C or Fortran program
contains an ad hoc, informally-specified, bug-ridden, slow
implementation of half of Common Lisp.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Can we apply that to Makefiles, too?  This is what I wrote
tonight:&lt;/P&gt;&lt;PRE&gt;find-hwm-sources = $(subst $(srcdir)/arch/$(ARCH_DIR)/,,\
                            $(wildcard $(HWM_DIR)/$(1)/*.$(2)))
hwm-c-objfile-name = $(subst /,-,$(1:%.c=%.o))
hwm-S-objfile-name = $(subst /,-,$(1:%.S=%.o))
hwm-sources-varname = HWM-$(1)-$(2)
hwm-objects-varname = HWM-$(1)-$(2)-objects

define hwm-object-template
$(call hwm-sources-varname,$(1),$(2)) := $(call find-hwm-sources,$(1),$(2))
$(call hwm-objects-varname,$(1),$(2)) := \
  $$(foreach o,$$(value $$(call hwm-sources-varname,$(1),$(2))),\
     $$(call hwm-$(2)-objfile-name,$$(o)))
$$(value $$(call hwm-objects-varname,$(1),$(2))) \
  : hwm-$(1)-%.o : hwm/$(1)/%.$(2) $(if $(subst S,,$(2)),,assym.s)
	$$(CC) $$(if $$(subst S,,$(2)),,-D_ASM -include assym.s) $$(ALL_CFLAGS) $$&lt; -c -o $$@
HWM_ALL_OBJ_$(2) += $$(value $$(call hwm-objects-varname,$(1),$(2)))
endef

HWM_C_SUBDIRS := timer rhymer nickel dimer dcache icache ucache wecache zing
HWM_S_SUBDIRS := base
$(foreach s,$(HWM_C_SUBDIRS),$(eval $(call hwm-object-template,$(s),c)))
$(foreach s,$(HWM_S_SUBDIRS),$(eval $(call hwm-object-template,$(s),S)))&lt;/PRE&gt;&lt;P&gt;(newlines and backslashes inserted for sanity in word-wrapping; had
they actually been there, &lt;TT&gt;make&lt;/TT&gt; probably would have
choked.)&lt;/P&gt;&lt;P&gt;Just think how much easier that would have been in a language with
real macros.  Of course, it's also possible that there's a much simpler
way to do what I wanted...&lt;/P&gt;</description><category>lisp</category></item><item><title>looping issues</title><link>http://www.method-combination.net/blog/archives/2010/04/06/looping-issues.html</link><pubDate>Tue, 06 Apr 2010 23:37:00 CDT</pubDate><description>&lt;P&gt;I really enjoy using &lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm&quot;&gt;&lt;TT&gt;loop&lt;/TT&gt;&lt;/A&gt;.  Collapsing a surrounding &lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm&quot;&gt;&lt;TT&gt;let&lt;/TT&gt;&lt;/A&gt; in a &lt;TT&gt;with&lt;/TT&gt; binding clause or lifting an &lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/s_if.htm&quot;&gt;&lt;TT&gt;if&lt;/TT&gt;&lt;/A&gt;
expression into a conditional execution clause brings me happiness.  One
of the things I dislike about it, though, is collecting with nested
loops.  In highly repetitive macroized code, for instance, it's not
unusual to want to do something like:&lt;/P&gt;&lt;PRE&gt;(loop for ...
  do (loop for ...
        collect ...))&lt;/PRE&gt;&lt;P&gt;Except that doesn't work, because you're only collecting in the
inner loop, not in the outer loop where you want.  There are ways around
this; you can do:&lt;/P&gt;&lt;PRE&gt;(loop with list = nil
  for ...
  do (loop for ...
       do (push ... list))
  finally (return (nreverse list)))&lt;/PRE&gt;&lt;P&gt;Or, if you like using loop's features:&lt;/P&gt;&lt;PRE&gt;(loop for ...
  nconc (loop for ...
           collect ...))&lt;/PRE&gt;&lt;P&gt;I don't particularly care for either of those, though I'll use the
last one if the situation arises.&lt;/P&gt;&lt;P&gt;Recently, though, I found a shortcut for a special case.  I needed
to loop over several quantities, each of which could be true or false.
Extending the second workaround to a multilevel loop...well, let's not
go there.  However, by doing some bit-twiddling, I arrived at:&lt;/P&gt;&lt;PRE&gt;(loop for bits from 0 below (ash 1 n-quantities)
  for q0 = (logbitp 0 bits)
  for q1 = (logbitp 1 bits)
  for q2 = (logbitp 2 bits)
  ...
  collect ...)&lt;/PRE&gt;&lt;P&gt;which works well and avoids deeply nesting code.  It even works if
you have one quantity that iterates over a number of values that's not a
power of two.  Say you have three true/false things and one tri-valued
thing:&lt;/P&gt;&lt;PRE&gt;(loop for bits from 0 upto #b10111
  for q0 = (logbitp 0 bits)
  for q1 = (logbitp 1 bits)
  for q2 = (logbitp 2 bits)
  for q3 = (ecase (ldb (byte 2 3) bits)
             (0 ...)
             (1 ...)
             (2 ...))
  ...)&lt;/PRE&gt;&lt;P&gt;Perhaps not overly useful, but a nice trick to have in your bag.&lt;/P&gt;</description><category>lisp</category></item><item><title>love my debugger</title><link>http://www.method-combination.net/blog/archives/2010/03/25/love-my-debugger.html</link><pubDate>Thu, 25 Mar 2010 21:11:00 CDT</pubDate><description>&lt;P&gt;I love my debugger.&lt;/P&gt;&lt;P&gt;I realize that this is not the usual stance among developers.  &lt;CITE&gt;The Practice of Programming&lt;/CITE&gt; by Kernighan and Pike states in
 the chapter on debugging:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;As a personal choice, we tend not to use debuggers
 beyond getting a stack trace or the value of a variable or two.  One
 reason is that it is easy to get lost in details of complicated data
 structures and control flow; we find stepping through a program less
 productive than thinking harder and adding output statements and
 self-checking code at critical places.  Clicking over statements takes
 longer than scanning the output of judiciously-placed displays.  It
 takes less time to decide where to put print statements than to
 single-step to the critical section of code, even assuming we know
 where that is.  More important, debugging statements stay with the
 program; debugger sessions are transient.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Now, &amp;ldquo;thinking harder&amp;rdquo; is certainly a valuable skill.
 &lt;A HREF=&quot;http://kerneltrap.org/mailarchive/linux-kernel/2008/1/8/546884&quot;&gt;Debugging kernel oopses without the running kernel&lt;/A&gt; is certainly a
 valuable skill.  (Read that link; it's the sort of debugging you ought
 to aspire to.)  But I think it's fair to say that the above paragraph
 advocates two approaches to debugging: thinking hard and putting in
 print statements.&lt;/P&gt;&lt;P&gt;The critical observation that's made me love my debugger in the
 last several months is this: a debugger is a tool for inserting print
 statements &lt;EM&gt;at runtime&lt;/EM&gt;.  Stick a breakpoint where you think
 things are going wrong and poke around when you stop there.  Stick a
 breakpoint a little further along if you need to.  Disable the previous
 one because it's not helpful.  If your debugger supports it, tell it to
 automatically print out some information when it hits a breakpoint
 and/or make that breakpoint depend on some condition you think is
 interesting.  If you're feeling daring and you think you botched an
 assignment somewhere, tell the debugger to modify some variable values
 when you hit a breakpoint and continue execution.  Yes, it's all
 boiling down to print statements, but you're doing it &lt;EM&gt;at
 runtime&lt;/EM&gt;.&lt;/P&gt;&lt;P&gt;Plus, you can do all of these things without recompiling your
 program.  And that is a huge huge win.  With a huge program to debug,
 even with a beefy machine for compilation, you're stuck twiddling your
 thumbs waiting for a compile/link cycle.  Ooops, wait, you have to do
 another one because you screwed up a semicolon or some matter of
 syntax.  Oh, hm, that print statement isn't giving me enough
 information; I need to go insert another one somewhere.  Bother, that's
 too much information, I should set up a debug level framework for
 enabling these messages separately.  Wait, I need some information over
 here to obtain more clarity; should that be debug level one or debug
 level two or another debug level entirely?  Whoops, fix that format
 string mismatch with my &lt;TT&gt;printf&lt;/TT&gt;...you see how this can get
 tedious.&lt;/P&gt;&lt;P&gt;I was starting down the above path earlier this week when I decided
to use the debugger instead.  (And in a humorous twist, I was working on
GDB, so reaching for the debugger should have been the first thing on my
mind!)  And the experience was significantly more pleasant and took me
much less time than bothering with debug levels and &lt;TT&gt;printf&lt;/TT&gt;s
and staring at log output.&lt;/P&gt;&lt;P&gt;I'm not as good as Kernighan and Pike; perhaps I don't think hard
enough about where to place my debug statements.  Or I make too many
simple typos and require too many recompile steps.  Or the programs I
work on don't follow the Unix Way strictly enough and are too big.  And
yes, I've worked on several codebases where using a debugger was painful
and print statements are a better option.  But the next time you're
about to write a bevy of print statements to tell you everything you
need to know about what your program is doing, try using a debugger
instead.  I bet you will be surprised at how much better the debugging
experience is.&lt;/P&gt;</description><category>programming</category></item><item><title>movie recommendations</title><link>http://www.method-combination.net/blog/archives/2010/03/18/movie-recommendations.html</link><pubDate>Thu, 18 Mar 2010 00:02:00 CDT</pubDate><description>&lt;P&gt;Tricia and I are planning on activating a free 1-month Netflix
 subscription in the next few days.  Our short list of movies we'd like
 to rent during the subscription is:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;CITE&gt;&lt;A HREF=&quot;http://www.imdb.com/title/tt1135503/&quot;&gt;Julie and Julia&lt;/A&gt;&lt;/CITE&gt;&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;&lt;A HREF=&quot;http://www.imdb.com/title/tt0796366/&quot;&gt;Star Trek&lt;/A&gt;&lt;/CITE&gt; (the new one, obviously)&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;&lt;A HREF=&quot;http://www.imdb.com/title/tt0821642/&quot;&gt;The Soloist&lt;/A&gt;&lt;/CITE&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Anybody have any other suggestions?&lt;/P&gt;</description><category>movies</category></item><item><title>book report</title><link>http://www.method-combination.net/blog/archives/2010/03/05/book-report.html</link><pubDate>Fri, 05 Mar 2010 19:08:00 CDT</pubDate><description>&lt;P&gt;I've had a bit more time to read than normal these past two months
 because I've been traveling for work.  Even though I don't feel like
 I've been reading a book a week (my goal), the list below suggests I'm
 not doing too badly.&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;CITE&gt;Daemon&lt;/CITE&gt; by Daniel Suarez&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Who's Afraid of Postmodernism?  Taking Deriida, Lyotard,
and Foucault to Church&lt;/CITE&gt; by James K.A. Smith&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;The Price of Spring&lt;/CITE&gt; by Daniel Abraham&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;The Next Reformation&lt;/CITE&gt; by Carl Raschke&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Whole Earth Discipline&lt;/CITE&gt; by Stewart Brand&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Sidewalks in the Kingdom&lt;/CITE&gt; by Eric O. Jacobsen&lt;/LI&gt;&lt;LI&gt;Assorted Sherlock Holmes short stories by Sir Arthur Conan Doyle&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Cradle to Cradle&lt;/CITE&gt; by William McDonough and Michael Braungart&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Foucault for Beginners&lt;/CITE&gt; by Lydia Alix Fillingham&lt;/LI&gt;&lt;LI&gt;&lt;CITE&gt;Unlocking the Clubhouse: Women in Computing&lt;/CITE&gt; by Jane
Margolis and Allan Fisher&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;My recommendations from the above list are: &lt;CITE&gt;Daemon&lt;/CITE&gt;,
which is essentially &lt;CITE&gt;Halting State&lt;/CITE&gt; cranked to 11.  The
assembly line was an excellent representation of the lure behind MMOs.
&lt;CITE&gt;Whole Earth Discipline&lt;/CITE&gt; was a challenging book, especially
if you lean &amp;ldquo;green.&amp;rdquo; I understand the positive side of
postmodern thought much better after reading &lt;CITE&gt;The Next
Reformation&lt;/CITE&gt;; &lt;CITE&gt;Who's Afraid of Postmodernism&lt;/CITE&gt; can serve
the same purpose, but as it focuses on Foucault, Derrida, and Lyotard,
it doesn't give one quite as much history or as broad an understanding
as &lt;CITE&gt;The Next Reformation&lt;/CITE&gt;.&lt;/P&gt;&lt;P&gt;Honorable mentions: &lt;CITE&gt;Unlocking the Clubhouse&lt;/CITE&gt; gave me a
 lot to think about with raising two little girls and exposing them to
 technology (which I admittedly haven't done very much of beyond
 twiddling with iTunes and explaining how to play CDs in the PS2).  I
 appreciated the vision that &lt;CITE&gt;Cradle to Cradle&lt;/CITE&gt; presented; I
 wish all books were made out of similar material, both for the
 pleasantness of heft and for the eco-friendliness.  &lt;CITE&gt;The
 Price of Spring&lt;/CITE&gt; was just as good as I expected it to be.  If you
 like fantasy and you haven't read Daniel Abraham's Long Price Quartet,
 you ought to start now.&lt;/P&gt;&lt;P&gt;What didn't make the list above?  I tried reading &lt;CITE&gt;One
 Market Under God&lt;/CITE&gt; by Thomas Frank, but I only made it about a
 quarter of the way through before I got sick of his smug know-it-all
 tone.  I've mostly finished &lt;CITE&gt;Discussion of t&lt;U&gt;h&lt;/U&gt;e
 Method&lt;/CITE&gt; by Billy Vaughn Koen, which serves much the same purpose for
 the engineer-ingly bent among us as &lt;CITE&gt;G&amp;ouml;del, Escher,
 Bach&lt;/CITE&gt; did for computer scientists.  I skimmed through &lt;CITE&gt;No
 Easy Answers&lt;/CITE&gt; by Allan Franklin; his descriptions of famous physics
 experiments were interesting, but past the first one or two, they
 didn't really draw me in.  The description of the Meselson-Stahl
 experiment that proved how DNA replicated is worth a read, though.&lt;/P&gt;</description><category>books</category></item><item><title>cities and redemption</title><link>http://www.method-combination.net/blog/archives/2010/02/18/cities-and-redemption.html</link><pubDate>Thu, 18 Feb 2010 14:30:00 CDT</pubDate><description>&lt;P&gt;From &lt;CITE&gt;Sidewalks in the Kingdom&lt;/CITE&gt; by Eric Jacobsen:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;...This radical change in the status of the city from
 a place of sin and unfaithfulness to the ultimate context for our
 redemption raises at least one important question: What can account for
 such a radical shift?  Why did God take what looks to be one of
 humanity's worst inventions and use it as the primary context for our
 redemption?&lt;/P&gt;&lt;P&gt;The answer to this question is to be found in the question itself.
 Our God is fundamentally a God of &lt;EM&gt;redemption&lt;/EM&gt;.  God takes us
 (and our decisions) seriously.  When we make mistakes--even profound
 ones--God does not obliterate the scars these mistakes leave on our
 character and start over.  Rather, God takes our mistakes and reworks
 them into his divine plan and transforms our scars into something
 beautiful.  Joseph said to his brothers when they repented of selling
 him into slavery, &amp;ldquo;Even though you intended to do harm to me, God
 intended it for good.&amp;rdquo;  So also it seems that God has said of our
 cities, &amp;ldquo;You meant them to be a form of escape from me, I used
 them to draw you back to me.&amp;rdquo;&lt;/P&gt;&lt;P&gt;And we see hints of this redemption theme all around the cities of
 the Bbible.  Cain's desire to flee to Enoch after killing his brother
 later finds a redeemed expression in the cities of refuge.  The fear of
 the residents of Babel that they might be scattered is redeemed when
 the Isrelites find cities in the Promised Land in which they can
 gather.  The Hebrews long to be free from their tyrant, Pharoah, and
 eventually found a good king in the city of David.  And finally, the
 Babel residents' desire to make a name for themeselves is met in
 Jerusalem, where God has caused his name to dwell.&lt;/P&gt;&lt;P&gt;Redemption shows that God's power to redeeem and restore is
stronger than our ability to alienate and break down.  But redemption is
not always the strategy that we would chose if it were up to us.  Often
what we seek is a return to innocence.  We want to forget about the past
and start over.  Psychologically, we repress painful memories.
Relationally, we cut ourselves off from people who remind us our past.
And culturally, we ignore our history in favor of what is new and
current.&lt;/P&gt;&lt;P&gt;...But for those who seek to take the Bible seriously, this cannot
be our strategy.  We cannot hate the city when our God is using it for
good.  We can suport the city from a truly rural setting, but we cannot
retreat to our own private gardens.  That way has been closed off.  We
must at some level learn to take our cities seriously.  Whether live,
work, worship, and play in our imperfect cities, or even just for them
at a distance, we need to look to our cities if we hope to catch a
glimpse of what God has in store for us.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;I approve of the strategy of incrementalism.  Starting over can be
 an option, but the opportunity to do so happens so infrequently that we
 are danger of idolizing it.  Not just in cities, but in other contexts,
 too.&lt;/P&gt;</description><category>culture</category><category>redemption</category><category>cities</category><category>books</category><category>quotes</category></item><item><title>banks asking for regulation</title><link>http://www.method-combination.net/blog/archives/2010/01/22/banks-asking-for-regulation.html</link><pubDate>Fri, 22 Jan 2010 21:52:00 CDT</pubDate><description>&lt;P&gt;If banks are going to continue in their expectations that the
 government is going to bail them out, then the government is
 naturally--regardless of arguments from the left for increased
 regulation or from the right for steering clear of the self-correcting
 market--&lt;A HREF=&quot;http://www.usatoday.com/money/industries/banking/2010-01-21-obama-backs-bank-limits_N.htm&quot;&gt;going to impose regulations&lt;/A&gt; to make it less likely that banks will
 place themselves in a position in which a bailout is necessary.  Simple
 economics.  You can debate back and forth about the popular merits of
 such a decision and the political maneuvering that comes with that.
 But the government is acting in its own self-interest in this case,
 plain and simple.  The banks are getting exactly what they asked for.&lt;/P&gt;</description><category>politics</category><category>economics</category></item><item><title>grouchy c programmer</title><link>http://www.method-combination.net/blog/archives/2010/01/15/grouchy-c-programmer.html</link><pubDate>Fri, 15 Jan 2010 22:05:00 CDT</pubDate><description>&lt;P&gt;Whenever possible, feature macros in C should be &lt;TT&gt;#define&lt;/TT&gt;'d to 0 or 1, rather than letting the definedness or lack thereof be
 the switch for the feature.  This convention means that you can talk
 about the feature macro in conditions, rather than having to jump
 through hoops to do so.  (Doing so also means that you can play clever
 tricks in code with said feature macros if need be...)  Of course, this
 implies that your compiler needs to be intelligent about dead code
 elimination in the presence of disabled features, but what compiler
 isn't?&lt;/P&gt;&lt;P&gt;Also, to all the hotspot rockstar programmers out there who are
 enormously impressed with their ability to record key routines from the
 C library using whizbang vector instructions and cache control
 instructions and show massive speedups: please try to actually test
 your code to ensure that it has the same correctness properties as the
 code in the C library.  Nobody cares how fast your routines are if they
 cause buffer overflows on real-world code, rather than the trivial
 benchmark you threw together.&lt;/P&gt;</description><category>programming</category><category>rants</category></item><item><title>ice skating</title><link>http://www.method-combination.net/blog/archives/2010/01/01/ice-skating.html</link><pubDate>Fri, 01 Jan 2010 23:33:00 CDT</pubDate><description>&lt;P&gt;We took the girls ice skating yesterday.  Becca liked it so much
 that she declared that she wanted to go back today.  So we did that,
 with one change: I put on skates today and went out on the ice.
 Yesterday was mostly holding onto Ally while Becca was on the ice or
 vice versa.  Tricia was going to send me out on my own.&lt;/P&gt;&lt;P&gt;&amp;ldquo;I'm not sure I've ever been out without holding onto
 somebody before,&amp;rdquo; I said.&lt;/P&gt;&lt;P&gt;&amp;ldquo;How many times have you been ice skating before?&amp;rdquo;&lt;/P&gt;&lt;P&gt;&amp;ldquo;Two.&amp;rdquo;&lt;/P&gt;&lt;P&gt;&amp;ldquo;How old were you?&amp;rdquo;&lt;/P&gt;&lt;P&gt;&amp;ldquo;Twenty-one.&amp;rdquo;&lt;/P&gt;&lt;P&gt;As you can guess, I haven't had much experience ice skating.  By
 the end of the public skate session, though, I had managed to make it
 around the rink a couple times at a fair distance from the side.  I
 even managed to take both of the girls out all by myself--and let me
 tell you, that was about the most fun I've had with my children in a
 while.&lt;/P&gt;&lt;P&gt;I was so proud of Becca too, for really trying to skate both days.
 She even managed to travel short distances (a couple of yards) on her
 own.&lt;/P&gt;</description><category>family</category><category>life</category></item><item><title>a geek's lament</title><link>http://www.method-combination.net/blog/archives/2009/12/30/a-geeks-lament.html</link><pubDate>Wed, 30 Dec 2009 22:51:00 CDT</pubDate><description>&lt;P&gt;Somebody more skilled in humorish things than I needs to write a
 piece in the style of &lt;A HREF=&quot;http://paws.kettering.edu/~jhuggins/humor/essay.html&quot;&gt;A college admission essay&lt;/A&gt;.
 In this piece, the author would set forth his geek credentials.
 Examples:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;I have a four-digit Slashdot user id.&lt;/LI&gt;&lt;LI&gt;I installed Slackware when it only had 12 diskettes.&lt;/LI&gt;&lt;LI&gt;I won an argument with Ulrich Drepper.&lt;/LI&gt;&lt;LI&gt;I &lt;TT&gt;-funroll-all-loops&lt;/TT&gt;.&lt;/LI&gt;&lt;LI&gt;I taught Chuck Norris everything he knows.&lt;/LI&gt;&lt;LI&gt;I know Bruce Schneier's password.&lt;/LI&gt;&lt;LI&gt;I have successfully rickrolled somebody.&lt;/LI&gt;&lt;LI&gt;I survived the Eternal September.&lt;/LI&gt;&lt;LI&gt;I have ascended with every character class.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;...and so forth, perhaps more outlandishly than I have done above.
 After a suitably long listing of all these feats of geekdom in suitably
 stylistic prose, the essay should conclude with:&lt;/P&gt;&lt;P&gt;&amp;ldquo;But I have not yet figured out the usefulness of Google
 Wave.&amp;rdquo;&lt;/P&gt;</description><category>humor</category><category>geek</category></item><item><title>suitcase parent hack</title><link>http://www.method-combination.net/blog/archives/2009/12/29/suitcase-parent-hack.html</link><pubDate>Tue, 29 Dec 2009 22:03:00 CDT</pubDate><description>&lt;P&gt;When we asked the girls what they wanted to buy with their
 Christmas gift money this year, they responded that they wanted little
 travel suitcases.  Neither one of us wanted to buy a little
 rickety suitcas with thin vinyl siding plastered with the cartoon
 character &lt;EM&gt;du jour&lt;/EM&gt;, though.  We wanted to buy something that
 would last for a while and even be useful beyond these next couple of
 years.&lt;/P&gt;&lt;P&gt;We looked around online, but children's luggage is rather
 boutique-ish.  So it looked like we'd have to go with the cheap plastic
 luggage or with some boutique luggage that would very nearly break the
 bank.&lt;/P&gt;&lt;P&gt;We were able to go out on a date today and were wandering around TJ
 Maxx when we noticed a bright orange Columbia rolling carry-on.  It was
 a standard adult size, but it was definitely on the small side.  It was
 also heavily discounted.  We looked around a little more and found a
 slightly smaller red Wenger rolling carry-on as well as a blue Columbia
 bag of the same style as the orange one.&lt;/P&gt;&lt;P&gt;The Wenger bag was about half again as much as your standard
 plastic luggage; the Columbia bag was a little bit more than twice as
 much.  Both were significantly cheaper than the other options we'd seen
 online, though.  Both bags can easily accommodate a week's worth of
 clothes for several years.  Even when the girls get older, they can fit
 a couple days' worth of clothes in the bags.  So they win on the price
 and practicality fronts.&lt;/P&gt;&lt;P&gt;At this point, however, the girls appreciate the color most.  I
suppose they appreciate the size of the bags, since they can fit a lot
of doll clothes in them.  (We got the blue Columbia one and the red
Wenger one.)&lt;/P&gt;&lt;P&gt;Anyway, that's the parent hack of the day: discounted adult luggage
for children.&lt;/P&gt;</description><category>parenting</category><category>hacks</category></item><item><title>clos initialization protocol</title><link>http://www.method-combination.net/blog/archives/2009/12/22/clos-initialization-protocol.html</link><pubDate>Tue, 22 Dec 2009 16:40:00 CDT</pubDate><description>&lt;P&gt;&lt;STRONG&gt;Update:&lt;/STRONG&gt; Tobias Rittweiler pointed out that I don't
need &lt;TT CLASS=&quot;hyperspec&quot;&gt;&amp;amp;ALLOW-OTHER-KEYS&lt;/TT&gt; in my method
definitions; &lt;TT CLASS=&quot;hyperspec&quot;&gt;&amp;amp;ALLOW-OTHER-KEYS&lt;/TT&gt; was
already declared in the &lt;TT CLASS=&quot;hyperspec&quot;&gt;DEFGENERIC&lt;/TT&gt; and
isn't required in individual methods.  Furthermore, putting &lt;TT CLASS=&quot;hyperspec&quot;&gt;&amp;amp;ALLOW-OTHER-KEYS&lt;/TT&gt; in your method
definitions when it's already been declared in &lt;TT CLASS=&quot;hyperspec&quot;&gt;DEFGENERIC&lt;/TT&gt; inhibits useful argument checking.  So don't
do that.  I've fixed the examples below.&lt;/P&gt;&lt;P&gt;From the last blog post, we saw that &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; is a useful way to reduce consing.  You say,
 &amp;ldquo;well, sure, that's why I have &lt;TT CLASS=&quot;hyperspec&quot;&gt;RESET-FOO&lt;/TT&gt; functions in the library/application that I'm
 writing.&amp;rdquo; I'd like to suggest that if you've written such
 functions, you ought to be writing &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; methods (if you're resetting structures) or
 writing &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; methods on the usual
 CLOS initialization protocol methods instead.  Doing so is more Lispy
 than the usual reset functions.  Writing to the existing protocol also
 encourages you to more clearly define what's initialization, what's
 reinitialization, and what can be shared between them.&lt;/P&gt;&lt;P&gt;&amp;ldquo;OK,&amp;rdquo; you say, &amp;ldquo;but what are these CLOS methods and
how do I use them?&amp;rdquo;  Glad you asked.&lt;/P&gt;&lt;P&gt;There are three major generic functions that participate in the protocol:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_init_i.htm&quot;&gt;&lt;TT&gt;initialize-instance&lt;/TT&gt;&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_reinit.htm&quot;&gt;&lt;TT&gt;reinitialize-instance&lt;/TT&gt;&lt;/A&gt;&lt;/LI&gt;&lt;LI&gt;&lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_shared.htm&quot;&gt;&lt;TT&gt;shared-initialize&lt;/TT&gt;&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;As you might imagine, &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITIALIZE-INSTANCE&lt;/TT&gt; is called from &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt; and &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; is called from, well, &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt;.  &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; is called from both &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITIALIZE-INSTANCE&lt;/TT&gt; and &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; and handles bits common to both methods.
We'll focus on &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;
because it underpins the other two and because &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; is also called when updating class
definitions and changing the class of an instance.  You get a lot of
things for free when writing methods for &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;.&lt;/P&gt;&lt;P&gt;First things first: you generally only want to write after methods on
&lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;, viz:&lt;/P&gt;&lt;PRE&gt;(defmethod shared-initialize :after ((object my-class) slot-names &amp;amp;rest initargs &amp;amp;key)
  ...)&lt;/PRE&gt;&lt;P&gt;The reason you do this is because the primary method on &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; already does a lot of useful
things, like initializing slots from their &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITFORM&lt;/TT&gt;s and &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITARG&lt;/TT&gt;s.  (For
the same reason, you should generally use &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; methods for &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITIALIZE-INSTANCE&lt;/TT&gt; and &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt;.)  You can, of course, write:&lt;/P&gt;&lt;PRE&gt;(defmethod shared-initialize ((object my-class) slot-names &amp;amp;rest initargs &amp;amp;key)
  (call-next-method)
  ...)&lt;/PRE&gt;&lt;P&gt;But that's generally not how things are done.  I think writing &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; methods makes your intent clearer:
you're doing extra work after the standard bits have been done.  It's
also easy to forget to &lt;TT CLASS=&quot;hyperspec&quot;&gt;CALL-NEXT-METHOD&lt;/TT&gt;, which would lead to puzzling behavior and also might lead you to
submit spurious bug reports like &amp;ldquo;CLOS initialization doesn't work
with user-defined classes&amp;rdquo;.  Also, method combination is often
more useful and more declarative than trying to get &lt;TT CLASS=&quot;hyperspec&quot;&gt;CALL-NEXT-METHOD&lt;/TT&gt; in the right place.  That doesn't
mean &lt;TT CLASS=&quot;hyperspec&quot;&gt;CALL-NEXT-METHOD&lt;/TT&gt; doesn't have its
place, it just means I think method combination should be preferred when
possible.&lt;/P&gt;&lt;P&gt;OK, so, onto initializing things.  What's this &lt;TT CLASS=&quot;hyperspec&quot;&gt;SLOT-NAMES&lt;/TT&gt; parameter?  &lt;TT CLASS=&quot;hyperspec&quot;&gt;SLOT-NAMES&lt;/TT&gt; is a (possibly empty) list of slot names that need to be
initialized from their &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITFORM&lt;/TT&gt;s, or &lt;TT CLASS=&quot;hyperspec&quot;&gt;T&lt;/TT&gt; to stand in for &amp;ldquo;all
slots&amp;rdquo;.  For our purposes here, we are going to assume that &lt;TT CLASS=&quot;hyperspec&quot;&gt;SLOT-NAMES&lt;/TT&gt; is only ever &lt;TT CLASS=&quot;hyperspec&quot;&gt;T&lt;/TT&gt; (for when &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; is called from &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITIALIZE-INSTANCE&lt;/TT&gt;) or &lt;TT CLASS=&quot;hyperspec&quot;&gt;NIL&lt;/TT&gt; (for
when &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; is called from &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt;).  In the &lt;TT CLASS=&quot;hyperspec&quot;&gt;T&lt;/TT&gt; case, the primary method on &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; handles the initialization logic.
So we don't have to worry too much about &lt;TT CLASS=&quot;hyperspec&quot;&gt;SLOT-NAMES&lt;/TT&gt;.&lt;/P&gt;&lt;P&gt;You can also mostly ignore &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITARGS&lt;/TT&gt;.  Most of the keyword-argument pairs in it will have been handled
elsewhere by standard CLOS bits.  Any bits that are interesting to you
will be pulled out via separate &lt;TT CLASS=&quot;hyperspec&quot;&gt;&amp;amp;KEY&lt;/TT&gt; arguments; we'll get to that use-case in a second.&lt;/P&gt;&lt;P&gt;OK, so what useful things can we do in &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;?  We can recompute slots that depend on the
values of other slots and therefore can't be usefully initialized with &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITFORM&lt;/TT&gt; or &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITARG&lt;/TT&gt;:&lt;/P&gt;&lt;PRE&gt;(defclass triangle ()
  ((a :initarg :a :reader a)
   (b :initarg :b :reader b)
   (c :initarg :c :reader c)
   (area :reader area)))

(defmethod shared-initialize :after ((o triangle) slot-names &amp;amp;rest initargs &amp;amp;key)
  (let ((area (compute-area-of-triangle (a o) (b o) (c o))))
    (setf (slot-value o 'area) area)))&lt;/PRE&gt;&lt;P&gt;In cases like this, you might be tempted to write some sort of
wrapper (with the appropriate modification to the definition of
&lt;TT CLASS=&quot;hyperspec&quot;&gt;TRIANGLE&lt;/TT&gt;):&lt;/P&gt;&lt;PRE&gt;(defun make-triangle (a b c)
  (let ((area (compute-area-of-triangle a b c)))
    (make-instance 'triangle :a a :b b :c c :area area)))&lt;/PRE&gt;&lt;P&gt;which is certainly doable (I'll leave the subject of whether to
wrap &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt; or expose it
directly to users in your API for a future post).  But this sort of
wrapper doesn't easily enable reinitialization.  Consider what your
hand-crafted &lt;TT CLASS=&quot;hyperspec&quot;&gt;RESET-TRIANGLE&lt;/TT&gt; function
might look like to handle all the cases the &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; method would handle for free:&lt;/P&gt;&lt;PRE&gt;(defun reset-triangle (triangle &amp;amp;key a b c)
  (let ((a (or a (a triangle)))
        (b (or b (b triangle)))
        (c (or c (c triangle))))
    (setf (slot-value triangle 'a) a
          (slot-value triangle 'b) b
          (slot-value triangle 'c) c
          (slot-value triangle 'area) (compute-area-of-triangle a b c))
    triangle))&lt;/PRE&gt;&lt;P&gt;Notice that you've duplicated slot setting (the CLOS internals
handle that for you) and you're computing the area of the triangle in
two different, but related (both part of initialization) places.  You
might say that you only want users resetting all three sides of a
triangle, so the API should reflect that.  Maybe.  But in that case, you
should be the one calling &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt;, and you'd wind up going the &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; route anyway.  I think the &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; method also better captures
what it means to compute the area: the computation of the area is an
integral part of initialization, rather than something that you do
beforehand prior to creating the object.&lt;/P&gt;&lt;P&gt;For a less pedagogical example, let's say you have a cool encryption
algorithm:&lt;/P&gt;&lt;PRE&gt;(defclass les () ; the LISP encryption standard
  ((round-keys :reader round-keys)
   (n-rounds :reader n-rounds)))

(defmethod shared-initialize :after ((o les) slot-names &amp;amp;rest initargs &amp;amp;key key)
  (multiple-value-bind (round-keys n-rounds) (schedule-key key)
    (setf (slot-value o 'round-keys) round-keys
          (slot-value o 'n-rounds) n-rounds)))&lt;/PRE&gt;&lt;P&gt;You may have noticed that &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; takes a &lt;TT CLASS=&quot;hyperspec&quot;&gt;KEY&lt;/TT&gt;
keyword argument above, even though there's no &lt;TT CLASS=&quot;hyperspec&quot;&gt;:INITARG&lt;/TT&gt; &lt;TT CLASS=&quot;hyperspec&quot;&gt;:KEY&lt;/TT&gt; in the
&lt;TT CLASS=&quot;hyperspec&quot;&gt;DEFCLASS&lt;/TT&gt; form.  One cool thing about &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; is that any &lt;TT CLASS=&quot;hyperspec&quot;&gt;&amp;amp;KEY&lt;/TT&gt; arguments to it automatically become
candidates for use with &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt;
and the other generic functions that participate in the initialization
protocol.  This feature enables you to pass keyword arguments to &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt; that aren't directly connected
with slots, but require massaging in some way to produce something
suitable for slot values.  So using the above, you say:&lt;/P&gt;&lt;PRE&gt;(defvar *l* (make-instance 'les :key #(#xde #xad #xbe #xef)))
...lots of code...
;; sometime later
(reinitialize-instance *l* :key #(#xca #xfe #xbe #xbe))&lt;/PRE&gt;&lt;P&gt;Again, you could use wrapper functions.  But I think the same
arguments cited above for clarity and for not repeating yourself apply
here as well.  (And if you're really serious about this encryption
stuff, you also want to be able to reset the initialization vector/nonce
for your encryption mode and possibly even to change the encryption mode
entirely.  Once you've done that, you've basically rewritten &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;, and you have potentially
duplicated logic between your &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt; wrapper and your reset function.)&lt;/P&gt;&lt;P&gt;Another reason to have &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; methods is because they naturally cooperate with
subclassing.  Let's say you're dealing with some packaging format and
you're creating entries from octet vectors:&lt;/P&gt;&lt;PRE&gt;(defclass entry ()
  ...slots...)

(defun make-entry-from-buffer (buffer &amp;amp;key (start 0))
  (let (...parse out individual slots from BUFFER...)
    (make-instance 'entry ...initargs for slots...)))&lt;/PRE&gt;&lt;P&gt;Fine and dandy.  Now let's say that your customers tell you about
packaging format v2, which mostly retains the format of v1, but adds a
way of specifying additional metadata as part of the entries.  OK:&lt;/P&gt;&lt;PRE&gt;(defclass entry-v2 (entry)
  ...more slots...)

(defun make-entry-from-buffer (buffer &amp;amp;key (start 0))
  ;; A `2' at the start of the buffer indicates a version 2 entry.
  (if (= (aref buffer start) 2)
      (make-entry-v2-from-buffer buffer :start start)
      (make-entry-v1-from-buffer buffer :start start)))&lt;/PRE&gt;&lt;P&gt;Hm.  We want to initialize the slots in an entry in a common place,
so as to avoid code duplication:&lt;/P&gt;&lt;PRE&gt;(defun initialize-common-entries (entry buffer &amp;amp;key (start 0))
  (let (...parse out individual slots from BUFFER...)
    (setf ...lots of slots...)
    entry))

(defun make-entry-v2-from-buffer (buffer &amp;amp;key (start 0))
  (let ((entry (make-instance 'entry-v2)))
    (setf ...new slots for ENTRY-V2...)
    (initialize-common-entries entry buffer :start start)))&lt;/PRE&gt;&lt;P&gt;and so on.  Possibly with slight adjustments because parsing the
slots for &lt;TT CLASS=&quot;hyperspec&quot;&gt;ENTRY-V2&lt;/TT&gt; might depend on the
values of one or more of the common slots in &lt;TT CLASS=&quot;hyperspec&quot;&gt;ENTRY&lt;/TT&gt;.  I claim that this is more elegantly handled by:&lt;/P&gt;&lt;PRE&gt;(defmethod shared-initialize :after ((o entry) slot-names &amp;amp;rest initargs &amp;amp;key buffer start)
  (let (...parse out individual slots from BUFFER...)
    (setf ...lots of slots...)
    o))

(defmethod shared-initialize :after ((o entry-v2) slot-names &amp;amp;rest initargs &amp;amp;key buffer start)
  (let (...parse out individual slots from BUFFER...)
    (setf ...slots for ENTRY-V2...)
    o))

(defun make-entry-from-buffer (buffer &amp;amp;key (start 0))
  ;; A `2' at the start of the buffer indicates a version 2 entry.
  (if (= (aref buffer start) 2)
      (make-instance 'entry-v2 :buffer buffer :start start)
      (make-instance 'entry :buffer :start start)))&lt;/PRE&gt;&lt;P&gt;Since &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; methods run in
least-specific-first order, the &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt;
method on &lt;TT CLASS=&quot;hyperspec&quot;&gt;ENTRY&lt;/TT&gt; will be called first.
The &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; method on &lt;TT CLASS=&quot;hyperspec&quot;&gt;ENTRY-V2&lt;/TT&gt; can therefore freely use the value of any
slots from &lt;TT CLASS=&quot;hyperspec&quot;&gt;ENTRY&lt;/TT&gt;.  Using &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt; here not only enables &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt;, it also does the right thing in
handling common code from a software engineering perspective.&lt;/P&gt;&lt;P&gt;Of course, if you have code that specifically needs to run at &lt;TT CLASS=&quot;hyperspec&quot;&gt;MAKE-INSTANCE&lt;/TT&gt; time, or &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; time, then you can add &lt;TT CLASS=&quot;hyperspec&quot;&gt;:AFTER&lt;/TT&gt; methods to &lt;TT CLASS=&quot;hyperspec&quot;&gt;INITIALIZE-INSTANCE&lt;/TT&gt; or &lt;TT CLASS=&quot;hyperspec&quot;&gt;REINITIALIZE-INSTANCE&lt;/TT&gt; as appropriate.  For instance, if all of your
objects need to have a unique ID, you surely don't want to assign a
unique ID in &lt;TT CLASS=&quot;hyperspec&quot;&gt;SHARED-INITIALIZE&lt;/TT&gt;.&lt;/P&gt;&lt;PRE&gt;(defclass unique-id-mixin ()
  ((unique-id :reader unique-id)))

(defmethod initialize-instance :after ((o unique-id-mixin) &amp;amp;rest initargs &amp;amp;key)
  (setf (slot-value o 'unique-id) (get-unique-id-for-instance o)))&lt;/PRE&gt;&lt;P&gt;(You might, however, want to assign a different unique ID if
somebody &lt;A CLASS=&quot;hyperspec&quot; HREF=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_chg_cl.htm&quot;&gt;&lt;TT&gt;change-class&lt;/TT&gt;&lt;/A&gt;'ed your object.  That's a topic for future
discussion; I only sort-of understand the protocol involved in &lt;TT CLASS=&quot;hyperspec&quot;&gt;CHANGE-CLASS&lt;/TT&gt; and I have yet to see really
pragmatic reasons for adding methods to the generic functions
involved.)&lt;/P&gt;&lt;P&gt;I know that my code doesn't always work according to the ideas I've
laid out above; it's taken me a while to wrap my head around what goes
where and why.  But now that I understand, I'm slowly modifying my code
to use these ideas.  Where can your code benefit from these ideas?&lt;/P&gt;</description><category>lisp</category><category>programming</category></item><item><title>archive release</title><link>http://www.method-combination.net/blog/archives/2009/12/18/archive-release.html</link><pubDate>Fri, 18 Dec 2009 23:11:00 CDT</pubDate><description>&lt;P&gt;I've released &lt;A HREF=&quot;http://cliki.net/archive&quot;&gt;ARCHIVE&lt;/A&gt;
 0.8.  It features an assortment of bugfixes, including fixes for
 extraction of tar files and fixes for Lispworks/Win32 users.  This
 version also understands POSIX global headers in tar files, so if
 you've been getting complaints about &amp;ldquo;unknown typeflag 103&amp;rdquo;
 or similar, now would be a good time to upgrade.  It is available from
 the usual places, including &lt;A HREF=&quot;http://github.com/froydnj/archive&quot;&gt;straight from github&lt;/A&gt;.  (And
 like a git n00b, I've managed to botch the tagging of 0.8.  The tag of
 0.8 is almost right, except the version number in the .asd is
 wrong...sigh.)&lt;/P&gt;</description><category>lisp</category></item><item><title>surveillance clock</title><link>http://www.method-combination.net/blog/archives/2009/12/18/surveillance-clock.html</link><pubDate>Fri, 18 Dec 2009 20:24:00 CDT</pubDate><description>&lt;P&gt;One of the more interesting (and frightening) pieces I've read in
 a while is Jeff Jonas's &lt;A HREF=&quot;http://jeffjonas.typepad.com/jeff_jonas/2007/10/six-ticks-till-.html&quot;&gt;Six Ticks till Midnight: One Plausible Journey from Here to a Total
 Surveillance Society&lt;/A&gt;.  He explains the ACLU's &lt;A HREF=&quot;http://www.aclu.org/technology-and-liberty/surveillance-society-clock&quot;&gt;Surveillance Society Clock&lt;/A&gt; and exactly why it's set where it is by
 laying out the rough sketches of what needs to happen before the
 activities of everybody can be tracked 24-7.  (Aside: the ACLU utterly
 failed at this.  If you look at their site without reading Jonas's
 post, it looks like general fear-mongering, since they don't provide
 any explanation of &lt;EM&gt;why&lt;/EM&gt; the clock is where it is.)  Also
 note the clock has moved up one minute since Jonas's post two years
 ago.&lt;/P&gt;&lt;P&gt;The really amusing/interesting/chilling part is this:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Oh yeah, one more thing, no more need for facial
 recognition (a very hard problem many years off anyway). In this coming
 world, all that useless video being collected can now be efficiently
 recalled because GPS data provides the missing link … who was where
 when?&lt;/P&gt;&lt;P&gt;While the exact technologies or the exact sequence of events may
 unfold quite differently, nonetheless such a future is coming. And this
 future is being created by us consumers, not the government!&lt;/P&gt;&lt;P&gt;Consumers are funding the surveillance economy, with the blistering
 pace of this extraordinary surveillance being driven by ordinary people
 who relish all the technological advances and willing to entirely trade
 in their information and privacy as they optimize their life.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;One of the reasons I've become very interested in reading about
 history--a subject which I disliked in school--is this idea of
 unintended consequences.  (The same principles come up in
 economic/political discussions too, except nobody seems to care...wait,
 that's exactly how history works, too.)  Luther, for instance, almost
 certainly had no intention of producing the individualistic evangelical
 culture we have today--but you can trace a pretty convincing path
 between the two.  Or economists making decisions based on some
 particular model of things and convincing themselves that said
 decisions will have the desired effect--without realizing that those
 same decisions are changing fundamental assumptions undergirding the
 model.  (William Greider's &lt;CITE&gt;Secrets of the Temple&lt;/CITE&gt;, which
 discusses the Federal Reserve's actions under Paul Volcker, has several
 examples of this.)  There's no grand cabal of people, no portly,
 mustached executives and bureaucrats carefully designing a system to
 track everybody everywhere--&lt;A HREF=&quot;http://jeffjonas.typepad.com/jeff_jonas/2009/08/your-movements-speak-for-themselves-spacetime-travel-data-is-analytic-superfood.html&quot;&gt;we are doing this to ourselves&lt;/A&gt;.&lt;/P&gt;</description><category>culture</category><category>technology</category><category>politics</category></item></channel></rss>