<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6508797467947601724</id><updated>2011-11-27T19:47:09.640-05:00</updated><category term='Consing Mariano Rivera Lisp mastery'/><category term='reading comprehension'/><category term='Road to Lisp'/><category term='scheme'/><category term='Silver bullet'/><category term='dynamic binding'/><category term='writing Lisp comedy Socrates Izzard'/><category term='javascript ajax jquery dojo qooxdoo yui comparison'/><category term='Lisp qooxdoo QxTransformer Dojo Yui Web 2.0 development Javascript framework PHP Python'/><category term='Clojure Scala Groovy Coherent Reaction Trellis Cells Guy Steele James Strachan Johnathan Edwards'/><category term='Cells'/><category term='Flapjax'/><category term='quotations'/><category term='arc'/><category term='OpenLaszlo Cells dataflow FRP reactive programming'/><category term='Finite state machine software engineering'/><category term='ZenLisp Scheme Nils Holm McCarthy Hopper Knuth'/><category term='lisp'/><category term='30day'/><category term='Kenny Tilton'/><category term='Tilton&apos;s Law software engineering'/><category term='Trellis'/><category term='paul graham'/><category term='Dataflow'/><category term='academia'/><category term='Nike Spike Lee Michael Jordam shoes Lisp'/><category term='Lisp Erik Naggum quads XML SGML HTML'/><category term='Macros Arc Common Lisp Python'/><category term='baseball Larry Ritter book review'/><category term='Chomsky Pinker skateboards drinking'/><category term='Programming design Taoism'/><category term='alan turing'/><category term='math eductaion'/><category term='special variables'/><category term='Clinical drug trial management software Lisp'/><category term='Cobol Macros Tall Buildings Metaprogramming'/><category term='Lisp ASDF tutorial guide beginner help build make system defintion'/><category term='Common Lisp'/><category term='Lisp packahes symbols interned uninterned case sensitivity noobs problems tutorials help'/><category term='Lisp Macros Python C'/><category term='McCarthy'/><category term='Lisp consing solar power torpedos molasses tuning'/><category term='Cells ECLM OOPS Fred Brooks No Silver Bullet dataflow FRP functional reactive programming'/><category term='Tilton&apos;s Law DBMS bugs Tandy COBOL'/><category term='Functional reactive programming'/><category term='javascript ajax frameworks qooxdoo RIA Web 2.0 Lisp jQuery Dojo YUI HTML CSS'/><category term='language design'/><title type='text'>smuglispweeny</title><subtitle type='html'>Grossly unfair, unreliable, biased, and pretty much delusional rants and ravings on Lisp from a simple working application programmer.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5574063229675590871</id><published>2010-08-28T18:56:00.008-04:00</published><updated>2010-08-28T20:45:28.398-04:00</updated><title type='text'>Fortune Cookie File Number Two</title><content type='html'>Wow, what an effort! Nice followup to &lt;a href="http://smuglispweeny.blogspot.com/2008/02/what-hell-is-fortune-cookie-file-anyway.html"&gt;part one&lt;/a&gt;! Thx, Madhu!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;Are you trying to win a Moron Contest*, or did I miss a joke?&lt;br /&gt;        -- Kenneth Tilton &lt;br /&gt;%&lt;br /&gt;[Quoting some "Bell Labs engineer" from the Newark Star Ledger]&lt;br /&gt;&lt;br /&gt;"The hardest part for me was realizing I was being tolerated by all the people I had been tolerating."&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;That is a metaquestion.  No metaquestions allowed under Obama.  Note that this is a metametaanswer, it's like minus signs, ya got two ya ain't got any.  With me so far?&lt;br /&gt;        -- Kenneth Tilton &lt;br /&gt;%&lt;br /&gt;Let's decide on the shape of the table before deciding if the discussion to decide if free open software is ethical is going anywhere.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Pioneers do not wait for the rest areas on the interstate highway to&lt;br /&gt;have sushi bars.&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;The Mac I have now sounds like a 747 turbine after spinning up, can't&lt;br /&gt;even hear The Voices let alone program a computer.&lt;br /&gt;        -- Kenny &lt;490ba086$0$5643$607ed...@cv.net&gt;&lt;br /&gt;%&lt;br /&gt;What part of Anna Kournikova do you not understand?&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;That will be well-received, and when Anna Kournikova sends you an&lt;br /&gt;email asking you to come spend a week with her you complain that she misspelled Tahiti and the airline tickets she sent were not first-class and write back asking if she knows anyone prettier you could stay with?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I think Celtk just needs Cells.  This is like saying that if you want&lt;br /&gt;Anna Kournikova to have your baby then you have to sleep with her.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Anna played tennis?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Muhammed ibn Musa al-Khowarizmi!  He wrote the book on Algebra!&lt;br /&gt;Literally.  Not sure where I can get a picture, tho.  Maybe I can give&lt;br /&gt;Anna a beard...&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I feel a naggum coming on.  When you think you know what I am thinking try to stop thinking.&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;[...] you should -- I feel a naggum coming on -- stop trying to impose&lt;br /&gt;your prior understanding on a new experience.  You are like an&lt;br /&gt;American tourist landing in Kinshasha and going in search of a Burger&lt;br /&gt;King.  Sadly they do not have to go far.&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;I feel a Naggum coming on.  Before you contradict me or challenge me or quote me, please make sure you are not in fact talking about an inferior model of me rooting around somewhere in your cortex (and what a scary image that is).&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;New Yorkers are not offensive.  The joke is a good one (The proper way to ask for directions in NYC? "Excuse me, can you tell me the way to Lincoln Center, or should I go fuck myself?") but the reality is New Yorkers are so nice they will gladly give you directions whether or not they know the way.&lt;br /&gt;%&lt;br /&gt;[...] the mentally ill are often the most compassionate because of what they have endured.&lt;br /&gt;        -- Kenny &lt;br /&gt;%&lt;br /&gt;Instead you are like a new yorker asked for directions and before they&lt;br /&gt;can even get out the words "...to Carnegie Hall" you have responded&lt;br /&gt;"Use Google Maps.  And rent the French Connection.  The chase scene&lt;br /&gt;covers most of Manhattan."&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;&lt;br /&gt;[Actually it was shot in Brooklyn -- rc]&lt;br /&gt;%&lt;br /&gt;Your other mistake is thinking I was planning a 500-page treatise&lt;br /&gt;complete with suggested legal forms.  I am an American, we have Cliff&lt;br /&gt;Notes for haiku.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I will be honest here, I am just a humble application programmer, and as an American I barely know where Monte Carlo is because we only need to know where is Las Vegas.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; "If Lisp is so great why don't libraries, etc. exist for it like&lt;br /&gt;&gt; they do for Ruby, Python, ...".&lt;br /&gt;&lt;br /&gt;You are wondering why Shakespeare never conceived a hit game show like&lt;br /&gt;Deal Or No Deal, and why Tiger Woods sucks at miniature golf.  Why&lt;br /&gt;Pavarotti never has and never will make it to the Billboard Pop 100,&lt;br /&gt;and why Dale Earnhart got fired after one week driving a taxi in NYC&lt;br /&gt;(he could only make left turns).&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;The first time you run into something is only the first time you will run into it.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Then again, I do not see why you even want to see it, you already have that sanctimonious glow from using free as in how we defined it software.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;What I saw was a defense of Java as being halfway to Lisp and the bit about him having a chart trying to close all the possible holes where behavior was unspecified.  True Lispers laugh in the face of unspecified.  Hell, we pay extra for it.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Meanwhile Steele famously claims Java is halfway to Lisp.  Perhaps he&lt;br /&gt;meant starting from the stone axe?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Apparently these geniuses think it matters one whit whether the spec&lt;br /&gt;in its entirety can be carved on the head of a pin.&lt;br /&gt;        --Ken Tilton&lt;br /&gt;%&lt;br /&gt;Now there's a language design principle.  Another good one is that you&lt;br /&gt;can sing it to the tune of Camptown Races.&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;"...Those who can't do, teach.  Badly.  I am reminded of the New Math,&lt;br /&gt;which made Principia Mathematica (?) a first-grade textbook."&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;".... Never heard from again, though rumor has it Steele found work&lt;br /&gt;as a tech writer for Sun."&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;[on motivation to finish his product]&lt;br /&gt;&lt;br /&gt;Not to worry, I have a friendly letter here from the IRS asking when&lt;br /&gt;they might expect to see last year's taxes, those tend to focus the&lt;br /&gt;mind wonderfully as well. :)&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;wants to follow The One True Lisp Way and trust us to know what we are&lt;br /&gt;doing, so compliance here would be compliance for it's own sake.&lt;br /&gt;&lt;br /&gt;I must need a drink, that last word looks like a Japanese malt brew.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Had you responded here instead of by email I could have eviscerated you in public (the only thing I really enjoy, the only thing that sets me apart from serial killers).&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;&lt;br /&gt;&gt; And thank you all, (every #'primep ...) worked great.  I found it is&lt;br /&gt;&gt; a very nice and helpful place here!&lt;br /&gt;&lt;br /&gt;Just wait until you put a parens on its own line, the honeymoon will&lt;br /&gt;be over fast.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; I try never to memorize what I can just look up.&lt;br /&gt;&lt;br /&gt;Right.  I never memorized C precedence, I dog-eared that one page in&lt;br /&gt;K&amp;R and/or threw in a pair of air-bag parens and skipped the lookup&lt;br /&gt;altogether,&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;But that code is quite solid and close to Deeply Correct.  I know because it has not changed much in years and handles new requirements effortlessly, generally by /taking out/ code that was enforcing disciplines which turned out not to be necessary (and in Lisp we hold inalienable the right to shoot off our own toes).&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;In the end I remembered that I have never let a concern for accuracy&lt;br /&gt;get in the way of my rants, way too much work.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;hard-charging newbies such as yourself landing in Lispville dumbfounded by all the dust, cobwebs, rust, and neglect giving the boot to the war-weary, disheartened, parentheses-mocked old soldiers rolling up your sleeves and setting about dragging the damn language out of the seventies and into the 21st century just in time for the asteroid to hit.  What was the question?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;You want there to be a problem, just like the strong static typers&lt;br /&gt;want there to be a problem.  Unfortunately for all you finger shaking,&lt;br /&gt;rule making, strait jacket wearing school marms we have a nonexistence&lt;br /&gt;proof of craploads of great code being written without a problem in&lt;br /&gt;spite of your sky is falling obsessive compulsive gnashing of the&lt;br /&gt;teeth.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;&gt;&gt; Wow, that is two non-required requirements in a week.  Me, I am&lt;br /&gt;&gt;&gt; looking for a transmission that can go from forward to reverse at&lt;br /&gt;&gt;&gt; fifty miles an hour without self-destructing.  I don't have a need&lt;br /&gt;&gt;&gt; for this, I am just looking for it.&lt;br /&gt;&gt; Easily done.  Not so easy is to allow any human passengers to&lt;br /&gt;&gt; survive the event.&lt;br /&gt;&lt;br /&gt;Reminds me of the guy I met who said he and his buddy agreed at&lt;br /&gt;sixty-five miles an hour to find out what would happen if they applied&lt;br /&gt;the parking brake.  Let's just say it is a good thing that they had&lt;br /&gt;agreed on it, and that the rental car company did not ask how their&lt;br /&gt;car ended up upside down.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;If you have to use so many big words, you must be wrong.&lt;br /&gt;        --Ken Tilton &lt;br /&gt;%&lt;br /&gt;Please follow up, I want to see if my killfile is working.&lt;br /&gt;        --Ken Tilton &lt;br /&gt;%&lt;br /&gt;Yeah, yeah, it was just a rant, you never want those held back by&lt;br /&gt;concerns over accuracy.  The sexp/mexp thing esp.  suggests divine&lt;br /&gt;inspiration might be a better model than alien arrival.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Unlike the inability of a deliberate mention of Hitler to function as&lt;br /&gt;would an emotionally honest invocation of same to signal the end of a&lt;br /&gt;flamewar, one can apparently climb up on top of the nearest car hood&lt;br /&gt;and announce one is starting a flamewar just to irritate people and a&lt;br /&gt;crowd will immediately form to argue with one over doing so.&lt;br /&gt;&lt;br /&gt;I once saw a nature special in which some insect or other dragged some other dead insect somewhere then turned around and dug a whole for it to bury it but the researchers moved the dead insect a bit while it was digging so it had to drag it back but while it did they filled in the hole and back and forth this insect went indefinitely until a PETA sniper took out the researchers.  Where was I?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt;&gt;I realize other people prefer other environments, they are just&lt;br /&gt;&gt;&gt;mistaken.  My ideal setup happens to be the best, hands down.&lt;br /&gt;&lt;br /&gt;Wow, I am really out on a limb there.  It would be pretty easy to take me down by naming a superior or even near equal environment.  Or you could back down in the face of my confidence and resort to, I don't know, name-calling?&lt;br /&gt;&lt;br /&gt;&gt; You're clearly deluded.&lt;br /&gt;&lt;br /&gt;Understood.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I am not, really.  I will do a year or two of Algebra and then have&lt;br /&gt;enough money to open a bar, do what I really want, tend bar.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Mind you I /have/ AG, but there is no point in doing cells-rdf if the&lt;br /&gt;rest of you food-stamp licking, government cheese eating, thrift&lt;br /&gt;shopping oooh-its-gotta-be-free pikers won't be able to benefit from&lt;br /&gt;my unceasing thankless toil on your behalf.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; Cells or Cello might be the solution.  But getting mad at people won't&lt;br /&gt;&gt; help.&lt;br /&gt;&lt;br /&gt;Thanks for your concern!&lt;br /&gt;&lt;br /&gt;Not to worry, I abuse these yobbos for fun, not out of anger.  And I&lt;br /&gt;am not sure c.l.l would know what to do with KGK (Kindler Gentler&lt;br /&gt;Kenny), but...&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Otherwise, sorry Karl, we are discussing the best way to learn Lisp&lt;br /&gt;(free ACL trial on win32), not the best way to resurrect your six-feet&lt;br /&gt;under commie pinko socioeconomic theory.&lt;br /&gt;        -- Ken Tilton  &lt;br /&gt;%&lt;br /&gt;&gt; Can someone with a bigger brain than me please elucidate.&lt;br /&gt;&lt;br /&gt;I think the problem is not brain-size so much as your admirable attempt to understand a tool by reading about it.  That puts you at the mercy of technical writers, who combine an inability to program at all well with an inability to write.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; check this out buddies&lt;br /&gt;&lt;br /&gt;I have a buddy?!!!  woo-hoo!  I thought I had alienated everyone with&lt;br /&gt;my sarcasm!!!!&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Tell us more about your home planet.&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;I'm gonna hurl.  Come on, everyone, newsgroup hug....&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;(a) You seem to be unaware of the Laws of Conservation of Hyphen&lt;br /&gt;Momentum: according to the CLHS, a term in hyphen motion tends to&lt;br /&gt;remain in motion, a term at hyphen rest tends to remain at rest.&lt;br /&gt;&lt;br /&gt;(b) Really, the worst thing you can do in CL is use a macro where a&lt;br /&gt;function would do.  The Pope does not sudo ex cathedra to say, "It's&lt;br /&gt;not the heat, it's the humidity."&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Was the author writing under the cloak of infallibility, channeling&lt;br /&gt;the word of G*d, and is our Talmudic interpretation of those awkward&lt;br /&gt;words precise?  The legislative history shows that CL got designed to&lt;br /&gt;address concerns of The Big Customer over language fragmentation, so&lt;br /&gt;it is hard to imagine an intent other than to define one language.&lt;br /&gt;The next step was a pretty tight ANSI standard language specification.&lt;br /&gt;&lt;br /&gt;Too easy? (I know, it is more fun being contrarian.)&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;The language lawyers cannot save you.  I am your only hope.  I am a&lt;br /&gt;simple application programmer.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Fine, bring me a single malt, a pint of amber back, a wedge of cheddar and some saltines.  And we'll need more napkins before we're done with this design.&lt;br /&gt;&lt;br /&gt;ps.  Oh, and another jar of dijon, and ask the redhead under the moose head if she would like to join us.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; What is a `hacker', or `programmer', or `computer scientist'?&lt;br /&gt;&lt;br /&gt;The last two were dragged to their death in the last thread.  Hacker is a term used by us computer geeks in a desperate attempt to glamorize our bit-ridden asses, as if the best of us will ever get laid as often as the tone-deaf, rhythym-blind bassist of a third rate cover band on Long Island, let alone the rock stars we pose as when we call ourselves hackers.  Paul Graham, who I generally greatly admire and hope will because I said that fund my start-up but more lavishly than he does those Y-Combinator conscripts, drove a stake through the heart of the term here: [snip]&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I actually had a business card that just said "Programmer".  Got everyone quite upset, they wanted "Systems Analyst" or "Software Engineer" or "Database Administrator" or something.  My point was that one cannot program a computer effectively without doing all those things, so "Programmer" was sufficient.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Now can we get back to name-calling?  Stop trying to civilize this&lt;br /&gt;brawl.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt;&gt; I always tell youngsters it is OK to take one year off before grad&lt;br /&gt;&gt;&gt; school, but for the love of god don't take two.&lt;br /&gt;&gt; I think this depends on the person.&lt;br /&gt;&lt;br /&gt;Never look a gift joke in the mouth.&lt;br /&gt;        -- Ken Tilton  &lt;br /&gt;%&lt;br /&gt;&gt; My theory is that is we bought and open-sourced [...] we could get&lt;br /&gt;&gt; the community to rally around that one,....&lt;br /&gt;&lt;br /&gt;The idea of this Lisp community "rallying" is about as conceivable as&lt;br /&gt;a hootenany down at the cemetery.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;It is the mouse that feels bad, not the cat playing with it.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;The big mistake is thinking Lisp is going to grow by first being&lt;br /&gt;adopted in Tall Buildings.  They are the drones, the lemmings, the&lt;br /&gt;sheep.  They follow where We the Blessed Gurus lead them.  But this&lt;br /&gt;time it is to the slaughterhouse, because the world needs only fifty&lt;br /&gt;Lisp programmers to write All the Code.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;... listening instead of yapping?  Read my frickin lips: I am talking&lt;br /&gt;about actual tall-office design reviews in which well-paid engineers&lt;br /&gt;...  pragmatically suggested design disasters because they objected to&lt;br /&gt;anything a pet rock (sorry, Rockie) could not code.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Anyway, if one has not programmed heads down for three years one likely does not know much about design.  I am sure I write more code in a year than academics write in a lifetime, because we are doing different things.  Hell, they have the sorry task of trying to pretend there /is/ such a thing as computer science.  If there was, wouldn't everyone be using Lisp?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Unfortunately I still do not understand the question, and I am a&lt;br /&gt;frickin genius, I have a three-digit IQ, 50% more than 2.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Well the trick of folks like H.. is to listen just enough so that one can respond to a direct hit with multiple non-pointing counterpoints, each more retarded than the last and each stated in an artfully needling fashion guaranteed to make the sanest NG denizen continue the thread, as if the /next/ direct hit will achieve any more than the last.&lt;br /&gt;&lt;br /&gt;It's like playing paintball with a guy who keeps running around and&lt;br /&gt;shooting, covered head to toe in paint.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; deal more.  But after seeing your behaviour in cll you can be&lt;br /&gt;&gt; assured that I will never, ever consider any functional programming&lt;br /&gt;&gt; language.  I can just do without languages that attract that kind of&lt;br /&gt;&gt; behaviour.&lt;br /&gt;&lt;br /&gt;        -- tim (and yes, before you respond, that is one reason I&lt;br /&gt;           don't use CL so much any more as well.)&lt;br /&gt;&lt;br /&gt;Abandoning something wonderful because of who else uses it makes&lt;br /&gt;perfect sense.  Why did I give up sex?  One word: Joey Buttafucco.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Never been to a code review, have you?  You are blessed.  The worst crap in the world gets protected by the manager because he is the only person in the room more clueless than the author of the crap and dies when the author dies because the author is in effect a buoyancy device for the in effect non-swimmer manager.  But I digress.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;I cannot write correct code to save my life, I just throw out any bad code.  Only trick there is to distract the author with a banana while deleting their code.&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;You know, the oil companies have developed a car that runs on carbon dioxide and has like 800 horsepower.  Where you can buy one is another question.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Me, I saw the "Microsoft Research" oxymoron and did not get much&lt;br /&gt;further.  Unless by research they mean using Google to find out what&lt;br /&gt;ideas other people have successfuly developed and commercialized so&lt;br /&gt;they can copy it badly and crush them.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; Yawn.  You must be a riot at parties.&lt;br /&gt;&lt;br /&gt;And you must be the life of a funeral.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;The way to get this going is to post here an especially good RQ&lt;br /&gt;question and your Lisp solution, see if you can drum up interest.  If&lt;br /&gt;it takes off, you start a Web site or something.  If not, the ball&lt;br /&gt;game comes on at two.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;ps.  I agree, the "fingers will be chopped off" sign should not have&lt;br /&gt;been Comic Sans. :)&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Well whaddya know.  I do GUIs, leave file work to the chimps.  You win&lt;br /&gt;a banana.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Can we continue this over on comp.lang.turing.complete?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;...the only thing that matters is Becoming the Latest Thing.  What is&lt;br /&gt;the latest thing?  The (a) new thing (b) being recommended (c) by&lt;br /&gt;Famous People (d) in respectable places&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;The operator helpfully suggests that I could avoid this problem by simply saying that my mother's maiden name is YOBBO, no one will make fun of me.  He also takes care of confirming the purchase over the phone, while I try to figure out how to sell "Hi, I need to change my mother's maiden name..." to the next operator.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;So I am working in a lab?  That would explain all the beakers.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;That rose girl is drying up and a few volcanos need sweeping.&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;Grapette this: no, Jodie Foster is /not/ responsible for John Hinckley&lt;br /&gt;shooting three people including the President.  The correct question&lt;br /&gt;was "Who is John Hinckley?".&lt;br /&gt;&lt;br /&gt;Really, kiddies, it is OK to blame the perpetrator.  Not that I do in&lt;br /&gt;this case.  The OP is clearly an unhappy puppy deserving nothing other&lt;br /&gt;than compassion for the demons that drive them to randomly attack&lt;br /&gt;Usenet blowhards like me.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;And Uhl says Kenny has made the South forget the Civil War, not sure&lt;br /&gt;how I could top that.  The hounds are exhausted, smiling in their&lt;br /&gt;sleep.  It's all good -- but someone has to talk Bubba and Jethro down&lt;br /&gt;from their sniper nests.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Do they have the distinction between a priori and a posteriori in your&lt;br /&gt;banjo-pickin, moonshine-slurping, carcinogen-growing,&lt;br /&gt;basketball-playing neck of the woods?  How about de jure vs. de facto?&lt;br /&gt;Simular.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;That /was/ a despicable and wholly unjustified ad stateum low-blow, a&lt;br /&gt;cheap shot deliberately designed to make me look bad.  It crosses a&lt;br /&gt;shocking line, beneath contempt, really.  Clearly I had cut in my&lt;br /&gt;flamethrower after-booster and lost all reason or sense of decency.&lt;br /&gt;It almost makes me wonder if I was even serious...&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;See, this is what happens when you get all riled up and change the&lt;br /&gt;subject to whether Kenny is consistent or not, you get so emotional&lt;br /&gt;you cannot read straight.  And my inconsistency varies quite a bit, so&lt;br /&gt;I do not know if you can build an argument on that anyway.&lt;br /&gt;&lt;br /&gt;ps. Random problem cloning is going well, but obviously slowly enough&lt;br /&gt;to have me dashing here to hide pretty regularly. :) What kind of Lisp&lt;br /&gt;did you write today?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;MWUAHAHAHAHAHHAHAA!!!!!  Yes, palindromeloopstate set to 1 makes the&lt;br /&gt;movie run endlessly forth and back.  Picture looks fine running&lt;br /&gt;backwards, but instead of the spoken words coming out in reverse,&lt;br /&gt;well, it is just unrecognizable noise.  Working on that now...&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Fine, but anyone who uses Usenet knows that that is not how one says&lt;br /&gt;"Thanks".  Which is why I felt safe moving directly to defcon 3, just&lt;br /&gt;to see how big an *sshole we had on board.  His defcon 1 "Rot in hell&lt;br /&gt;jackass" response merely, well, QED.&lt;br /&gt;         -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;[...] the serious answer comes from the Tao Te Ching, lessee, on about&lt;br /&gt;every other page:&lt;br /&gt;&lt;br /&gt;        "A man on tiptoe cannot walk easily."&lt;br /&gt;&lt;br /&gt;Or:&lt;br /&gt;        "Never trying to impress, their being shines forth Never&lt;br /&gt;        saying 'this is it', people see what the truth is -- Never&lt;br /&gt;        boasting, they leave the space in which they can be valued ...&lt;br /&gt;        And since they never argue, no one argues with them either."&lt;br /&gt;&lt;br /&gt;Lao Tzu clearly would be no fun in a flame war.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;"Gotcha" is like analogies, they lead to arguments about the&lt;br /&gt;gotchaness of the gotcha, an exponential explosion guaranteed.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;Despite copious opinion to the contrary, I speak not as Grand Poobah&lt;br /&gt;of Common Lisp and have not the power to marshall our forces to&lt;br /&gt;maximize the benefit of their labor.  I can only pause between rides&lt;br /&gt;to town on my pushbox to wonder aloud in camp why a serous chunk of&lt;br /&gt;our tribe is over there under the tree working on the wheel and&lt;br /&gt;axle -- ones no better than the one on my pushcart.&lt;br /&gt;&lt;br /&gt;Kenzo: "Dudes, it's been twenty-five years, prices down at Throg's&lt;br /&gt;Wheel &amp; Axle aren't all that bad.  Why not work on a mast and sail?"&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;A subtle execution of the tip of a tongue pressed against the upper&lt;br /&gt;teeth with sprays of spittle coming out either side probably is not&lt;br /&gt;what you had in mind.&lt;br /&gt;&lt;br /&gt;Hmmm.  Then we change the spelling to Lithp, and never have to hear&lt;br /&gt;that stupid joke again.  Our slogan can be "Thay it loud, thay it&lt;br /&gt;proud."*, and we already have the frickin lambda.&lt;br /&gt;&lt;br /&gt;Or "Out With Lithp!".&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;Barker: "Stairway to Heaven!  Open to all!  Come on up!  One-day&lt;br /&gt;amnesty!"&lt;br /&gt;&lt;br /&gt;Kenny: "No elevator?"&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;No, I made a few changes and sent it to the Copyright Office.&lt;br /&gt;&lt;br /&gt;For Mom I am holding out for the cover of Wired.  (She already takes&lt;br /&gt;America's Most Wanted.)&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;"you also physically incapable of understanding that your opinions are&lt;br /&gt;not the words of God".  Nice comeback on originality!  Physical&lt;br /&gt;understanding?  What part of the mind-body problem do you not&lt;br /&gt;understand?&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;No, I would mock you for being so locked into mob-rule and aggression that you think my insistence on walking to a different drummer entails also abusing anyone not conforming to my non-conformity.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;"wet feet" might not do justice to the 3D learning curve -- that&lt;br /&gt;subsonic rumble shaking your kayak is Niagara Falls.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;"Feeling no pain, Kevin?"&lt;br /&gt;"Sorry?"&lt;br /&gt;"You just came out of the women's rest room."&lt;br /&gt;"Look, I had to take a leak.  Odd, no urinals, just sit-downs."&gt; &amp; no&lt;br /&gt;'bouncers' made any approach..&lt;br /&gt;&lt;br /&gt;It's crowded, they are still working their way through the crowd.&lt;br /&gt;Don't worry, we'll explain about the Lisp "high".&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;er, um... no.  OO is about managing huge wadges of code in huge&lt;br /&gt;systems that will be spending most of their lives waiting on disk I/O&lt;br /&gt;so WTF cares about OO overhead, we need to manage these huge&lt;br /&gt;codebases!!!  ie, OO is for lazy-ass mo-fos who cannot be bothered to&lt;br /&gt;toss of a few dozen lines of code and reinvent "objects" in a fashion&lt;br /&gt;screamingly optimized for their application.&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;So it samples the pitch and guesses at rhythm and provides tutoring&lt;br /&gt;similar to what I would get from a good music teacher?  Astonishing.&lt;br /&gt;AI has been solved!  Stop the presses on the emasculation of George&lt;br /&gt;Bush, we have real news!!!&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&lt;br /&gt;&gt; if Clisp is so good where are the commonly used apps?&lt;br /&gt;&lt;br /&gt;If George and Barbara had such great sex, how did they produce Jeb and Dubbya?&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;&gt; I like the lizard.&lt;br /&gt;&lt;br /&gt;No, you don't, you are just saying that.  Think again.&lt;br /&gt;&lt;br /&gt;&gt; But then, I like the Geico gecko, too.&lt;br /&gt;&lt;br /&gt;Everybody likes the GG.  It has an australian accent.&lt;br /&gt;&lt;br /&gt;&gt; And I like Common Lisp, too.  Guess I'm weird, hunh?  ;-}&lt;br /&gt;&lt;br /&gt;I was thinking "doomed".&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;And a mascot like Joe Camel to suck in the kiddies, gotta have a&lt;br /&gt;mascot.&lt;br /&gt;        - Ken Tilton &lt;br /&gt;%&lt;br /&gt;You yobs might want to ... oh, what's the use?  Lisp is dying.  The next generation of Lispniks is over on #lisp worshipping themselves and learning nothing and achieving less.  My god, another two years and Slime may be half the power of the ACL IDE.  What is the word I am looking for... ah, here it is: PFFFFFFFT!&lt;br /&gt;        -- Ken Tilton &lt;br /&gt;%&lt;br /&gt;You French really are pissed off about Lance Armstrong, aren't you?&lt;br /&gt;    -- Ken Tilton  &lt;br /&gt;%&lt;br /&gt;* reminds me of part of a route description to a rock climb called&lt;br /&gt;Death's Door: "Don't use the jug handle just to the right of the&lt;br /&gt;finger jam, that hold is part of Cakewalk."&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;br /&gt;I have worked with body shop programmers who could not be bothered to write structured code.  Are the concepts of structured programming too hard?  Nah, those people just "refused to be bothered" (a direct quote), meaning they were too inured to the pain of spaghetti coding to realize how much "bother" structured programming could save them. They thought spaghetti code was /easier/ because, hey, how hard does one have to think to add another GOTO?  It breaks somewhere else?  Add another GOTO! C'mon, this is easy!  Breaks somewhere else...read my lips: GOTO!&lt;br /&gt;        -- Ken Tilton&lt;br /&gt;%&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5574063229675590871?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5574063229675590871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5574063229675590871' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5574063229675590871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5574063229675590871'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2010/08/fortune-cookie-file-number-two.html' title='Fortune Cookie File Number Two'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-8431785601885283345</id><published>2009-10-31T13:11:00.004-04:00</published><updated>2009-10-31T14:03:19.019-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Clojure Scala Groovy Coherent Reaction Trellis Cells Guy Steele James Strachan Johnathan Edwards'/><title type='text'>The King is Dead!? Long live... Scala? Clojure?!</title><content type='html'>&lt;div&gt;Whoa, why wasn't I told Java is &lt;a href="http://www.jroller.com/scolebourne/entry/no_more_java_7"&gt;closing its doors&lt;/a&gt;? I guess I have been out of touch, word seems to be everywhere. I had to go &lt;a href="http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html"&gt;here&lt;/a&gt; (blog of the guy who created &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;) to find out. James is whooping it up over &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; as Java's successor. Yes, the guy who invented Groovy prefers Scala. Quite a bit:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;I can honestly say if someone had shown me the Programming in Scala book by by Martin Odersky, Lex Spoon &amp;amp; Bill Venners back in 2003 I'd probably have never created Groovy. -- James Strachan&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Damn. So he pretty much invented Groovy by mistake? Did not know about the two-year old Scala? No one mentioned it to him? Groovy got admitted to the standard in the meantime?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, &lt;a href="http://coherence-lang.org/Onward09.pdf"&gt;Johnathan Edwards&lt;/a&gt; reinvented Python &lt;a href="http://peak.telecommunity.com/DevCenter/Trellis"&gt;Trellis&lt;/a&gt; (ergo &lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;Cells&lt;/a&gt;) without knowing it,  and I did not know about &lt;a href="http://www.faqs.org/faqs/garnet-faq/"&gt;Garnet&lt;/a&gt;'s KR or constraints -- but Groovy got adopted as official Java! You think Scala might have come up over coffee. Anyway...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Steele said Java brought the world half-way to Lisp. I do not think Lisp means what he thinks it means. Proof might be how hard it is for folks to climb out of the pit of javathink. If Java had been a stepping stone to Lisp it would have made the next step easier, not harder. But Java still cannot do closures. Please. And a quick look at closures in Scala has me thinking, omigod, they call &lt;i&gt;that&lt;/i&gt; closures? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; starts to look like a Good Move. I see it mentioned in writings on the death throes of Java and that is a big marketing win. The superwhacky thing here is that both Scala and Clojure are syntactically discontinuous from Java. Folks always thought successors had to have syntax similar to the succeeded though &lt;a href="http://www.opendylan.org/"&gt;Dylan&lt;/a&gt; should have served as cautionary counter-evidence. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No, it is not the syntax. The necessary bridging element seems to be....wait for it...the Java runtime! How did that tail end up wagging the language adoption dog? But Clojure gets the nod along with Scala just for sitting atop the JRE! You people scare me.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, if Steele were right Clojure would prevail over Scala. Right now googlefight has Scala winning five to one. Maybe Rich Hickey can move 17% of the world 90% of the way to Lisp?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-8431785601885283345?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/8431785601885283345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=8431785601885283345' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8431785601885283345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8431785601885283345'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/10/king-is-dead-long-live-scala-clojure.html' title='The King is Dead!? Long live... Scala? Clojure?!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7008785515259142802</id><published>2009-08-10T06:01:00.000-04:00</published><updated>2009-08-10T06:02:20.800-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='writing Lisp comedy Socrates Izzard'/><title type='text'>To write, or not to write?</title><content type='html'>&lt;div&gt;&gt;&gt;  By the way, to change the subject a little, who was it who said,&lt;/div&gt;&lt;div&gt;&gt;&gt;  "there are no dead languages, only dead minds"?&lt;/div&gt;&lt;div&gt;&gt; &lt;/div&gt;&lt;div&gt;&gt; Dunno, but to change the subject even more, Socrates objected to writing&lt;/div&gt;&lt;div&gt;&gt; since it deprives an idea of a mind in which it can "live". So yeah.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Interesting. "Free writing" is a form that lives within a mind but also create a permanent record and slow the mind down enough to achieve more coherence so the mind can work out hard problems. Comedy writing is necessary to trigger a laugh response because every word matters, but then the words must be delivered as if they were coming live from a mind. Exceptions are improv and semi-improv such as Eddie Izzard, of which Mr. Socrates would approve because they arise within a living mind. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I get a lot of complaints about the writing in this blog because I deliberately write as chaotically as I think. Other times I found I gave a much better talk if I read from something written beforehand precisely because otherwise the living mind is too chaotic to get the talk done in anywhere near the time available. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was just getting ready to videotape an improvised bit to get the good bits to then pull into a fixed, written bit because I am finding good stuff comes out only if the mind is not slowed down as by free writing. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The question is whether Eddie Izzard is lazy, or if Socrates is right on this. Does Izzard do better by capturing his improv and distilling it down to a precise fixed bit, or does he do worse? Or does he just lack the ability to deliver the prepared as if it were unprepared.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We're getting pretty close to talking about programming in Lisp vs NotLisp now. Lisp programming unconstrained by static typing and blessed with a rich library once that library is mastered such that it is all at the programmer's fingertips allows the code to flow freely yet mostly correctly from a live mind even as that mind is forming the solution the code embodies. Diagram that.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7008785515259142802?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7008785515259142802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7008785515259142802' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7008785515259142802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7008785515259142802'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/08/to-write-or-not-to-write.html' title='To write, or not to write?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7230566389574006646</id><published>2009-06-26T00:47:00.007-04:00</published><updated>2009-06-26T01:25:00.030-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp Erik Naggum quads XML SGML HTML'/><title type='text'>I Feel A Naggum (RIP) Coming On: Quads</title><content type='html'>I sometimes begin c.l.l rants with "I feel a naggum coming on...". What is a naggum? Normally:&lt;div&gt;&lt;blockquote&gt;naggum (n): A rant along one of Erik Naggum(1965-2009)'s themes.&lt;/blockquote&gt;That might be self-referentially hopeless which is fine because that is not what I am talking about, I just thought that would be a clever title. In this case a "naggum" is a nugget of Erikian technology. First, his specification of what he called quads (see below), and my poor implementation (even further below and good luck even figuring out how to test it) .&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;kt&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#|&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From: Erik Naggum (erik@naggum.no)&lt;/div&gt;&lt;div&gt;Subject: Re: XML-&gt;sexpr ideas&lt;/div&gt;&lt;div&gt;Newsgroups: comp.lang.lisp&lt;/div&gt;&lt;div&gt;Date: 2004-01-19 04:24:43 PST&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;* Kenny Tilton&lt;/div&gt;&lt;div&gt;| Of course it is easy enough for me to come up with a sexpr format off&lt;/div&gt;&lt;div&gt;| the top of my head, but I seem to recall someone (Erik? Tim? Other?)&lt;/div&gt;&lt;div&gt;| saying they had done some work on a formal approach to an alternative&lt;/div&gt;&lt;div&gt;| to XML/HTML/whatever.&lt;/div&gt;&lt;div&gt;| &lt;/div&gt;&lt;div&gt;| True that? If so, I am all ears.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Really?  You are?  Maybe I didn't survive 2003 and this is some Hell&lt;/div&gt;&lt;div&gt;  where people have to do eternal penance, and now I get to do SGML all&lt;/div&gt;&lt;div&gt;  over again.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Much processing of SGML-like data appears to be stream-like and will&lt;/div&gt;&lt;div&gt;  therefore appear to be equivalent to an in-order traversal of a tree,&lt;/div&gt;&lt;div&gt;  which can therefore be represented with cons cells while the traverser&lt;/div&gt;&lt;div&gt;  maintains its own backward links elsewhere, but this is misleading.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  The amount of work and memory required to maintain the proper backward&lt;/div&gt;&lt;div&gt;  links and to make the right decisions is found in real applications to&lt;/div&gt;&lt;div&gt;  balloon and to cause random hacks; the query languages reflect this&lt;/div&gt;&lt;div&gt;  complexity.  Ease of access to the parent element is crucial to the&lt;/div&gt;&lt;div&gt;  decision-making process, so if one wants to use a simple list to keep&lt;/div&gt;&lt;div&gt;  track of this, the most natural thing is to create a list of the&lt;/div&gt;&lt;div&gt;  element type, the parent, and the contents, such that each element has&lt;/div&gt;&lt;div&gt;  the form (type parent . contents), but this has the annoying property&lt;/div&gt;&lt;div&gt;  that moving from a particular element to the next can only be done by&lt;/div&gt;&lt;div&gt;  remembering the position of the current element in a list, just as one&lt;/div&gt;&lt;div&gt;  cannot move to the next element in a list unless you keep the cons&lt;/div&gt;&lt;div&gt;  cell around.  However, the whole point of this exercise is to be able&lt;/div&gt;&lt;div&gt;  to keep only one pointer around.  So the contents of an element must&lt;/div&gt;&lt;div&gt;  have the form (type parent contents . tail) if it has element contents&lt;/div&gt;&lt;div&gt;  or simply a list of objects, or just the object if simple enough.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Example: &lt;foo&gt;123&lt;/foo&gt; would thus be represented by (foo nil "123"),&lt;/div&gt;&lt;div&gt;  &lt;foo&gt;123&lt;/foo&gt;&lt;bar&gt;456&lt;/bar&gt; by (foo nil "123" bar nil "456"), and&lt;/div&gt;&lt;div&gt;  &lt;zot&gt;&lt;foo&gt;123&lt;/foo&gt;&lt;bar&gt;456&lt;/bar&gt;&lt;/zot&gt; by #1=(zot nil (foo #1# "123"&lt;/div&gt;&lt;div&gt;  bar #1# "456")).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Navigation inside this kind of structure is easy: When the contents in&lt;/div&gt;&lt;div&gt;  CADDR is exhausted, the CDDDR is the next element, or if NIL, we have&lt;/div&gt;&lt;div&gt;  exhausted the contents of the parent and move up to the CADR and look&lt;/div&gt;&lt;div&gt;  for its next element, etc.  All the important edges of the containers&lt;/div&gt;&lt;div&gt;  that make up the *ML document are easily detectible and the operations&lt;/div&gt;&lt;div&gt;  that are usually found at the edges are normally tied to the element&lt;/div&gt;&lt;div&gt;  type (or as modified by its parents), are easily computable.  However,&lt;/div&gt;&lt;div&gt;  using a list for this is cumbersome, so I cooked up the «quad».  The&lt;/div&gt;&lt;div&gt;  «quad» is devoid of any intrinsic meaning because it is intended to be&lt;/div&gt;&lt;div&gt;  a general data structure, so I looked for the best meaningless names&lt;/div&gt;&lt;div&gt;  for the slots/accessors, and decided on QAR, QBR, QCR, and QDR.  The&lt;/div&gt;&lt;div&gt;  quad points to the element type (like the operator in a sexpr) in the&lt;/div&gt;&lt;div&gt;  QAR, the parent (or back) quad in the QBR, the contents of the element&lt;/div&gt;&lt;div&gt;  in the QCR, and the usual pointer to the next quad in the QDR.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Since the intent with this model is to «load» SGML/XML/SALT documents&lt;/div&gt;&lt;div&gt;  into memory, one important issue is how to represent long stretches of&lt;/div&gt;&lt;div&gt;  character content or binary content.  The quad can easily be used to&lt;/div&gt;&lt;div&gt;  represent a (sequence of) entity fragments, with the source in QAR,&lt;/div&gt;&lt;div&gt;  the start position in QBR, and the end position in QCR, thereby using&lt;/div&gt;&lt;div&gt;  a minimum of memory for the contents.  Since very large documents are&lt;/div&gt;&lt;div&gt;  intended to be loaded into memory, this property is central to the&lt;/div&gt;&lt;div&gt;  ability to search only selected elements for their contents -- most&lt;/div&gt;&lt;div&gt;  searching processors today parse the entire entity structure and do&lt;/div&gt;&lt;div&gt;  very little to maintain the parsed element structure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Speaking of memory, one simple and efficient way to implement the quad&lt;/div&gt;&lt;div&gt;  on systems that lack the ability to add native types without overhead,&lt;/div&gt;&lt;div&gt;  is to use a two-dimensional array with a second dimension of 4 and let&lt;/div&gt;&lt;div&gt;  quad pointers be integers, which is friendly to garbage collection and&lt;/div&gt;&lt;div&gt;  is unambiguous when the quad is used in the way explained above.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  Maybe I'll talk about SALT some other day.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-- &lt;/div&gt;&lt;div&gt;Erik Naggum | Oslo, Norway&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Act from reason, and failure makes you rethink and study harder.&lt;/div&gt;&lt;div&gt;Act from faith, and failure makes you blame someone and push harder.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;|#&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(in-package :ukt)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;;;;(defstruct (juad jar jbr jcr jdr)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &lt;/div&gt;&lt;div&gt;(defun qar (q) (car q))&lt;/div&gt;&lt;div&gt;(defun (setf qar) (v q) (setf (car q) v))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun qbr (q) (cadr q))&lt;/div&gt;&lt;div&gt;(defun (setf qbr) (v q) (setf (cadr q) v))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun qcr (q) (caddr q))&lt;/div&gt;&lt;div&gt;(defun (setf qcr) (v q) (setf (caddr q) v))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun qdr (q) (cdddr q))&lt;/div&gt;&lt;div&gt;(defun (setf qdr) (v q) (setf (cdddr q) v))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun sub-quads (q)&lt;/div&gt;&lt;div&gt;  (loop for childq on (qcr q) by #'qdr&lt;/div&gt;&lt;div&gt;      collecting childq))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun sub-quads-do (q fn)&lt;/div&gt;&lt;div&gt;  (loop for childq on (qcr q) by #'qdr&lt;/div&gt;&lt;div&gt;      do (funcall fn childq)))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun quad-traverse (q fn &amp;amp;optional (depth 0))&lt;/div&gt;&lt;div&gt;  (funcall fn q depth)&lt;/div&gt;&lt;div&gt;  (sub-quads-do q&lt;/div&gt;&lt;div&gt;    (lambda (subq)&lt;/div&gt;&lt;div&gt;      (quad-traverse subq fn (1+ depth)))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun quad (operator parent contents next)&lt;/div&gt;&lt;div&gt;  (list operator parent contents next))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun quad* (operator parent contents next)&lt;/div&gt;&lt;div&gt;  (list operator parent contents next))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun qups (q)&lt;/div&gt;&lt;div&gt;  (loop for up = (qbr q) then (qbr up)&lt;/div&gt;&lt;div&gt;        unless up do (loop-finish)&lt;/div&gt;&lt;div&gt;        collecting up))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun quad-tree (q)&lt;/div&gt;&lt;div&gt;  (list* (qar q)&lt;/div&gt;&lt;div&gt;    (loop for childq on (qcr q) by #'qdr&lt;/div&gt;&lt;div&gt;        while childq&lt;/div&gt;&lt;div&gt;          collecting (quad-tree childq))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun tree-quad (tree &amp;amp;optional parent)&lt;/div&gt;&lt;div&gt;  (let* ((q (quad (car tree) parent nil nil))&lt;/div&gt;&lt;div&gt;         (kids (loop for k in (cdr tree)&lt;/div&gt;&lt;div&gt;                     collecting (tree-quad k q))))&lt;/div&gt;&lt;div&gt;    (loop for (k n) on kids&lt;/div&gt;&lt;div&gt;          do (setf (qdr k) n))&lt;/div&gt;&lt;div&gt;    (setf (qcr q) (car kids))&lt;/div&gt;&lt;div&gt;    q))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#+test&lt;/div&gt;&lt;div&gt;(test-qt)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun test-qt ()&lt;/div&gt;&lt;div&gt;  (print (quad-tree #1='(zot nil (foo #1# ("123" "abc")&lt;/div&gt;&lt;div&gt;                                . #2=(bar #1# (ding #2# "456"&lt;/div&gt;&lt;div&gt;                                                dong #2# "789")))))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(print #1='(zot nil (foo #1# ("123" "abc")&lt;/div&gt;&lt;div&gt;                          . #2=(bar #1# (ding #2# "456"&lt;/div&gt;&lt;div&gt;                                          dong #2# "789")))))&lt;/div&gt;&lt;div&gt;#+xxxx&lt;/div&gt;&lt;div&gt;(test-tq)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun test-tq ()&lt;/div&gt;&lt;div&gt;  (let ((*print-circle* t)&lt;/div&gt;&lt;div&gt;        (tree '(zot (foo ("123")) (bar (ding) (dong)))))&lt;/div&gt;&lt;div&gt;    (assert (equal tree (quad-tree (tree-quad tree))))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun testq ()&lt;/div&gt;&lt;div&gt;  (let ((*print-circle* t))&lt;/div&gt;&lt;div&gt;    (let ((q #1='(zot nil (foo #1# ("123" "abc")&lt;/div&gt;&lt;div&gt;                            . #2=(bar #1# (ding #2# "456"&lt;/div&gt;&lt;div&gt;                                            dong #2# "789"))))))&lt;/div&gt;&lt;div&gt;      (print '(traverse showing each type and data preceded by its depth))&lt;/div&gt;&lt;div&gt;      &lt;/div&gt;&lt;div&gt;      (quad-traverse q (lambda (q depth)&lt;/div&gt;&lt;div&gt;                         (print (list depth (qar q)(qcr q)))))&lt;/div&gt;&lt;div&gt;      (print `(listify same ,(quad-tree q))))&lt;/div&gt;&lt;div&gt;    (let ((q #2='(zot nil (ding #2# "456"&lt;/div&gt;&lt;div&gt;                                  dong #2# "789"))))&lt;/div&gt;&lt;div&gt;      (print '(traverse showing each "car" and itd parentage preceded by its depth))&lt;/div&gt;&lt;div&gt;      (print '(of data (zot (ding (dong)))))&lt;/div&gt;&lt;div&gt;      (quad-traverse q (lambda (q depth)&lt;/div&gt;&lt;div&gt;                         (print (list depth (qar q)&lt;/div&gt;&lt;div&gt;                                  (mapcar 'qar (qups q)))))))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;;;;(defun tree-quad (tree)&lt;/div&gt;&lt;div&gt;  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defun testq2 ()&lt;/div&gt;&lt;div&gt;  (let ((*print-circle* t))&lt;/div&gt;&lt;div&gt;    (let ((q #2='(zot nil (ding #2# "456"&lt;/div&gt;&lt;div&gt;                            dong #2# "789"))))&lt;/div&gt;&lt;div&gt;      (print '(traverse showing each "car" and itd parentage preceded by its depth))&lt;/div&gt;&lt;div&gt;      (print '(of data (zot (ding (dong)))))&lt;/div&gt;&lt;div&gt;      (quad-traverse q (lambda (q depth)&lt;/div&gt;&lt;div&gt;                         (print (list depth (qar q)&lt;/div&gt;&lt;div&gt;                                  (mapcar 'qar (qups q)))))))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;              &lt;/div&gt;&lt;div&gt;  &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7230566389574006646?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7230566389574006646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7230566389574006646' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7230566389574006646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7230566389574006646'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/06/i-feel-naggum-rip-coming-on-quads.html' title='I Feel A Naggum (RIP) Coming On: Quads'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5586079771938783666</id><published>2009-06-22T01:16:00.002-04:00</published><updated>2009-06-22T01:20:50.414-04:00</updated><title type='text'>American &amp; Iran: Separated at Birth?</title><content type='html'>Am I the only one grooving specifically on the fact that Iranians are telling their authority figures to go f*ck themselves? Here is the country we thought we hated but it turns out they are as kick-ass as us when it comes to political freedom, and we utterly respect them for their strength. Omigod, Americans and Iranians are going to get along great!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5586079771938783666?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5586079771938783666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5586079771938783666' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5586079771938783666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5586079771938783666'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/06/american-iran-separated-at-birth.html' title='American &amp; Iran: Separated at Birth?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7865367019335228012</id><published>2009-05-11T00:34:00.006-04:00</published><updated>2009-05-11T01:45:23.710-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='math eductaion'/><title type='text'>How to teach math</title><content type='html'>&lt;div&gt;&gt; On Sat, 09 May 2009 15:30:52 -0400, Kenneth Tilton wrote:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;Well, i was not really trolling, I was forking the thread to make fun of  the New Math that tried to get the numeral/number distinction across to five year olds.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Someone responded:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;You find it better to start with medieval concepts working gradually on to the mathematics of XIX century, while explaining each next year what was wrong with the things they learnt a year ago?&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I said all that? Ma's gonna be right proud. But... &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Funny you should ask. Yes, I suspect the path society took to get to what it knows now about math is the path an individual neuronal mass should follow. ie, kids should encounter zero and roman numerals and place value and algebraic variables in the same order society developed those ideas.  The history of math is your math curriculum guide.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The New Math erred by selecting the &lt;span class="Apple-style-span" style="font-style: italic;"&gt;logical &lt;/span&gt;organization of mathematical concepts as its curricular pole star. Next came Constructivism, which wanted kids to reinvent math. From scratch. Cool idea, but too slow.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Instead, let the history of mathematics dictate the &lt;span class="Apple-style-span" style="font-style: italic; "&gt;order &lt;/span&gt;in which things are &lt;span class="Apple-style-span" style="font-style: italic;"&gt;directly taught&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;. &lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;Maybe &lt;/span&gt;go further and teach math as history with less emphasis on computation. Math often advanced when needed to solve real problems. Maybe we can shut up the little devils asking why they need to learn this stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As for explaining all along the way what was wrong with the ideas taught the day before, hey, ever read a book on programming? They typically develop a chunk of code iteratively, presenting ever more improved variations on a primitive original. Come to think of it, ever develop some software? Same thing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the deal: most folks do not even &lt;span class="Apple-style-span" style="font-style: italic;"&gt;know &lt;/span&gt;zero had to be invented. One understands zero better if one has done without it and then the teacher invents it for you. Something like that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7865367019335228012?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7865367019335228012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7865367019335228012' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7865367019335228012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7865367019335228012'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/05/how-to-teach-math.html' title='How to teach math'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1451611794856733046</id><published>2009-02-04T11:10:00.002-05:00</published><updated>2009-02-13T11:31:42.535-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cells ECLM OOPS Fred Brooks No Silver Bullet dataflow FRP functional reactive programming'/><title type='text'>Cells: The Secret Transcript</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:'Times New Roman';"&gt;&lt;div style="border-width: 0px; margin: 0px; padding: 3px; width: auto; font-family: Georgia,serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: 100%; line-height: normal; font-size-adjust: none; font-stretch: normal; text-align: left;"&gt;&lt;div&gt;The Boss asked me to give the group fifteen minutes on Cells because I have been talking about it for a while as a future better mousetrap for us and then suddenly last week threatened actually to apply it to qooxdoo and the front end.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I forwarded to everyone a link to a reasonably complete yet relatively brief write-up which tells you &lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;everything you need to know about Cells&lt;/a&gt;. I know that if I were in your shoes I would not have read it so I presume no one has. But I would like to determine how many folks I will be boring to tears if I review said document, so I will first cut to the chase and ask if anyone has any questions based on what they read.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;........silence..............&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;OK. Cells is at once the simplest and hardest thing in the world for programmers to understand. Simple because the idea is just to have slot values of objects work like cells in a spreadsheet, and everyone knows how spreadsheets work. What is hard is understanding that one can program computers this way. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I only have fifteen minutes so: Yes, you can. Program inputs are assigned by good old imperative code to input cells the same way a user types values into a spreadsheet when they are doing what-if analysis or recording, say, actual monthly expenditure into a budget spreadsheet. Intermediate, derived, and aggregate cells compute new values based on those new inputs from predefined rules just as user changes to a spreadsheet propagate to other spreadsheet cells. Observers on cells let the emergent working model manifest its decisions with more good old fashioned imperative code, usually by simply updating the screen or playing a sound or controlling some external device over a serial port or updating a database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Boom, we're done. Why is it so great? What part of the superiority of functional and declarative paradigms should I explain first? As I outlined in the material you did not read, a lot of things have to happen when a program receives an input. The programmer coding the event handler has to look at the event and decide all the things that have to happen in light of that event, and any things that follow from those first things. Not only must they reliably see to all those things, but they must do them in the right order. The analogy to a real spreadsheet is quite strong, if you imagine hand-implementing a spreadsheet with old-fashioned pencil and paper.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the first things Cells does is eliminate a lot of work and thus a lot of bugs. Because the work eliminated is tedious, Cells also makes programming a lot more fun. But there is more.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The declarative paradigm means I always know why a slot has a certain value, because all the logic appears in one place, in the rule assigned to that slot. Without Cells any number of lines of code may have assigned a value to a particular slot and a unified deriving rule certainly cannot be divined even if one were to track them all down.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is more. Most people hate OO because it never quite panned out. Objects turned out not to be reusable. One of the nicest features of Cells is that two different instances can have different rules for the same slot. That makes objects reusable. Yayyyyyyy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I did not use Cells in the Kleaner because that was more of a straight calculation running from start to finish. I like to decribe the role for Cells being in any situation where one has an unpredictable stream of data and one is keeping a model with a sufficiently large amount of internal state consistent with that stream of inputs. Two examples being a GUI and a RoboCup client. The Kleaner worked by compiling statistics from a fixed store and then translating exactly once dirty data into corrected data. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Where Cells would have been useful would have been in implementing Phil's ideas about an ongoing stream of data leading to rediscernment of things previously discerned. Cell rules would take new raw inputs and propagate them over to tables of probabilities which would then reach out to existing cleaned data and possibly redecide from the original raw state a new cleaned state. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So no, I do not use Cells for everything, but in this case it was only because the full functionality had not been addressed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A fun note is that I have in the past applied Cells to a database, specifically the old AllegroStore persistent CLOS database. This works two ways. One is that a user can be looking at a screen and as the underlying data changes the screen changes. That may sound like old news but with Cells one doe not have to write any code to make it happen. One just says "this view shows this users overdue books" and when the date changes the overdue status on every book gets updated and a new book appears in the list on the screen if someone happens to be looking, simply by someone having written code to list overdue books on the screen as if it were an unchanging value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other thing that happens is hinted at above. Things like overdue books and amount of fines owed and paid can be calculated from scratch by reading a users entire history of checkouts and returns, but sometimes it is useful to record such derived values in the database and update them incrementally as books are checked out and returned. We can have code in programs do it and hope they run at the right time, or we can have the code in the database (as datapoints mediated by Cells) and be sure they run and run immediately. We get timeliness of data, efficiency, and we still get consistency even as we introduce redundancy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I left something out. That is bad because the thing I left out is the thing I am planning to do with Cells on my own anyway and then apply to the FE. Cells makes it dead easy to drive a separate framework from Lisp. In my note I mentioned tcl/Tk and Gtk. These are two killer C GUI frameworks with their own homebrewed little object models. We want to program in Lisp, and we want our models driven by Cells for all the reasons above. No problem. We build a model out of instances of CLOS classes mapping isomorphically onto Tk or GTk classes and use Cell observers to pipe information (thru an FFI or even literally a pipe) to the C library or runtime to drive there the creation and animation of C instances. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Works great, and one amazing programmer Peter Hildebrandt pulled off a trifecta in which he had Cells driving and driven by both GTk and a C physics engine, name forgotten.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For a while I kinda marvelled at how Cells could be so useful for such disparate activities, and do so in the same application, the two activities being building an application model and having some other programming framework dance to that model's tune. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I figured it out in time for ECLM 2008, not they were able to understand me. I opened by telling them that Cells was the single most powerful library they could use, because Cells is about change and nothing is more fundamental than change.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Programming is hard because like someone doing a spreadsheet on paper we programmers end up with the burden of propagating change thoughout our models. It is tedious work, it must be done reliably, and there is a lot of it as internal program state multiplies, exponentially a lot. This exponential growth in interdependence of program state is what led Brooks to declare that a silver bullet was not only unlikely to be found but that it would be impossible to find; he felt the complexity was ineluctable because as states multiply there is nothing that can be done to avoid the explosion of interdependence.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I wrote to Dr Brooks recently and asked him if he had ever looked at dataflow. He said he was familiar with the concept, but no. Oops.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1451611794856733046?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1451611794856733046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1451611794856733046' title='29 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1451611794856733046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1451611794856733046'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/02/cells-secret-transcript.html' title='Cells: The Secret Transcript'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>29</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-94725993430236426</id><published>2009-01-25T15:12:00.001-05:00</published><updated>2009-01-25T21:23:54.217-05:00</updated><title type='text'>Tinkering</title><content type='html'>&lt;span class="Apple-style-span"  style=" ;font-family:'Times New Roman';"&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;&lt;div&gt;Spring cannot come soon enough for Bobi, who is losing it badly these days on comp.lang.lisp:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Slobodan Blazeski wrote:&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;Dear board members&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm baseball player for a several time periods (days,&lt;/div&gt;&lt;div&gt;moths ,years,decades) I've noticed that interest in baseball is&lt;/div&gt;&lt;div&gt;dwindling, and baseball is becoming less and less relevant and will&lt;/div&gt;&lt;div&gt;soon become extinct with only baby boomers supporting it, and even&lt;/div&gt;&lt;div&gt;those are either going to die or switch to golf. In order to save our&lt;/div&gt;&lt;div&gt;favorite sport I propose we make drastic changes and adapt more modern&lt;/div&gt;&lt;div&gt;things like:&lt;/div&gt;&lt;div&gt;a. Playing on the beach sand wearing swimwear like in beach&lt;/div&gt;&lt;div&gt;volleyball, very modern sport. Check Thiobe for growth rate&lt;/div&gt;&lt;div&gt;b. Replacing bats  with  hockey sticks. Note that hockey is popular in&lt;/div&gt;&lt;div&gt;many world countries and we should think international&lt;/div&gt;&lt;div&gt;c. Including  24-Second Shot Clock like in NBA that will make our&lt;/div&gt;&lt;div&gt;sport more lively and fast paced&lt;/div&gt;&lt;div&gt;d. Square playing fields should be replaced with the more common&lt;/div&gt;&lt;div&gt;rectangular one like found in many popular sports : soccer, football,&lt;/div&gt;&lt;div&gt;tennis etc&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Including this will make baseball prosper.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;very truly yours&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;Concerned Semi-Ex Baseball Player&lt;/div&gt;&lt;div&gt;Avenue of delusional weirdos Number 23&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Bobi may not be as crazy as he thinks he is. Baseball suffered extreme popularity anxiety in the late Sixties and did indeed tinker with the game. Thinking more offense would attract more fans the pitching mound was lowered so pitchers did not get extra energy into the ball from falling into a pitch. The American League adopted the designated hitter to eliminate the 11% nil pitcher from batting lineups (eliminating as well an awful lot of interesting strategy). They avoided the salary caps of the NBA and instituted free agency (well, no, they lost a lawsuit) which allowed bigger markets like NYC, Boston, and LA to buy better teams, and bigger markets are always good for ratings. Minnesota fans will follow the Dodgers, Los Angeles fans will not follow the Twins. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The changes went beyond the playing field. Ballparks added mascots and a disgusting cacophony of party music between innings so loud you can barely talk, and limited alcohol sales late in games to make the experience more family-friendly cuz you know how the losing fans get in their third hour of drinking.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now baseball is hugely popular again so tinkering with grand institutions can work. Right?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wrong. In the end, baseball is just a great game: multi-dimensional and deep. Quality tells, and which quality one emphasizes matters. Hockey and basketball have non-stop action and are fading in popularity, while baseball and football like great music have a variety, a rhythm, a balancing of quiet against intense. Baseball has the pitch, football has the snap. All scales from small to large from inning or drive to the game or season always and invariably end up condensed into one point of explosive tension when the pitcher releases or the center snaps the ball.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Intense without quiet merely exhausts. A boxing match with two brawlers spurning defense landing bombs back and forth brings the crowd to its feet but those who love the sport do so for its nickname, The Sweet Science. They still talk about one genius of defense who won a round without throwing a punch. Between evenly matched fighters one solid punch (forget the knockout, the cartoon haymakers of Rocky &lt;span class="Apple-style-span" style="font-style: italic; "&gt;n&lt;/span&gt;) brings the crowd screaming to its feet, the culmination of rounds of careful, tentative, mutual exploration. A single knockdown becomes a cause for pandemonium and one punch knockouts almost do not happen between the best and when they do they are talked about for a long time. I digress.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tinkering. Basketball has all the action in the world and now faces its own popularity crisis. Racism is one factor, another is probably the salary cap that has San Antonio in the championship series instead of New York. Another problem: poor defense, and a twenty-point lead does not mean anything. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But worst of all is the lack of dimensionality. There just is not that much to these games to argue about over the water cooler. Baseball? Boston still talks about the time Grady Little [thx, Xach. ed.] left Pedro Martinez in one inning too long against the Yankees in game seven of the ALCS. Come on, he had thrown a hundred pitches! Everyone knows Pedro is useless after a hundred pitches! You just never hear anything like that about hockey or basketball, which both boil down to great athletes pretty much just playing run and gun.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Baseball never needed tinkering, though tinker they did. The fundamental quality of the game first ensured its survival throught the hard times when fans strayed for the quick fix of non-stop hockey and basketball action. Now the richness, subtlety, and sophistication of the game has some stadiums selling out most games of the year of a very long season.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moral for Lisp left as an exercise.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-94725993430236426?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/94725993430236426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=94725993430236426' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/94725993430236426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/94725993430236426'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/01/spring-cannot-come-soon-enough-for-bobi.html' title='Tinkering'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-4960005538372806404</id><published>2009-01-20T13:38:00.005-05:00</published><updated>2009-01-27T07:50:45.369-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tilton&apos;s Law software engineering'/><title type='text'>Tilton's Law: Solve the Failure First</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;The team was at my throat. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Just use the new search!," they bellowed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The mission critical, project saving, do or die demo to upper management was eight hours away and we had not even begun the always dicey process of moving the software from the development system to one within reach of the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Demomeister&lt;/span&gt;, and I was trying to find out why the old search was so slow.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Soon," I replied.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We had a new search I was told was a screamer but I continued poking around putting in metrics trying to figure out why the old search was so slow. Had we not been a virtual remote telecommuting team I would not have lived to tell this tale but we were so they had no choice and I reassured then that "soon" meant ten minutes and they shut up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why was I still trying to understand the perplexing sloth of the old when a whole new replacement module was available and working fine and pretty much the demo on which all our jobs and a cool project depended was coming on like freight train?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Tilton's&lt;/span&gt; Law: Solve the failure first.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Early on we learned the other side of that coin: &lt;a href="http://smuglispweeny.blogspot.com/2008/03/tiltons-law-solve-first-problem.html"&gt;Solve the first problem&lt;/a&gt;. The commonality is...no, let's do the war story first, war stories are more fun than preaching.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Back we go a quarter of a century to my first contract with a client who would become my sole recurring client for the next decade. I was being hired to take over maintenance of an application whose author had been one of the first to die of AIDS. I was reminded of the whole business by a conversation with another developer recently about the nature of working on OPC. Other People's Code. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my IT career I have worked always at the poles of software development, either writing new code or performing massive overhauls of OPC, never that relaxed zone between in which one simply maintains and extends in small ways a long-lived system. The second pole (OPC overhauls) always seemed to me an intimate one-way encounter with some anonymous predecessor, an encounter usually involving me roundly and steadily cursing them out. You can imagine then how eerie it was working on this system from this predecessor who was not so anonymous this time, especially when I learned that the poor guy was in bad shape during one stint but needed the money and so worked on the code I was now working on even as his fate rose up to meet him (this well before the days of the cocktails of today that make ones fate less certain). This guy I do not remember cursing out so much.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But I digress. Our lesson today is how to piss off your coworkers by insisting on solving a failure first, by which I mean even if you do decide to punt on X make sure you understand how X failed. I am not alone in this. In 2001 the movie when the crew determines that the unit Hal said was no good was fine he says fine let's put it back in and let it fail. Sure, he was really looking for a way to kill the crew but we learned in 2010 that Hal was just a computer system and I think the bit about putting the supposedly OK/not OK system back in to see if it failed was one of Hal's systems working nominally in accordance with Tilton's Law: we need to understand broken things.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[Aside: a good example of &lt;a href="http://sitereservation.com/xooglers/index.cfm?entryid=24"&gt;the Hell of Not Solving Failure&lt;/a&gt;.]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And now at long last, my unsolved failure. My predecessor's, actually. The application was a securities database with a nightly feed of data applied to the cumulative DB by a batch program. This is late 80s, primitive stuff. A security could have three IDs because three groups were tracking securities and each had their own ID system. We had tens of thousands of records in our VAX/VMS RMS file, and a separate RMS key for each of the three possible IDs. So far so yawn. Here comes the fun part.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Two of the IDs were populated all the time. The other one was populated five percent of the time. Big deal, right? Right, very big deal, the poster boy for Solve the Failure First. What happened was this quesswork reconstruction:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My predecessor Paul (I picked "Paul" because it easier to type than predecessor) had a problem. His program ran an initial test load of a hundred securities in a few seconds. Fine. Everything looked good. So then he ran it against a full daily feed, which would include news of every security traded that day so it would be -- OK, I confess I completely forget even the order of magnitude, let's say tens of thousands and declare up front that that is idiotic and I am sorry, but here is what happened: the damn thing ran forever. There probably was no immediate specific great mystery because Paul probably had the program printing something (a count, the last ID recorded, something) right to his VT-100 console as it went and he could see that the program had started out zooming along but then gradually got slower and slower until just adding one security to the database (and this is just good old ISAM, mind you) took... wait for it... twenty seconds. Oh. My. God. What on earth is happening?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Paul got a clue. Every once in a while two records were written out bang-bang, as fast as at the start. Dig dig dig puzzle puzzle...ah, there it is. Any record for which we have all three IDs is written out in nothing flat. Any record (you know, the ninety-five percent) with just two will (by the end of the run) be written out three per minute, 180/hour, or 1000/fuggedaboutit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Paul realized what was going on. The ISAM file system had no problem storing data with duplicate keys, which was a good thing because Paul was storing a whole lot of data with one key 95% the same: spaces. Poor ISAM it seemed was chugging thru all the duplicates looking for the last one after which it would record the latest duplicate. And apparently it took twenty seconds back then to walk (effectively) the entire index of a hundred-thousand record file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the good news is that we would never need to look something up using spaces as the key value sought, so....what can we do? Paul was no slouch. He popped open the RMS reference manual and to his delight discovered he was not the first to pass this way and gleefully added the option "NULL_VALUE=SPACES" (translated: "if the value is spaces, Just Don't Index this record on this key") to the key definitions in the file definition script he was using to initialize the file and recreated the file and re-ran the program from scratch.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The change did not help. At all. I think we all know that feeling, as visceral as a dropping elevator.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There it was, the option explicitly intended to solve the problem he had explicitly encountered,  and it did not change a thing. Impossible. But this happens to us programmers all the time.  We know what to do. Compile the damn code, because we made the edit change but forgot to compile. Or link. Or, in Lisp, to zap the faultily specialized method. Or something.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So Paul edited the definition again and checked that NULL_VALUE = SPACES was the right syntax and right spelling and on the right key -- to hell with that, he put it on all three damn keys -- and he saved it and checked the date and created the file again and ran his program again and you know it did not run any faster or I would not be telling this story.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;OK, time to get serious. Or if he was good he did this without all the huffing and puffing of the preceding paragraph. He Just Typed In "rms/analyze sdb.dat". And RMS looked at the file itself (not the script used to create it) and confirmed that "NULL_VALUE = SPACES" was operative for all indexes.&lt;br /&gt;&lt;br /&gt;Momma don't let your kids grow up to be programmers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What comes next is hard to convey. I can tell you but if you have not worked on this code or (we will learn) run this batch application it is hard to convey how much blood, sweat, tears, CPU time, and delayed nightly batch closes for how many years resulted from Paul's not first solving the failure of NULL_VALUES=YES. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, maybe this is a fair glimpse of the enormity that followed: the problem got sorted out only because the head of operations and I got to talking one day and he pretty much ended up down on one knee begging me to find some way to eliminate the two-hour merge step that held up the nightly close every night. I had never heard this before, though I had been overhauling the system for months.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"It just sits there for two hours," he groaned. "It kills us every night. Please, if you can, please, do something to make this go away."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whoa. I had inherited this system and been asked to enhance it but no one had said a word about this. The code was far and away the best OPC I had ever dealt with so everything got the benefit of the doubt, including the (soon-to-be explained) two hour merge. As in, if it is there, it must be there for a good reason. What was not there was The Story of the Unsolved Failure of NULL_VALUE=SPACES, but even if it had been I would have taken that at face value, too, because the NULL_VALUE option was unknown to me. But enough of this flash forward, let's get back to poor Paul.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;NULL_VALUE was not working as it should. Software is like that. Good programmers do not let bad software stop them. Plan B. A rule is born: Thou shalt not write new securities to the securities database where the massive duplicates will make each write take twenty seconds. Paul decides to write them to a second file initialized empty on each run. Since we only got dozens of new securities in one batch, that file would never have the massive count of duplicates and writes would be lightning fast. Then we just do a sort/merge at the end of the batch to combine the new securities in with the old. Oops. "Just."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The funny "you can run but you cannot hide" moral within the moral being that I did the calculations one day and worked out that twenty seconds times the usual number of new securities in a day was exactly as long as the sort/merge that was just killing the folks down in operations. And I bet Paul realized that but only after writing all the crazy code he had to write to work with two files at once as if there were only one file and at that point he just gave up and moved the thing into production. Speaking of crazy code...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You should have seen it. Looking back I cannot recall why it should have been so hard, but I did overhaul that code and I was forever tripping over it. The idea is simple. To look up a security to see if we already have it, first look in the real DB and if it is not there look in the daily "new stuff" DB and if it is not there, ah, it is new. If it is, update it. Just remember to update the right file, because we can get data from two sources about the same new security.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Piece of cake, right? A bottleneck function for all reads and updates... anyway, it seemed like the issue was always getting underfoot as I worked, and just looking at the code one saw again and again this check here/there code, and both Paul and I were the kind of engineers always on the lookout for ways to make code non-redundant. I would think my memory was faulty but I also remember eliminating Paul's Plan B after solving his failure first and &lt;span class="Apple-style-span" style="font-style: italic;"&gt;that &lt;/span&gt;was no picnic. It just permeated the application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what was the first failure and how did it get solved? First, I had noticed the issue myself while using Datatrieve to add a record to the securities DB for test purposes. I hit enter and thought I had crashed the system because it went away and never came back and like every egomaniacal programmer out there I always assumed that whenever a system stopped responding the last thing I had done must have broken it so there I sat in dread for twenty seconds until the system finally responds. Wow. Twenty seconds? And then I guess I added a record specifying all three keys and it responded instantly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But this idea of null values not being recorded in an index was new to me, and we did not have the Internet back then where I could just ask the ether what was going on so it was only a coincidence that just after the guy in operations had begged me for a fix that I was visiting with the lads from a prior contract and I moaned that RMS sucked because it could not handle files with hundreds of thousands of records and they laughed at me and said they were handling millions with RMS. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can actually remember the look on my face, a neat trick when you think on it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I haul ass back to work and pull out the RMS reference manual and I can tell you that dead trees aside there is one good thing about paper documentation: right above the entry for NULL_VALUES close enough to catch my eyes was the entry for NULL_KEYS.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yep. You need to specify both. Paul had specifed NULL_VALUE=SPACES. He had not specified NULL_KEYS=YES. The default for NULL_KEYS? Guess.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I kinda wretch inside even now thinking about the astonishing amount of money, work, debugging, and delayed batches that followed from one simple failure to understand one broken thing. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The metalesson shared with "Solve the First Problem"? In programming, never deal with the unknown. This game is hard enough.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Epilogue&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The punchline is that I never solved the first failure from Scene I of this tragedy. As my father used to say, "Do as I say, not as I do." We &lt;span class="Apple-style-span" style="font-style: italic;"&gt;did &lt;/span&gt;have a deadline, and I &lt;span class="Apple-style-span" style="font-style: italic;"&gt;did &lt;/span&gt;narrow down the location of the problem in a way that reassured me somewhat that it would not jump up to bite the new code in the rear end. And even in its breech the law is confirmed: we &lt;span class="Apple-style-span" style="font-style: italic;"&gt;do &lt;/span&gt;need to address the underlying problem which I have some confidence I now understand because it still presents problems for the software but it will go away only when bigger problems are solved and they are much bigger so I am keeping my sights set on them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-4960005538372806404?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/4960005538372806404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=4960005538372806404' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/4960005538372806404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/4960005538372806404'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2009/01/tiltons-law-solve-failure-first.html' title='Tilton&apos;s Law: Solve the Failure First'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-2952451628360585841</id><published>2008-12-29T02:23:00.009-05:00</published><updated>2009-01-08T06:19:48.788-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript ajax frameworks qooxdoo RIA Web 2.0 Lisp jQuery Dojo YUI HTML CSS'/><title type='text'>The Road to qooxdoo Part III: Why It Rocks</title><content type='html'>In the episodes &lt;a href="http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo.html"&gt;one&lt;/a&gt; and &lt;a href="http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo-part-ii.html"&gt;two&lt;/a&gt; we learned all about how a Lisp God and Interwebby know-nothing found a way to support a client needing an enterprise Ajax Web application, said way turning out to be &lt;a href="http://qooxdoo.org/"&gt;qooxdoo&lt;/a&gt; after solid efforts to make jQuery, Dojo, and YUI fill the same bill. But we did not learn very much detail about qooxdoo, we just learned that it comes with lots of doc, lots of examples, a solid community, and that the engineering is first rate. I may not have mentioned this, but it also was dramatically faster/smoother than the others on my acid test: scrolling a datagrid. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Okay, that &lt;span class="Apple-style-span" style="font-style: italic;"&gt;is &lt;/span&gt;a lot as a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;general &lt;/span&gt;recommendation. I mean we did not learn much detail. Until now. Here are four Big Things that really stand out:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;1. HTML? CSS? Never heard of 'em.&lt;/span&gt;&lt;br /&gt;First comes a shocker. The qooxdoo user codes no HTML or CSS and needs know nothing about those two disappointments. Just as my Lisp compiler reads my Lisp code and spits out optimized native machine code, qooxdoo takes your qooxdoo/Javascript and produces the HTML and CSS to drive the browser. Upside: qooxdoo developers write less code and never have to worry about browser variability again.&lt;br /&gt;&lt;br /&gt;To a Web noob like me there is a second big win here: I do not have to &lt;span class="Apple-style-span" style="font-style: italic;"&gt;learn &lt;/span&gt;HTML, CSS, or the vagaries of the different Web browsers my client might want supported. I am a bit of a rarity in my ignorance of those things but soon I should have a lot of company now that qooxdoo has set the bar as high as it has on insulating the web app developer from lower level technology.&lt;br /&gt;&lt;br /&gt;By the way, in case you are wondering: yes, there is a widget (two, actually) that will accept classic HTML.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;2. I do declare. Not!&lt;/span&gt;&lt;br /&gt;The second thing that hits us is a consequence of the first: we are going to be writing a lot more Javascript than we would be with libraries such as Dojo where authors still write HTML/CSS. With declarative tools we sit in Lisp or Ruby or PHP on the server generating HTML. Not qooxdoo (but see next)  and not YUI.&lt;br /&gt;&lt;br /&gt;I am not at all happy about this but I will live and if it ever bothers me enough I will spend a weekend exploring the qooxdoo markup contrib called &lt;a href="http://qxtransformer.org/"&gt;QxTransformer&lt;/a&gt;. Right now I need to catch up on a backlog of functionality the client has had to do without because of the six weeks it took me to identify qooxdoo as The One.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;3. OO is not the Grail, but OO rocks&lt;/span&gt;&lt;br /&gt;Stendhal said it best in "On Love" in the chapter on Infatuation: (paraphrasing poorly) we do the object of our desire two injustices, first setting them on a pedestal unreasonably high and then, when they inevitably disappoint, setting them too low. OO is not the Grail, it is just a profound advance in serious application development. All by way of introduction of another stunner: qooxdoo's slightly more substantial object model layered atop the core Javascript OO capabilities. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To be honest this struck me as a bit of a yawn until I decided to start carving up my existing code into distinct qooxdoo classes. This is a very big application and I needed code re-use almost immediately and doing it in HTML with Javascript glue was...well, before qooxdoo I was pretty much starting to build my own abstraction layer atop the core tools--there was no way around it.&lt;br /&gt;&lt;br /&gt;But now that I have used qooxdoo's OO to partition my rapidly growing code base I have more than once had that wonderful sense of getting something for nothing after doing a major refactoring (you know, taking all the pieces and throwing them up in the air) and having it Just Work after two or three tweaks. Furthermore, I will not bore you with the details but I have not even started leveraging the full capabilities of qooxdoo's object layer: even more benefit will be reaped moving forward because of some nifty &lt;a href="http://en.wikipedia.org/wiki/Reactive_programming"&gt;reactive&lt;/a&gt; capabilities.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This came as a pleasant surprise. I do more OO in more ways than you can imagine in part because I normally program with Lisp's CLOS which is to normal OO what normal OO is to binary arithmetic but by the time I stumbled onto qooxdoo I had been doing Javascript, HTML, and CSS for a couple of months under a lot of pressure so I never had the time to build a sensible OO abstraction atop Javascripts primitive little OO pretensions. Thus Javascript had endowed me with a bit of &lt;a href="http://en.wikipedia.org/wiki/Shoshin"&gt;child mind&lt;/a&gt; and I was able to experience the mundane code structuring win of OO as if for the first time. It rocks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;3. Layout the Wazoo&lt;/span&gt;&lt;br /&gt;I may have lied. This may have been the first stunner I felt in my gut. The others I knew would be huge if they panned out, but this was the first one I saw in action working as beautifully as had the other frameworks left me hanging. With other frameworks I could find no way to get built-in layout schemes to use the full window real estate available. That cuts two ways: I either ended up with unused whitespace (and with our app we need all we can get) or my application panels grew so large that the browser itself put up scroll bars, meaning I had to window-scroll my scroll panes around. No, that was not a candidate for production release. Note that to a large degree this is the same as point #1: a framework is not hiding HTML/CSS from me if I am still victim to surprising browser decisions, such as oh gosh that is big let's use a scroll bar here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;How good is qooxdoo at layout? When I popped open the Firebug debugger in FireFox, where by default it begins by seizing application window real estate, the qooxdoo layout engine handled the downsizing impeccably, right down to adjusting scroll bars to accurately reflect the new dimensions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;4. Message In A Bottle&lt;/span&gt;&lt;/div&gt;&lt;div&gt;This feature is huge in a small way, by which I mean I could probably roll my own version of qooxdoo's Message mechanism in a an hour but--wait for it--I did not have to. They did. That is huge, the huge thing being that the qooxdoo team really has set out to create a compleat Web application development environment and with such a beast comes pleasant surprises such as their Message mechanism which allows a nice decoupling of widgets: one widget can dispatch "Make it so" and anyone responsible for "it" knows to roll up their sleeves simply by having subscribed to "Make it so".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Beyond the Message mechanism we have the Event mechanism. The documentation of every widget lists the events it might generate and what data the event will carry, and in toto we have an engine with an event model dozens of times richer than pure DOM.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;5. I know, I said "4"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Number five is an umbrella win, too detailed to list: as I whined above, this Lisp God is now writing an awful lot of Javascript leveraging more and more qooxdoo all the time. Again and again your highly critical correspondent is finding nothing but good news in qooxdoo. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yes, I could make a bug report every other day if I had the time, but a long time ago I figured out that I am not looking for a perfect library, I am looking for a powerful library that is fundamentally sound (so anything broken can be readily fixed) and actively maintained (so things actually get fixed).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;/div&gt;&lt;div&gt;qooxdoo: fast, powerful, complete, rich, well-engineered, and it hides browsers, HTML, and CSS. Great doc, loads of examples, fine community. It's all good.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-2952451628360585841?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/2952451628360585841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=2952451628360585841' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2952451628360585841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2952451628360585841'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo-part-iii-why-it-rocks.html' title='The Road to qooxdoo Part III: Why It Rocks'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1193706948969696207</id><published>2008-12-13T23:24:00.006-05:00</published><updated>2008-12-28T07:17:13.892-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp qooxdoo QxTransformer Dojo Yui Web 2.0 development Javascript framework PHP Python'/><title type='text'>The Road to qooxdoo - Part II</title><content type='html'>&lt;a href="http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo.html"&gt;Last time&lt;/a&gt;, we learned how one self-appointed Lisp God with no knowledge of web programming ended up programming the web and then soon enough embarked on a six week grand tour of Javascript frameworks in search of a platform suitable for an enterprise web application and where his tour ended: qooxdoo. That episode ended with a promise of more information on qooxdoo, but first a note on the methodology: there was none.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My first experiment with web programming had thanks to the marvels of Lisp in general and AllegroCL's web tools in particular mushroomed into a full-blown web application aided here and there by jQuery widgets before we slowed down enough to think, Damn, we could benefit from a full-blown Web application framework.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; So I eyeballed the usual suspects and ran them through &lt;a href="http://googlefight.com/"&gt;googlefight&lt;/a&gt; and picked the most promising one and used that to redo what I had accomplished to date. Which was: tab controls, select boxes, data grids as views into server-side data stores, tree views, text input, tool tips, pushbuttons, pop-up windows, and probably one or two things I am forgetting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;How did I assess the libraries? We needed a professional look, good performance, and maximum productivity. Sorry if that seems blindingly obvious. The productivity assessment has some beef: I looked for lots of documentation and tons of examples describing a rich set of widgets at once high-level, feature-rich, and yet highly authorable which may not be a word but it means I get to override stuff without resorting to back doors. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I considered also two metaqualities: on-line support and internals code quality. Having the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Front/index.htm"&gt;Lisp HyperSpec&lt;/a&gt; an F1 away is just a little faster than asking for the same information on comp.lang.lisp. ie, Community matters. As for code quality, the good thing about open source is not that it is free, it is that I can use the source to understand things at 3am when the community might be quiet; I can add print statements to debug my code; and maybe I can find and fix a bug in the library. But if the code is of low quality good luck with anything more than the print statement insertion.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It was a rough six weeks. Three times in six weeks I logged onto support groups and said, "Hi, this is my first day..." as I rebuilt a relatively feature-rich web app three times while staggering up to speed three times on three environments. All while the client is getting absolutely no new functionality. I feel bad all the while because they need this stuff &lt;span class="Apple-style-span" style="font-style: italic;"&gt;now.&lt;/span&gt; I am letting them down and there is the strong possibility they will be letting me go: I had been brought on to do the Web front-end. I like learning, but not so much with a gun to my head and a time bomb ticking.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Are we having fun yet? Well, yes. The last framework we tried was qooxdoo and it has worked out great. I can now give the client pretty much what they want fast and looking good once they pony up for a graphic artist because I just saw this &lt;a href="http://juhukinners.com/2008/12/23/qooxdoo-in-the-ct/"&gt;impressive example&lt;/a&gt; of what can be done with their "appearance" framework. But I ain't no designer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Funny thing, though: qooxdoo  like YUI and Dojo came up short during the evaluation. It had no example of the widget I needed most, a fairly standard widget at that: a datagrid backed by a remote store. Bad sign. Second, qooxdoo did no better on googlefight than does Lisp, and that is pretty bad. Finally, qooxdoo like YUI lacks a declarative programming model [though the declarative &lt;a href="http://qxtransformer.org/"&gt;QxTransformer&lt;/a&gt; has been revived since my original investigation] which means I cannot just sit in my Lisp IDE catching XHRs and tossing back HTML/CSS. This would put a non-trivial dent in my productivity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So how did qooxdoo prevail? What can I tell you? Bullet charts are useless, expert systems work great as long as expert humans interpret their output, and resumes tell us nothing about the work we will get out of people. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;qooxdoo &lt;span class="Apple-style-span" style="font-style: italic;"&gt;did &lt;/span&gt;have a contributed example of a remote data store which pretty much worked and when I looked at the qooxdoo internals to learn how to make it work better I found very good code and rather quickly had the datagrid I needed. Otherwise qooxdoo did have loads of examples and documentation and decent community (I say "decent", you'll say "great"--my standard is comp.lang.lisp) and then we get to the bottom line.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While resurrecting my app for the third time with qooxdoo, yes, I worked just as hard as I did using Dojo and YUI. But the effort was different. With qooxdoo I was struggling to learn a very nice framework that needs an index: I was slaving for six hours to find the simple six lines of code I had to write. With YUI I was struggling with a framework that did not work all that well and scared me more and more the more I looked inside it. With Dojo the struggle was with a good framework but the struggle was such that I suspected the struggle would never diminish and probably increase exponentially as the application grew in complexity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As for the declarative thing, hey, I am a programmer, I can write code. And Javascript has a lot of Lisp soul, I am not stuck with something daft like PHP or Python. Sure, having to spend more time in a JS IDE means a ten percent productivity hit but ten percent we can do. The terror we developers dread is the tool nightmare death by a thousand cuts two steps forward two steps back rope drag death. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will blog on rope drag sometime soon, but first let's get specific about qooxdoo. In Part III of my Road to qooxdoo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1193706948969696207?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1193706948969696207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1193706948969696207' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1193706948969696207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1193706948969696207'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo-part-ii.html' title='The Road to qooxdoo - Part II'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5609758665124194473</id><published>2008-12-12T20:19:00.010-05:00</published><updated>2008-12-29T02:15:29.853-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript ajax jquery dojo qooxdoo yui comparison'/><title type='text'>The Road to qooxdoo</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;[The title of this rather boring entry derives from a fun little &lt;/span&gt;&lt;/span&gt;&lt;a href="http://64.233.169.132/search?q=cache:http://wiki.alu.org/RtL_Highlight_Film"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;survey&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; I kicked off years ago.]&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;OK, why should you listen to a Lisper on Javascript frameworks? Because we use Lisp so obviously we have better instincts when it comes to developing applications. In fact, this road would not have ended so well had not Lars, a fellow Lisper developing a killer new Lisp Web programming framework called &lt;/span&gt;&lt;/span&gt;&lt;a href="http://groups.google.com/group/symbolicweb?pli=1"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Symbolic Web&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; (SW) brushed aside my enthusiasm for &lt;/span&gt;&lt;/span&gt;&lt;a href="http://dojotoolkit.org/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Dojo&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; and mentioned he found &lt;/span&gt;&lt;/span&gt;&lt;a href="http://qooxdoo.org/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;qooxdoo&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; interesting, although for now SW uses a little &lt;/span&gt;&lt;/span&gt;&lt;a href="http://jquery.com/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;jQuery&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;. "A little" because the whole idea of Symbolic Web is to do most of your programming in Lisp which of course is the only way to go but SW is still emerging from the sea and I had a requirement &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;now&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; (well, six weeks ago, but there is major new release of SW just out I need to look into but as this Road will reveal I am not likely to change horses now because of what I found in qooxdoo (not that SW will not eventually catch up)). Gasp.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;The second question might be how a Lisp god and Interwebby know-nothing ended up doing heads-down intense Interweb development. Well, it was the Lisp credentials. A former client using mostly Lisp was having great luck with a Ruby/Rails front end but was looking for more speed and hoped having a Lisp image serve the pages directly would make for better response.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;What happened next was pretty neat, and again Lisp conquers all. I told the client I would look at what they had and what they needed for a few days to decide if even I could help them, because I can do a lot of things but one thing I cannot do is exaggerate how little I knew about Web programming and even static HTML eight weeks ago.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;A glance at the existing screens and Rails code had me thinking, "No way", but I was curious anyway about even getting an application to drive a web site so I fired up a tutorial on Web app development using &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.franz.com/support/tech_corner/ajax.lhtml"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;tools&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; from my Lisp vendor of choice, &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.franz.com/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Franz&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;How good are Lisp, Franz,  the tutorial, and the WebActions tool? In the three days I was supposed to be deciding whether I could help the client I managed to execute a respectable fraction of the first component they needed.  Sorry, no screenshots, NDA and all that.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;So now there I am with a contract and a browser toolbar sagging from the weight of bookmarks to sites on &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.w3schools.com/sitemap.asp"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;HTML, CSS&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;, and for the hell of it jQuery though I was not sure why but everyone was jumping up and down about it. And then I needed it.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Well, not jQuery. I needed a razzle-dazzle spreadsheet-like grid presenting data from an arbitrarily large table of data held on the server. Now at this point I had already rolled my own Ajax paging mechanism, but something superficial but nonetheless important for that this being an important application was holding me back: my HTML looked like crap. Meta-holding me back was my sense from surfing the Web that getting good results out of HTML/CSS was a black art requiring years of practice which certainly leaves me out. Enter &lt;/span&gt;&lt;/span&gt;&lt;a href="http://webplicity.net/flexigrid/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;FlexiGrid&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;. A URL which as I write responds "&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Please contact the billing/support department as soon as possible." &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;Which brings me to why I dumped jQuery. What I found was small, yes, and add-ons, yes, but a hodge-podge of add-ons does not a professional development environment make. By the time I punted I had contribs from three people and while each was lovely alone together they looked like, well, a great decorator on a multiple-personality binge. And beyond appearance there came a surprising result: FlexiGrid did not offer a "row selected" event. Meta-worse was the author's response. "Right, no row-selected event." Ooops. Next up was jqGrid and that was fine but I still had Crazed Decorator Syndrome going and now I am looking for the next widget I need and a light went on: we are building an application here, not a Web page/site. It is wonderful that jQuery is small, but small is exactly the wrong thing for developing a sophisticated application with a coherent look and feel never mind coherent engineering underneath so widgets can play well together. Enter Dojo. But first...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;In case you are wondering where the client went, they are encouraging my search for a pre-fab solution. Probably seeing the gorgeous FlexiGrid widget compared to my ugly efforts did not hurt, but the client has good instincts anyway (they use Lisp, right?) so they are leaning towards my original assessment that I am overmatched if I am going to try to turn out a hot application on short experience with HTML and CSS even though at this point I have wondered aloud to them how much HTML/CSS I might have mastered in the same time I was spending beating my head against pre-fab, this being the classic failed deal we make with the devil when we reach for 4GL: yeah, wow, a complete browser screen in five minutes. Gee, could we get the first sub-item appearing on the same row with the item? No. The client wants it. It cannot be done. That was Datatrieve on VAX/VMS twenty-five years ago, but nothing has changed. 4GLs get their apparent power by making decisions for me which works only if I (and my client) are not making any decisions.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;But no, the client says "find a framework" and I decide to try again with Dojo. Again?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;I had looked at Dojo before. The word on Dojo was incredibly good. Of course that word was from their Web site. When I tried to confirm by eyeballing the doc I could not find it. I mean, there were some great links, but all the pages they led to were blank. Next! But now I was back, encouraged by the news that &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.openlaszlo.org/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;OpenLaszlo&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; had just placed a bet on Dojo. IBM as well, but OpenLaszlo is more important because I know they are geniuses, they have a dataflow hack like &lt;/span&gt;&lt;/span&gt;&lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;mine&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Oooh-ooh! Another reason Dojo looked good was a &lt;/span&gt;&lt;/span&gt;&lt;a href="http://blog.creonfx.com/javascript/dojo-vs-jquery-vs-mootools-vs-prototype-performance-comparison"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;benchmark&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; I had found showing the thing was fast. I have no idea if the benchmark is valid, but the pictures are gorgeous so I trust it. So why did I dump Dojo?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Well, OK, I did not really. It came in second. The question is why did I keep looking such that I found the eventual winner. Easy: too frickin hard to get to work. The documentation is awful. They know this and are addressing it but did I mention we need this &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;now?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; Overall Dojo fit the bill of being a Compleat Solution with solid backing and a great future, but after banging my head against the wall over something (ah, it was the six hours I spent trying to figure out the "build" mechanism for a compressed production release of my JS culminating in watching a blurry video that finally showed how to do it) I went for a better way surf (as in there's gotta be) and saw &lt;/span&gt;&lt;/span&gt;&lt;a href="http://developer.yahoo.com/yui/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;YUI&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; touted as a serious solution.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;A quick glance at the enormous volume of well-organized documentation and exhaustive examples and the client and I agreed at once to give it a try. And I will tell you right now YUI has the best graphic designers, because their stuff looks &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;hot&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;. Dojo is a close second there, too. YUI is a complete solution with a big backer, gorgeous style, and more doc than you can imagine. How did it get dumped?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Stuff was not working well. Even with all the doc and examples it was hard to get working. When I dug into the source to see why things were not working, I did not like what I saw. And the death knell: YUI abandons the declarative model. Why is this so bad? Hellooooo, Lisp? Remember?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Up thru Dojo I was programming in Lisp 90% of the time, doing just enough JS to get information back to the Lisp server application where HTML could be generated and sent back, even that Lispily thanks to HTML generating macros. And YUI was going to make me give that up and be as hard to figure out as Dojo and I suspect worse under the hood. So regretfully I informed the client my battles with Dojo would be resuming.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;So how does this road end up at qooxdoo? &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;The weekend was coming up. Weekends are mine, so I decide to follow-up on Lars's hint about qooxdoo. qooxdoo is the ultimate threat to YUI because qooxdoo also says Just Code Javascript, and if I am forced to do that by YUI I may as well do it in qooxdoo where the code is as good as YUI's is bad. (I looked at about fifty lines of it for five minutes, I should know.) Anyway....&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;qooxdoo is amazing. They need help on the graphic design (never look directly at their tab control, use a mirror) but other than that the engineering is terrific. [My bad: they simply leave anything more than the utilitarian look up to the developer, witness this &lt;a href="http://juhukinners.com/2008/12/23/qooxdoo-in-the-ct/"&gt;before/after&lt;/a&gt; case study.] The documentation and examples are also abundant here, and the support is great. They even do &lt;/span&gt;&lt;/span&gt;&lt;a href="http://qooxdoo.org/documentation/0.7/properties"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;dataflow&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;! Yes, I wish I could spend all my time in Lisp sending over HTML, but two things on that.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;One, there is a side-project that brings a declarative model back into qooxdoo.&lt;/span&gt;&lt;/span&gt;&lt;a href="http://qxtransformer.org/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; QxTransformer&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;. I have no idea where that stands, but I did see a note on-line where a developer spoke of it in the past tense. [Now &lt;a href="http://qxtransformer.org/"&gt;resurrected&lt;/a&gt;.]&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Two, hey, I can write some Javascript. I did ten years of C before I did fifteen years of Lisp, Javascript is not a problem. And it even has lambda, something &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.python.org/%7Eguido/"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;this guy&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; still does not understand. Lisp/markup would be better, but when dealing with mission-critical stuff (the client is doing valuable data crunching but does not win until they make it accessible) any team can roll up its sleeves and crank out the work even if they have to do without the brilliance of Lisp.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;This entry is getting long and I am getting tired and my bartenders are starting to worry about me so I will leave a detailed praise singing of qooxdoo to my next entry, but allow me a bit of a rant. What a mission-critical effort cannot stand is fundamentally flawed solutions that seem to offer a fast track but in fact bleed developers to death. This can be jQuery with an incomplete solution forcing me to try to build an application out of mom and pop contribs or YUI with fundamentally bad code or some other framework that might be just plain slow.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;As a developer I am not looking not to work, I am looking to have my work yield quality results predictably. I might spend four hours trying to figure out how to do something in qooxdoo but once I do it turns out to be insanely simple and work beautifully. Moral: their documentation needs an index! But I am keeping my big yap shut because documentation is a bitch and they have done a ton of it and I do not document &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;my&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; stuff so...I keep my big yap shut. But the point is that my work now yields results reliably and predictably and this will accelerate as I learn the framework and even learn better how to navigate the documentation.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;qooxdoo not only fits the bill of being a complete solution well documented with many examples but it also has high-quality code under the hood, which both gives me confidence that I have found the right tool and not incidentally serves as useful further documentation. More next time.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5609758665124194473?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5609758665124194473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5609758665124194473' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5609758665124194473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5609758665124194473'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/12/road-to-qooxdoo.html' title='The Road to qooxdoo'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-3854837146497331496</id><published>2008-12-07T12:38:00.001-05:00</published><updated>2008-12-07T12:41:35.167-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp packahes symbols interned uninterned case sensitivity noobs problems tutorials help'/><title type='text'>Why Lisp Packages are so Easy (Hard)</title><content type='html'>Slobodan Blazeski wrote:&lt;br /&gt;&gt; May somebody please explain me with simple words why cl packages are&lt;br /&gt;&gt; hard to use, 'couse I really don't get it?&lt;br /&gt;&gt; The best is probably to hear from somebody who just learned lisp or&lt;br /&gt;&gt; somebody who teaches lisp (do such people exist anymore?) and his/her&lt;br /&gt;&gt; students has problems with packages.&lt;br /&gt;&lt;br /&gt;...or a good teacher, defined as someone who remembers what it was like before they knew what they were teaching.&lt;br /&gt;&lt;br /&gt;The first problem is one of those immune system deals. Packages have a lot of the same proteins as, say, C dot aitch definition files so the recognition systems of programmers coming to Lisp from other languages (you know, everyone) does its damndest to parse them as dot aitches.&lt;br /&gt;&lt;br /&gt;In fact, packages have nothing to with anything but symbols, neither the functions nor global values they might name. More expansively: packages are about mapping string names to first class Lisp symbol objects and dividing this up into discrete mappings called packages so the same string "Hi, Mom!" can map to multiple |Hi, Mom!| symbols in multiple packages.&lt;br /&gt;&lt;br /&gt;The second problem is that symbols take us straight to black-belt Lisp in which one must understand the Lisp reader and fancy things like read-time and compile-time and all that. Example:&lt;br /&gt;&lt;br /&gt;I remember getting messed over because some symbol was mysteriously appearing the base CL-USER package. I could not for the life of me see where it was being introduced. I turned the problem over to a few trees worth of monkeys and one of them came up with this rule:&lt;br /&gt;&lt;br /&gt;"Never use a normal symbol like |Hi, Mom!| in a defpackage form coded in a source file with (in-package :cl-user) at the top which would likely be the default even without that."&lt;br /&gt;&lt;br /&gt;Instead, use a string like "Hi, Mom!" or an uninterned symbol like #:|Hi, Mom!|.&lt;br /&gt;&lt;br /&gt;Strings are dicey because you might want to export 'banana and be silly enough to code "banana". Lisp will take you seriously and create |banana| instead of BANANA, case sensitivity being what it is except when it is not when Lisp folds 'banana to 'BANANA which is what it does unless you are in Modern (case sensitive) mode.&lt;br /&gt;&lt;br /&gt;Did I mention "black-belt"? The fundamental idea is simple, but noobs get thrown off mostly by the non-simular simularity with C and then in the debugging stage by case sensitivity seeming to come and go at random and the whole read-time compile-time thang.&lt;br /&gt;&lt;br /&gt;hth, kxo&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-3854837146497331496?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/3854837146497331496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=3854837146497331496' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3854837146497331496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3854837146497331496'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/12/why-lisp-packages-are-so-easy-hard.html' title='Why Lisp Packages are so Easy (Hard)'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1037639102832500046</id><published>2008-12-07T11:17:00.004-05:00</published><updated>2010-03-31T09:26:16.832-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp ASDF tutorial guide beginner help build make system defintion'/><title type='text'>A Beginners Guide to ASDF (Ha!)</title><content type='html'>&lt;div class="moz-text-flowed" style="font-family: -moz-fixed; font-size: 13px;" lang="x-western"&gt;OK, there is at least one thing about which Lispers are not so smug: ASDF (Another System Definition Facility), the de factor standard for the Lisp library equivalent of Makefiles, and my post today was prompted by ANFOBA (Another Noob Effed Over By ASDF) washing ashore on comp.lang.lisp, and how I almost responded there:&lt;br /&gt;&lt;br /&gt;Francogrex wrote:&lt;br /&gt;&lt;blockquote type="cite"&gt;Hi, I am struggling to understand how to work with asdf.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I have been using it for ten years and I am about 50-50 now on getting  it to work. I am assured it does a great job in working with a multitude  of Lisps/OSes, and I can assure you it is a disaster at working with  programmers.&lt;br /&gt;&lt;br /&gt;Come back here and post console output freely, you will need help,  especially because one of its great triumphs is useless error messages.&lt;br /&gt;&lt;br /&gt;Hints:&lt;br /&gt;&lt;br /&gt;(1) It will work. You will have to promise it your first-born, but it  will work.&lt;br /&gt;&lt;br /&gt;(2) No, PB was not joking: you have to separately push locations onto  some magical special variable. Leave off a slash (or add a slash, I  forget) and ASDF will take your head off, so don't do that.&lt;br /&gt;&lt;br /&gt;(3) No, PB was not joking, the syntax is:&lt;br /&gt;&lt;br /&gt;    (asdf:operate 'asdf:load-op :cl-pdf)&lt;br /&gt;&lt;br /&gt;Why is it not (asdf:load-system :cl-pdf)? In my experience, extremely  smart programmers think it astoundingly brilliant when "one function  does everything!!!!", remembering the ridiculous op-code first parameter  left as an exercise.&lt;br /&gt;&lt;br /&gt;Since you asked, this is because extremely smart programmers are tone  deaf to programmer productivity; they are so smart they do not even notice when they have created something unuseable, they just brain through it.&lt;br /&gt;&lt;br /&gt;(4) ASDF has a featurebug: it loads in the wrong order in order to make  McCLIM work. Don't ask. If the author of the .ASD file retreated to the  desert for forty days to slave over the dependencies this will not be  a problem. Otherwise do what I do: take a sledgehammer to the beast:&lt;br /&gt;&lt;br /&gt;    (asdf:operate 'asdf:load-op :cl-pdf :force t)&lt;br /&gt;&lt;br /&gt;That abandons the whole point of having a build system, but it gets ASDF  to work. When for the love of god I am just trying to build this frickin  thing!!! that is a nice tradeoff of compile-time vs tracking down and short-sheeting the author of ASDF.&lt;br /&gt;&lt;br /&gt;(5) On success ASDF emits more messages than an IBM OS/360 core dump.  This is so any errors will scroll well out of view and anyway stand out  like a healthy thumb from the surrounding...um, other healthy thumbs.  Anyway, do what I do: ignore all messages other than a backtrace and Just Try the Hello World(tm).&lt;br /&gt;&lt;br /&gt;If you get a backtrace, Just Post It to c.l.lisp.&lt;br /&gt;&lt;br /&gt;(6) If hello world fails, f*ck! But at least now you are a Real Lisp  Programmer(tm), this is what we live with.&lt;br /&gt;&lt;br /&gt;hth, kenny&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1037639102832500046?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1037639102832500046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1037639102832500046' title='45 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1037639102832500046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1037639102832500046'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/12/beginners-guide-to-asdf-ha.html' title='A Beginners Guide to ASDF (Ha!)'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>45</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-18209943361666309</id><published>2008-11-18T21:08:00.005-05:00</published><updated>2008-11-19T05:57:17.359-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Finite state machine software engineering'/><title type='text'>The Foisting of An Infinite State Machine</title><content type='html'>"I will not allow you to foist this convoluted scheme on the bank!", Sam yelled.&lt;br /&gt;&lt;br /&gt;This was fun in a lot of ways. First of all come on this is a bank, three or four full floors of programmers all enthralled by nothing more technical than getting through the day unfired and back on the train home to their families and here is  this aging cardpunch nutjob throwback not only noticing Someone Else's Code but caring?!&lt;br /&gt;&lt;br /&gt;Second, I did not make that up. Sam actually used the word "foist" without trying. I use SAT words all the time but I am usually trying, you can see my eyebrows arch a little as my language organ reaches for the thesaurus. Nothing shabby about "convoluted", but "to foist"? And Sam tossed that off in earnest in anger in the heat of diatribe sans affectation and it is not clear to me I have ever before or since heard the word used in vitro. Which brings me to the third fun bit.&lt;br /&gt;&lt;br /&gt;Sam was Jewish. Classic Orthodox home-by-sundown-on-Friday Brooklyn Jewish and of course he would be good with words. Right, get all PC on me and denounce me but what can you say?, he used "foist" in a sentence on the fly and I think I win on this. So there he is with this classic Billy Crystal Princess Bride accent yelling at me for foisting convoluted code on the bank.&lt;br /&gt;&lt;br /&gt;"I will not allow this!" he cried. "I will stop you!"&lt;br /&gt;&lt;br /&gt;Oh, please, tho Sam was a sweetheart. Yeah, "was". I heard he passed, Lord keep him, a beautiful soul. I could have choked him in that moment but at least he was attacking me for Code Quality. What was my sin?&lt;br /&gt;&lt;br /&gt;I had been tossed a throw-away job of persuading two applications to exchange information reliably when either app was free to collapse in a heap at any time and I was not to lose any information. Nowadays we just pull packages off the shelf for that but this was a while ago. Oddly enough in my first IT job ever I had had to do the same and it was fun because there was nothing theoretical about it, the two applications did even during development reliably disappear left and right allllll the time. Decnet, PDP-11, RSTS/E, 1981... you understand.&lt;br /&gt;&lt;br /&gt;What was different was that somewhere in the intervening ten years I had gotten this crazy idea of creating a domain-specific language to make it easier to develop a &lt;a href="http://www.theoryyalgebra.com/"&gt;software Algebra tutor&lt;/a&gt; so I had gotten a book on compiler design because I did not realize I could Just Use Lisp. I do not like reading so I did not get very far but fortunately one of the earliest chapters was on parsing  so I ended up learning about finite state machines. Oh, sorry.&lt;br /&gt;&lt;br /&gt;This post came up because I am doing some Web2.0 programming these days from Lisp and I wanted to send over Lisp sexprs and since Javascript for some reason lacks a Lisp reader I was going to have to parse it myself and after  ten minutes of trying to do it without a finite state machine I realize, damn, I should code up a finite state machine.&lt;br /&gt;&lt;br /&gt;I will not in this space try to explain what is a finte state machine but it is really simple and powerful and no matter what level programmer you are you need to have it in your, well, toolbox. I think the example I learned on was a pocket calculater when folks still had those. Your initial state is "initial". Duh. Then what happens? Oh, I got "/". Bzzt! Or just ignore it and my next state is still "initial". Now I get a "1". Great! Save that, my new state is...I dunno..."got a digit". We're on a roll. But wait, what other inputs could I get? A "+". Ummm...well, it seems no different, but we'll say "got a plus sign", and indeed when we are done one of the cool things that can happen is that as we fill in the table we may well discover that the row for the state (did I mention that rows were for states and columns were for inputs? Sorry) ..the row for the state "got a plus sign" might be no different from the row "initial" and we first go "whoa, enlightenment" and then collapse the two rows into one. I digress.&lt;br /&gt;&lt;br /&gt;But the idea is that we just break it down into cases. A fun example is that we now know whether a "+" is addition or a plus sign (or an error) without really trying, because we have aggrssively exploded the analysis into all these different states like "just got a digit" or "just got a left parens" or...yeah, it goes on, but guess what? Here comes the name! "Finite State Machine"! There are only so many!!! You may think there are a kabillion but after ten you are done, maybe after twenty. And you can collapse inputs (1-9 become "positive digit") and so you have a finite number there. Do you now have 150 cases to handle? Yeah, and each one you can code in your sleep. The alternative is one hyperglutionous mass of conditionals, tests, and branches that will fail on the one millionth execution because of a first time path execution.&lt;br /&gt;&lt;br /&gt;Back to Sam.&lt;br /&gt;&lt;br /&gt;I have realized that the reliable exchange between two autonomous systems permitted to fail at any point will best be solved using my old friend the finite state machine and I have enthusiastically shared this with Sam. Somehow I am now being denounced for using an algorithm learned from the top book in compiler design. Specifically, I am being denounced for foisting. I will be stopped. The bank will be saved from my convoluted scheme.&lt;br /&gt;&lt;br /&gt;Ooooookayyyyyyy.&lt;br /&gt;&lt;br /&gt;Well, what can one anachronistic lost in the Torah yamaha wearing card punching goto coding nut job do? Would you believe he could force a code review? Nay, a &lt;span style="font-style: italic;"&gt;defense&lt;/span&gt;. Sam forced a frickin &lt;span style="font-style: italic;"&gt;defense&lt;/span&gt; of about thirty lines of the best simplest most powerful correct code that bank had ever seen. Mind you Sam is also the man who produced my favorite line of code ever, using the Vax Basic statement modifier mechanism:&lt;br /&gt;&lt;blockquote&gt;return if flag&lt;/blockquote&gt;That's right, an action at a distance code teleportation straight out of the middle of seventy line for loop using a flag he had named.... flag. You can imagine my &lt;a href="http://smuglispweeny.blogspot.com/2008/07/aa-bb-cc-and-dd.html"&gt;reaction&lt;/a&gt;. And this guy is challenging &lt;span style="font-style: italic;"&gt;my &lt;/span&gt;code?&lt;br /&gt;&lt;br /&gt;If you are not yet suitably horrified, understand that novice programmers were regularly crashing production runs because no one anywhere was looking at their code and they were going to call a meeting of like twelve programmers to review my foistation of convolution upon the bank? Sorry, my ire is showing. Chase cut to.&lt;br /&gt;&lt;br /&gt;Code review/defense: twenty minutes, here it is, any fucking questions?&lt;br /&gt;&lt;br /&gt;Yes that was pretty much the tone of my presentation -- I like to consider people skills one of my strengths. And then Sam spoke and you will see why I loved him. At pain of repetition, probably no one else on those four floors would have even listened to me as I bragged on my FSM, but go to the mattresses to stop what he thought was bad code? One in a million. And one in ten million in my experience would have said what he said.&lt;br /&gt;&lt;br /&gt;"OK," Sam he said. "That looks fine."&lt;br /&gt;&lt;br /&gt;Of course now I am pissed off because I am just getting my turbines spun up for a full bore antler to antler knock down drag out kickin and a gougin in the mud and the blood and the beer round fifteen thrilla in manila finish and Sam is saying...fine?&lt;br /&gt;&lt;br /&gt;"That is simple," Sam continued, gesturing towards my whiteboard diagram. "This infinite state machine idea is complicated, but the way it works is simple."&lt;br /&gt;&lt;br /&gt;The beauty of that being......no. I would only ruin it.&lt;br /&gt;&lt;br /&gt;RIP, Sam. RIP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-18209943361666309?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/18209943361666309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=18209943361666309' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/18209943361666309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/18209943361666309'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/11/foisting-of-infinite-state-machine.html' title='The Foisting of An Infinite State Machine'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-8359206713983307951</id><published>2008-09-09T14:17:00.006-04:00</published><updated>2008-09-09T15:14:10.064-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='baseball Larry Ritter book review'/><title type='text'>URBBR #2: How Bad Is This Book?</title><content type='html'>[The following has been... well, only the names have been changed to protect the endangered toads.]&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have a One-Paragraph Test for fiction. Not a complicated test, it involves reading the first paragraph and then deciding. If We are &lt;span class="Apple-style-span" style="font-style: italic;"&gt;really&lt;/span&gt; undecided We can read a second paragraph, but that is a Bad Sign.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For non-fiction We look at the blurbs the author managed to suck out of unwilling blurbers. Well, OK, We do not really want the blurbs to be from blurbers, We want them to be reviews and We know they have cherry-picked the review sentences so everything gets discounted about an order of magnitude. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And there are two such reductions applied, the second for the source of the review. Kirkus Review of Books... well, just quoting them gets a book back onto the shelf. In the wrong section, upside-down, binder in.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the Gold Standard for non-fiction back covers (hmm, the URL goes to the whole book, be clever and click "Back Cover"): &lt;a href="http://www.amazon.com/gp/reader/0688112730/ref=sib_dp_ptu#reader-link"&gt;The Glory of Their Times&lt;/a&gt;. Yes, you need to read this book, and no I do not give a rat's ass if you like baseball just read it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We turn now to a book I have been asked to review, which will go unmentioned for the same reason I restacked it binder-in:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  ;font-family:verdana;font-size:13px;"&gt;&lt;blockquote&gt;"This work strikes a balance between the pure functional aspects of Blub and the object-oriented and imperative features that make it so useful in practice, enable .NET integration, and make large-scale data processing possible."&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  ;font-family:Georgia;font-size:16px;"&gt;&lt;div&gt;The clever unwilling blurber always manages to say something nice by talking about something else, in this case the language .... instead of the book for 90% of the blurb. What does he say about the book? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It strikes a balance. Wow. How big a put-down is that? Note that the reviewer did not say "a perfect balance" or even "a good balance". And what the Hell does balance buy me anyway?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The good news is that We cannot discount that 90%, Our micrometer does not go that low. But We better check the author of the blurb.&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;—John Doe, PhD, Researcher, Blubber Ltd.&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Oh. The people selling Blub.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The neat thing is that We now know the book is awful and that John was slowest to hide under his desk when the marketing people came around looking for a recommendation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-8359206713983307951?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/8359206713983307951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=8359206713983307951' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8359206713983307951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8359206713983307951'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/09/urbbr-2-how-bad-is-this-book.html' title='URBBR #2: How Bad Is This Book?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-3023480239322239042</id><published>2008-09-09T06:19:00.006-04:00</published><updated>2008-09-09T07:24:59.866-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZenLisp Scheme Nils Holm McCarthy Hopper Knuth'/><title type='text'>Unread Book Review: Zen Style Programming, Nils Holm</title><content type='html'>&lt;div&gt;On comp.lang.lisp, Nils M Holm wrote:&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&gt; I am happy to announce that free pre-release copies of my latest book&lt;/div&gt;&lt;div&gt;&gt; &lt;/div&gt;&lt;div&gt;&gt;           "zen style programming"&lt;/div&gt;&lt;div&gt;&gt; &lt;/div&gt;&lt;div&gt;&gt; are now available.&lt;/div&gt;&lt;div&gt;&gt; &lt;/div&gt;&lt;div&gt;&gt; Blurb&lt;/div&gt;&lt;div&gt;&gt; &lt;/div&gt;&lt;div&gt;&gt; The primary purpose of programs is to be understood by fellow human &lt;/div&gt;&lt;div&gt;&gt; beings,&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nonsense! Nils has been reading &lt;a href="http://www-cs-staff.stanford.edu/~uno/lp.html"&gt;Knuth&lt;/a&gt; or something. The purpose of programs is to model other processes so the most important virtue of a language is the ease of building programs with it. Yes, those programs should tend to be clear but that just requires powerful constructs, long names, and support for the functional paradigm. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Besides, "revise"  means "rewrite from scratch anyway because the way this was done is all cocked up" so we do not generally have to understand programs to work on them.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&gt; hence programming languages should have certain properties:&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Bzzt!  The source of obfuscation is the programmer, not the programming language.&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&gt;     * Small size and uniformity&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;Hand-waving! Nils has been reading Graham or something. Small size as a requirement does not follow even if one were to exalt human readability to Prime Directiveness. You could just have good names for functions, like pathname-sans-file. And an editor that knows how to get to a hyperspec.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;     * Unambiguousness&lt;/div&gt;&lt;div&gt;     * A high degree of abstraction&lt;/div&gt;&lt;div&gt;     * Achitecture neutrality&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; The first part of this book introduces the concept of functional  programming and describes a purely symbolic language that fulfills these requirements. This language is a minimalisti variant of Scheme whose only data types are symbols and ordered pairs. Nothing else is required to describe algorithms for solving a variety of different problems.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second part of the book shows how to apply the techniques of  symbolic programming to some problems of varying complexity. Topics discussed in this part range from simple functions for sorting or permuting lists to ``lazy'' data structures, regular expression matching, formal language translation, and declarative programming.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The third part, finally, shows how to implement the abstraction layer that is necessary for solving problems in an abstract way on a concrete computer. It reproduces the complete and heavily annotated source code for an interpreter of symbolic LISP and provides an example of clear and readable C code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This book contains the full source code to a source-to-source compiler, a meta-circular interpreter, a logic programming system, and to the language that is used to implement all of these. &lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Damn, that was a lot of work. I should be nicer to Nils. Here's the &lt;a href="http://www.t3x.org/books/zen.html"&gt;book&lt;/a&gt;, anyway. Let us see what it says:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;"The first points are no-brainers."&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Come on, Nils, we talked about the hand-waving. &lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;"If a language is too complex..."&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Well, by the meaning of the word "too" I think you are on safe ground for the rest of that sentence, but it begs the question of how too is too? Nils needs to make his case or judge someone else's case, not both.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;"...programmers will have to look up things in the manual perpetually instead of concentrating on the actual problem."&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;So now we need programs to be understandable by people who do not know the programming language? I think that &lt;span class="Apple-style-span" style="font-style: italic;"&gt;was&lt;/span&gt; a design goal for COBOL. Anyway, that does not give you a language with a small instruction set, it gives you a language with long, well-chosen names. Like COBOL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As for looking things up, I want to meet the guy who looks up delete-duplicates when the status bar is saying:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    delete-duplicates sequence &amp;amp;key from-end test test-not start end key&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's see if there are any more self-serving rationalizations....&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;"The class of problems that can be solved by programs is much smaller. It typically involves very clearly defined tasks like&lt;/div&gt;&lt;div&gt;-- find permutations of a set;&lt;/div&gt;&lt;div&gt;-- find factors of an integer;&lt;/div&gt;&lt;div&gt;-- represent an infinite sequence;&lt;/div&gt;&lt;div&gt;-- translate formal language A to language B;&lt;/div&gt;&lt;div&gt;-- find a pattern in a sequence of characters;&lt;/div&gt;&lt;div&gt;-- solve a system of assertions.&lt;/div&gt;&lt;div&gt;Of course these tasks have to be defined"&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nils must be a professor of computer science. Programs exist to model real-world entities of arbitrary complexity, tho good luck with the human mind. OTOH, simulations of car crashes are admitted into evidence by finicky courts and some people even model human &lt;a href="http://www.theoryyalgebra.com/"&gt;private Algebra tutors.&lt;/a&gt; Unfortunately those things are a ton of work which is why you will not see academics doing that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now about the title. Zen zen zen, what an affectation! Zen this, zen that. I am going to write a book on The Zen of Ordering Take-Out Pizza.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What is zen about zenlisp? Never justified, never even addressed. Does the author think zen means small because it is a small word? I like that, actually. I tried googling for synonyms: &lt;a href="http://www.merriam-webster.com/thesaurus/Zen"&gt;oops&lt;/a&gt;. I think they would be pleased down at the monastery. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So much for the name. How about the language itself? Raison d'etre? &lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;Zenlisp is similar to Scheme, but simpler.&lt;/blockquote&gt;That sounds like being rescued from a desert island and then dropped off in the middle of the Sahara. No, the only reason ZenLisp exists is because Lisp is a venus flytrap of a blackhole delivered by John McCarthy an alien from outer space sent to stop good programmers from Actually Programming. Apparently Grace Hopper was just a few lines of code away from anti-gravity and time travel so They sent John down with Lisp so any good programmer would get so excited about the language itself they would stop programming time-travel applications, take out their CodeWarrior CDs, and start &lt;span class="Apple-style-span" style="font-style: italic; "&gt;implementing&lt;/span&gt; a Lisp using (wait for it) C.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The ones who &lt;span class="Apple-style-span" style="font-style: italic;"&gt;really&lt;/span&gt; want to avoid programming will then write a book about their language. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I wonder what Nils will do now.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-3023480239322239042?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/3023480239322239042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=3023480239322239042' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3023480239322239042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3023480239322239042'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/09/unread-book-review-zen-style.html' title='Unread Book Review: Zen Style Programming, Nils Holm'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5555583444410903746</id><published>2008-07-25T03:00:00.004-04:00</published><updated>2008-07-25T05:13:40.673-04:00</updated><title type='text'>AA, BB, CC, and DD</title><content type='html'>I am not making it up. Those were the datanames in the code I had inherited from the Wunderkind. So this will be the most boring stating the obvious war story I ever write but that is not why I am writing it. I am writing it because the Lisp subset of the human race is at it again running factual red lights with their prior conviction feet to the pedal.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yes, kiddies, we revisit today &lt;a href="http://smuglispweeny.blogspot.com/2008/02/maybe-i-was-too-hard-on-sohail.html"&gt;The Unbearable Impenetrability of the Lisper&lt;/a&gt;. The cool thing being that Arc is again involved albeit peripherally in this latest train wreck of human comprehension.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Back then the Maddening Crowd was utterly fascinated that I liked Arc which I did not but they were not to be denied, the best part being those people who responded to my objection to the crowd's misperception by saying yeah I saw you were flabbergasted by everyone thinking you liked Arc so tell me, you like Arc? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No I am not making that up. Twice. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This time it was my scrimshaw-ready datanames, sample below. Some months after my exploration of Arc I had a laugh as I whipped up a DSL for my &lt;a href="http://www.theoryyalgebra.com/"&gt;Algebra software&lt;/a&gt; and found myself approaching Arcitude in the brevity of my names.  I posted something to comp.lang.lisp inadvertently loosing The Hounds of Lisp Density. A sample:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;(hard&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;    (dsb (b x) (rp 2 (rv))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;      (m/ (m^ b (m* (r2 7) x))(m^ (xqv b) (xqv x))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;    (dsb (b x) (rp 2 (rv))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;      (m* (m^ b (ms* (r+ 7) x))(m^ (xqv b) (ms* (r+ 3) (xqv x)))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;    (dsb (b x) (rp 2 (rv))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;      (m*eo (ms^ b (r+ 7))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;        (m^ (xqv b) (ms* (r+ 3) (xqv x)))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;    (dsb (b x) (rp 2 (rv))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;      (m/eo (ms^ b (r+ 7))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;        (m^ (xqv b) (ms* (r+ 3) (xqv x)))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;    (dsb (n d) (rv 2)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;      (w (k (r+ 12))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;        (m/ (m^ k n) (m^ k d))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;dsb is short for the Lisp destructuring-bind.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;m/ is short for make-fraction.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;m*eo is short for make-product reordering the factors randomly (either-order)&lt;/li&gt;&lt;li&gt;etc etc&lt;/li&gt;&lt;/ul&gt;I gave a tip of the hat to Arc and explained that I had done this before (in C) and that this code (to generate randomly many varieties of Algebra problems) was a known PITA and even in C I had used the C preprocessor to likewise make the coding manageable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enter the Savages of Comp.lang.lisp.To a geek they lectured me on the importance of nice long meaningful names, or as His Sulzberbergerness edified me a ways back what Confucius called The Rectification of Names which is not quite the same thing but I can never resist name-dropping either Jay or Confucius. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I responded to the jackals nipping at my heels that yeah I know but in this case with vast incessant repetition of a small collection of opcodes that recognition would not be an issue and that it was much better to diminish the low information content (cue Shannon) of long names (what exactly does make-product add to m* in a context where a leading m is used only for makers?)  and learn a dozen opcodes which were mnemonically and predictably built anyway from atoms such as M and * and EO.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The universal response was that longer names were better. My universal response was that these special circumstances flipped the arrow on that otherwise sage rule.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The universal response was that longer names were better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Trying again, my universal response was that I agreed, but would anyone like to address the salience of the special circumstances I had suggested were germaine, perhaps explaining how they were not special enough or too special or the wrong damn color?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;They all responded that longer names were better and I really started to enjoy things at that point. I was reminded of this desert spider that had a routine for burying any captured wasp and it involved positoning the wasp up just so and then going to dig a hole and then dragging in the dead wasp and these researchers would move the wasp a little while the spider was digging so the spider would be thrown off and start again by repositioning the wasp and no matter how many times they moved the wasp while the spider was digging the spider would just start right over readjusting the wasp and then digging the hole. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The topper was I myself was a staunch proponent of good long names. Tilton's Law of Programming:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt; Spend more time on the names you choose than on the algorithm.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt; As for the specific quality of length, we have Tilton's Rule of Abbreviation:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;Abbreviate no name less than seven characters long and then only if a good abbreviation is no more than half as long. Rounding down.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Which brings us to AA, BB, CC, and DD. I was working as a body shop consultant in easily my most &lt;a href="http://www.hickorywind.org/000068.php"&gt;Tall Building&lt;/a&gt; job ever. One day this new guy came on board, totally not GQ, scrawny, smart, energetic. I had no idea he was a first round draft pick, destined for greatness. An employee, by the way. Tom. He dives in and starts churning out a front-end application, learning the HLL and OS and tools all at once, a man after my heart. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At one point he mentions to me a problem. He wants users to be able to make discontinuous menu jumps, say, go sideways without backing up to the menu above (yeah, this was the good old days of modal interfaces) and the programming language would not go sideways. ie, He was using HLL recursion to handle nested menus.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I suggested the obvious: no, you cannot call sideways in a structured language, you have to return from the called function with a "message" always checked by the caller to see if the user should be taken somewhere else. Tom yelled Great! and tore off to code it up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A couple of weeks later I have inherited the system. Tom was smarter than I: as soon as he had chalked up the win he told his boss to "get some consultant" to maintain it. Moi. So there I am working on the first RFE and I am perusing the code trying to figure out how the hell it works and I find myself slowed a bit by the data names that pretty much controlled everything: AA, BB, CC, and DD.  Come on, you think I could make up names that bad?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So over I wander to Tom's desk, clear my throat, Tom looks up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Tom," I said. "I was looking at the code. AA? BB? CC? DD?"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tom burst out laughing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Those are just temporary variables!" he protested, laughing even more.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Un-hunh," I replied. "And they control the entire program flow."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"Well, change them if you like."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I said, Tom was a smart cookie, he was wiping his hands of the whole deal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now it turns out that one of the things I like to do when working on OPC (Other People's Code) is to stare at it and stare at it and when I see some crucial variable playing a big part in things and its name is getting in my way I pick a better name and do a global change, rinse, repeat until the damn code makes sense. The only reason I had gone to talk to Tom was the same reason we pay to see a two-headed sheep at the carnival.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Two hours into the renaming I had come up with decent names for AA, BB, CC, and DD (that last  one turned out to be three different variables) and I was making the global changes eyeballing each as I stepped through the source and after one such change forgive me I will never in my life remember the specifics but imagine you have just made the substitution and are now looking at a line of code that says:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  total-weight = total-weight + this-length&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I did not feel completely comfortable with that edit so I called Tom over. Did I mention he was a smart guy? Two seconds into explaining how I had gotten to that point he yells out, "Great! I gave up on finding that bug!"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Smart guy. Tough bug? He just moved on and chalked up the win. Let some consultant take over the code and run into the bug and think they introduced it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But there you have it. A bug so hard to find that a very smart programmer &lt;span class="Apple-style-span" style="font-style: italic;"&gt;gave up on finding it&lt;/span&gt; and someone who did not even know the bug &lt;span class="Apple-style-span" style="font-style: italic;"&gt;existed&lt;/span&gt; changed a few datanames and the bug positively jumped off the page. Explaining the corollary to Tilton's Law: &lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;If the names are right the algorithm will write itself.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Now if only some walking fencepost from c.l.l will post a comment saying... well, that would ruin it, would it not?&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5555583444410903746?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5555583444410903746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5555583444410903746' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5555583444410903746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5555583444410903746'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/aa-bb-cc-and-dd.html' title='AA, BB, CC, and DD'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-2614478629150288518</id><published>2008-07-18T15:16:00.004-04:00</published><updated>2008-07-18T19:14:57.315-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Consing Mariano Rivera Lisp mastery'/><title type='text'>Now Batting, Dave. Why is Mariano Rivera not worried?</title><content type='html'>&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;The venerable Mr. Roberts draws on his profound mastery of things algorithmic as he intones:&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;&lt;span class="Apple-style-span"   style="color: rgb(51, 51, 51);   line-height: 18px; white-space: normal; font-family:'Trebuchet MS';font-size:13px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;&lt;span class="Apple-style-span"   style="color: rgb(51, 51, 51);   line-height: 18px; white-space: normal; font-family:'Trebuchet MS';font-size:13px;"&gt;I'm actually quite conscious of cons-ing, but I also believe that obsessing about cons-ing leads to premature optimization and far greater numbers of bugs. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;We are fortunate to have the benefit of his wisdom and it occurs to me that we can keep talking past each other enjoyably for weeks like this so i will not suggest we try to establish a concrete example where he would code append and I would code nconc and ruin all the fun. But it &lt;span class="Apple-style-span" style="font-style: italic;"&gt;is&lt;/span&gt; a good question especially if we agree (we do) that as a rule the functional paradigm utterly Rocks the Casbah so how on earth am I going to get a list back from some function I call and not be free to nconc it? The moral being I am right (will it never end?): if we try to find a point of Actual Disagreement(tm) we will fail so let us not.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;Getting back to the fun abstract theoretical conflict, the problem is a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;policy&lt;/span&gt; of copying which leads straight to the solar power objection aka death by a thousand cuts which in turn leads us back to the simple question of why we do not just code the right operator at every turn? Genius is in the details which means we are &lt;span class="Apple-style-span" style="font-style: italic;"&gt;always&lt;/span&gt; on our game bringing me to Mariano Rivera.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;For those who do not know Mariano plays baseball and is starting to be called the best ever at his position, namely "closer" which means we won the first eight innings and do not want to lose the game please do the rest and he does. Even in the seventh game of the World Series that he lost every hitter broke their bat but the three balls involved known in the game rather morbidly as "dying quails" found their way to the grass. Hard to feel bad about shattering three bats. I digress, Mo is good.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;Genius. Details. The great Nconc vs Append War, Roberts-Tilton III, nothing like this since Ali-Frazier, Affirmed and Alydar.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;It was Just Another Game. The Yanks had won, Mo had saved. They always collar some poor sod and keep him from his shower and car service home to make those of us who pay to watch baseball on cable TV feel better and tonight poor Mariano's number (42!) came up and by the grace of God I pulled my face out of a carton of cold noodles with seame sauce just in time to witness a perfect moment in sports broadcasting and as well a master class in excellence any time any where.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;The announcer on the field for the interview went for a home run question, something way more astute than the usual "How did it feel getting the big out?" and he came up with a beaut: &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;"Billy Bob is a rookie and you have never faced him before, there must not be much of a book on him," the announcer observed. "Was it tougher facing an unknown quantity?". &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;"No," Mariano replied. "I went out during batting practice to watch him hit."&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap; font-family:'Lucida Grande';font-size:11px;"&gt;Mariano's disclosure that as a Hall of Fame shoe-in and multi-millionaire perennial All-Star participant he had looked down at the lineup and seen an unfamiliar name and broken off his clubhouse routine to go watch some ridiculous kid take batting practice had no small effect on our seasoned, professional, expert baseball announcer:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;"You did that?!!!!!!". He blurted out, hopping a little in the air, lurching towards Mariano. "You went out to watch him take batting practice?!!"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;Now it was Mariano's turn to be amazed, leaning back a little to create a margin of safety. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;"Of course," he replied. "I get paid a lot of money."&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;Doodleoodleoodleoodleoodleoooo.  Game over. The announcer (and I, I confess) had been seriously schooled. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;We sit at home and watch these athletes precisely because what they do is so wonderful to us and we endow them in our minds with magical and wonderful qualities because at an early age we were robbed of angels and dragons and Santa Claus and even monsters in the closet and trolls beneath the bridge and then every once in a while we learn that the miracle strikeout we saw with the bases loaded happened because a multi-millionaire punched the time clock, checked his glove for broken laces, sharpened his spikes, and checked the opposing team's roster for any names he did not know.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;I say learn the damn language.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  white-space: pre-wrap;font-family:'Lucida Grande';font-size:11px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-2614478629150288518?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/2614478629150288518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=2614478629150288518' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2614478629150288518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2614478629150288518'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/now-batting-dave-roberts-why-is-mariano.html' title='Now Batting, Dave. Why is Mariano Rivera not worried?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1876652932622299754</id><published>2008-07-18T02:55:00.004-04:00</published><updated>2008-07-18T03:41:26.392-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp consing solar power torpedos molasses tuning'/><title type='text'>Fear No Evil II, or Why Solar Power Sucks</title><content type='html'>Just a quick note cuz I remembered something that answers Dave's well-reasoned comment:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color: rgb(51, 51, 51);  line-height: 18px;  font-family:'Trebuchet MS';"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;My own personal rule on this is to use functional programming whenever possible and let the GC deal with it. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not much of an excerpt, but it says it all: modern Lisp GCs truly Rock the Casbah, and I myself am on record as denouncing the flipside of this blogcoin, consophobia. Actually, there may be a problem, Dave says "whenever" possible and perhaps then we agree! &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But "whenever possible" has a ring to it like "oh, you know, all the time" and I actually had a good reason for not doing &lt;span class="Apple-style-span" style="font-style: italic;"&gt;that&lt;/span&gt;, I just forgot it. Has to do with solar power. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The reason solar power sucks even though there is an overwhelming amount of it is that it is diffuse. Yes, enough sunlight falls on Kansas in a month (I am making this up) to power Earth for a year, but just try to find a solar panel as big as Kansas, never mind deal with the Kansans or the inefficiency of the transmission to Australia. I digress.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem with a "Damn the consing! Full molasses ahead!" policy is that when ones application drags to a halt there will not be a bottleneck to fix. There will just be hundreds of places one was too lazy to think about whether one could use the right construct. And correcting them all will be as painful, tedious, dreary, mind-numbing (sound like fun yet?) and thus as bug prone as it would be easy and fun whenever reaching for a list manipulation tool to challenge oneself with, gee, can I cut in the afterburner? Stand back, GC! Captain Destructo is in da house!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is a practical objection. My ethical objection (viz, hey, learn the language) is not all that far behind: jeez, I am building this list right here in front of my eyes, why am I not using a destructive operation for the next step? Do these same folks all have a copy-n-sort function in their personal toolkits that begins with a copy-list on the sequence to be sorted? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No, they do not. Why not? Hello.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My apps periodically get bogged down. I wait until they do and then dive in for what I like to call Speed Week after a regular TV extravaganza on vehicular racing. Normally this turns up interesting algorithmic gaffes I do not feel too bad about but one time the smoking gun was the most innocuous little needlessly copying statement you can imagine write at the center of the heaviest hitter bit of code you can imagine. This is pretty much the opposite of the solar power argument -- there &lt;span class="Apple-style-span" style="font-style: italic;"&gt;was&lt;/span&gt; just one little guy to track down -- but without the code profiler offered by AllegroC I am not sure how long it would have taken to find that. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And now I come back to the main point: er, exactly how hard is it to know when one can use destructive list operations?  So why not use them? Only one excuse comes to mind (fear) but always copying is not even a clear win (ie, it can totally suck at times) so.... learn the language?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If I was going to cut the Copying Cowards some slack I would say, shucks, not everybody writes insanely intense tight loops. But then I remember a point I made in FNO/1: we get noobs all the time struggling with slow code because of excess copying. Perhaps complex applications and tight loops are orthogonal?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I say learn the damn language.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1876652932622299754?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1876652932622299754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1876652932622299754' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1876652932622299754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1876652932622299754'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/fear-no-evil-ii-or-why-solar-power.html' title='Fear No Evil II, or Why Solar Power Sucks'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-3712749671353841083</id><published>2008-07-14T02:25:00.005-04:00</published><updated>2008-07-14T03:56:15.645-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chomsky Pinker skateboards drinking'/><title type='text'>Chomsky! Pinker! Get In Here!</title><content type='html'>[OK, OK, it is a Lisp blog but if I can refute Chomsky's entire body of work on language acquisition in one post, why not?]&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These academic PhD geniuses have a problem. They are geniuses. They think they can figure everything out by thinking, like Feynman fixing the neighbor's radio at the age of three or something close to that by thinking. Great story, buy the book. Forget which.&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Chomsky and Pinker merely repeat the error of the AI crowd who sniffed at NI (I just made that up, it means "natural intelligence") and said, "NI?! NI?! We don't need no stinkin NI!". They said that because they were geniuses they knew that what NI did with pretty much organic chemistry they could stomp with (drum roll, please) &lt;i&gt;reason&lt;/i&gt;.  Ooooohhhh, excuuuuse me!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess I can leave Pinker out of this, he did not add anything to Chomsky, he got drugged in only because a correspondent mentioned his "work" on blank slates. I love that "work": Oh, let me lean back and draw on my pipe and I have a PhD so if I think babies learn something too fast they learn them too fast, dammit! As if. And believe it or not I am coming to my point. But first a science trick, a prelude to my witnessing of the refutation of Chomsky. It has no bearing on anything else but it involves a cute girl and something I could not believe when I saw.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There I am in a sports bar/shore bar celebrating a great week almost delivering my world-changing &lt;a href="http://www.theoryyalgebra.com/"&gt;Algebra software&lt;/a&gt; when I see a lovely lass drop her drink. Three or four feet, to the floor. It was a plastic cup, which helped a lot come to think of it, because a glass glass being more rigid would not have absorbed the energy and there would have been a wicked rebound preventing what happened from happening: the drink landed upside down and just stood there, trapping half the drink inside. The bad news being there was no elegant way of finishing said drink, but that is not my point. Did I have a point?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, if I had to have a point, it would be that no one else was all that impressed. Clearly I need to spend more time in bars late at night watching drinks being dropped and I do not think it is possible to spend more time in bars late at night than do I so I guess I need to find bars with clumsier people, good luck on that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oh, and the other useless and irrelevant to the demolition of Chomsky/Pinker thing I learned is that it takes just &lt;i&gt;one&lt;/i&gt; unauthorized speech on world affairs (well, he was mumbling pretty badly, I am not sure it was on world affairs) over the unattended band microphone to get escorted unceremoniously out the front door at the sports bar in question. Right, Chomsky.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I look up and I see a skateboard competition, lucky enough to be watching the winner's winning run, and lucky enough for my brain to clear long enough to understand what I am seeing, a Johnsonian kicking of the rock I refute you thus Dr Berkeley of Chomsky/Pinker by some sixteen year-old if that. What did he do, and why did my brain have to clear? Two good questions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What he did was give himself a push across a flat floor in a reasonably small room (no gigantic ramps and concomitant acceleration/stored momentum) and upon reaching a ramp at the same time push off in such a way that the skateboard (unattached to his feet for those who do not know) elevated with him to a height just above a rail (er, just an elevated horizontal pipe mebbe a foot off the floor) such that he could land on the skateboard in midair just as the tip of the skateboard landed on the rail and using his/their forward momentum proceed to slide along the rail for a couple of yards before again levitating off to land somewhere else to commence another trick. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And before the anti-blank-slate morons can scream "Oh that is easy, I have the algorithm right here" allow me to break their hearts and add that as he did the initial elevation springing the board into the air with him (a yawner in these competitons) he took the trouble to pop his deck into a barrel roll (or two, who knows at that speed?) before regaining it to land the rail toe-slide. If the MIT geniuses think that is easy lemme just say that I have spent &lt;span class="Apple-style-span" style="font-style: italic;"&gt;years&lt;/span&gt; in Central Park watching the same people practice on skateboards for &lt;span class="Apple-style-span" style="font-style: italic;"&gt;years&lt;/span&gt; and they still cannot jump over a small backback and land on the skateboard on the other side.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So... these people have skateboard organs? Or do you think learning to barrel-roll a jump into a rail toe-slide is more important to them than is mastering language to an infant so their motivation is stronger? This would be a reasonable belief if one has never been in the presence of an infant who will join in any conversation it hears when it neither understands nor can generate one intelligible syllable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oh, and why did my brain have to clear? Because what I saw was a commonplace: inconceivable performance easily explained by sufficient practice. If a recent blog had not been on my mind I would not have given the skateboard performance a second thought, nor the motorcycle-flipping organ &lt;sigh&gt; manifested in the next story on ESPN.&lt;/sigh&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Come to think of it, this &lt;span class="Apple-style-span" style="font-style: italic;"&gt;is&lt;/span&gt; about why Lisp wins: we simply are not as smart as we think we are. I like to say that I cannot write good code but I do know when I have written crappy code. Recognizing is easier than generating. Hell, crappy is just one bit, right? But how do we produce a huge stream of uncrappy bits? Good luck.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What we want then is an agile language that lets us create awful code really fast and fix it as fast as we identify the problems. Pretty soon our software organs &lt;sigh&gt; cut in and we are creating not-so-awful code up front. Even better.&lt;/sigh&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I just have to figure out an elegant way to finish a drink upside down on a barroom floor.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-3712749671353841083?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/3712749671353841083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=3712749671353841083' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3712749671353841083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/3712749671353841083'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/chomsky-pinker-get-in-here.html' title='Chomsky! Pinker! Get In Here!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1523095351455178553</id><published>2008-07-09T02:39:00.003-04:00</published><updated>2008-07-09T03:19:19.593-04:00</updated><title type='text'>Buzz off, Charlotte</title><content type='html'>Omigod. I just made up that title because of the subject of this post and not five minutes ago I ended up daydreaming about a girlfriend I had back in college named Charlotte and as you will see there is no connection. Scary.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, it is 2:38 am and I am in the middle of a trivial but unwelcome re-de-refactoring with a scant few days to go before a self-imposed but jeez I gotta get this frickin thing out the door it is the middle of July deadline and it is an &lt;a href="http://www.theoryyalgebra.com/"&gt;educational app&lt;/a&gt; &lt;span class="Apple-style-span"  style="  white-space: pre; font-family:'Lucida Grande';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span"  style="  white-space: normal; font-family:Georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;and how far is it from the middle of July to frickin September?!!!!!!! I digress. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is 2:38 am and a spider I swear to god no more than 2mm across is dangling in front of my flat planel trying to figure out this code (the last bit of the last line, to be precise):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;(defun alert (s oks)&lt;/div&gt;&lt;div&gt;      (tk-format-now (conc$ "tk_dialog .oops {&lt;cough&gt;} {"&lt;/cough&gt;&lt;/div&gt;&lt;div&gt;                   (format nil "I thought you were solving for \"~c\"? I do not see it."&lt;/div&gt;&lt;div&gt;                            (key-char sfvar))&lt;/div&gt;&lt;div&gt;                   (format nil "} {} {~s} {~s}" oks oks))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Charlotte (look it up furriners, E B White) is freaking out over the double occurrence of the variable OKS. I know because the little hussy has lowered herself I swear to God ten feet from the A-frame ceiling of my ranch rental all the way down to within a foot of my desktop and stopped. How still is the air in here? She was swaying no more than another 2mm.  I digress. But how does a 2mm spider pack ten feet of gossamer into its, well, gossamer pack?! I don't care how thin it is, it is stll ten feet!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Charlotte was both deeply concerned and a sufferer of tunnel vision. She ascended to the top of the flat panel (I have it angled down to my slouched position a few inches above desktop), gained a foothold or five, and then inched...no, mmed over and redescended to get a better look at the first occurrence of OKS, just to be sure. It is possible she then pirouetted on her thread to ask why I did not check the CLHS on FORMAT to find out how to back up one argument and re-use it, but I cannot be sure. If my eyes were better, I could tell you. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, I am in a hurry dammit and you know what I think I have the strength to type oks a second time and no I do not think the redundancy will lead to the loss of a satellite but if a damn spider complains I know enough to listen... ah, there it is ~:*, back up one arg.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now buzz off, Ch... hey, where'd she go?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1523095351455178553?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1523095351455178553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1523095351455178553' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1523095351455178553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1523095351455178553'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/buzz-off-charlotte.html' title='Buzz off, Charlotte'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5640318785057335551</id><published>2008-07-03T02:07:00.004-04:00</published><updated>2008-07-03T03:38:52.715-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nike Spike Lee Michael Jordam shoes Lisp'/><title type='text'>It's the shoes, Jeff! It's the shoes!</title><content type='html'>My buddy Jeff wondered aloud on comp.lang.lisp why We Lisp Gods were so much better than the rest of you at adapting to alien environments, aka other languages. Without coming down in favor of any, he offered several possible explanations:&lt;div&gt;&lt;ol&gt;&lt;li&gt;We are just smarter than you un-Lisping dopes&lt;br /&gt;&lt;/li&gt;&lt;li&gt;We are accustomed to learning other languages because the food is OK in soup kitchens but the decor? Omigod!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;We are older and you can't teach an old dog new... hang on.&lt;/li&gt;&lt;/ol&gt;Based on recent copious experience, you can safely forget #1. Lispers are precisely as dense as other programmers, and if anything more so: as the title suggests, we are being carried by the shoes. Anyone both smart &lt;span class="Apple-style-span" style="font-style: italic;"&gt;and&lt;/span&gt; using Lisp is named Graham or Morris and either has or split over forty big ones, and no, a thousand smackolas is not "big".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#2 is a fine answer but is boring and knocks the legs out the upcoming argument so let us declare it false. That was easy&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#3 is part #2 and part what I joked: old may be wise but it sure ain't adaptable, it already knows The Right Way, it aint listenin.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That leaves the title of this entry, a reference to one (or more?) humorous Spike Lee ads for Nike sneakers in which he insists the sneakers explain Michael Jordan's Unbearable Lightness, to which we see his Airness reacting with feet-on-ground dubiosity. IIRC, but I think I do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But in this case, I think for once Chomsky might find a home. Chomsky decided that because he Chomsky could not understand how infants picked up language that there must be a magical device at play, a language organ in the brain dedicated to language acquisiton just as the spleen is dedicated to damn I wish I had not slept through biology.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Chomsky had a tiny little problem with his nonsense in that when one looks at human languages -- any of which can be picked up by any infant raised in its midst, whatever that infant's genetic tree -- well, the structural variation is infinite. I remember one universality they found: adjectives tend to appear very close to the nouns modified. Well, shazaam!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the Chomsker has a problem: this super-duper language organ has to be hardwired not to learn any particular syntax, it has to be hardwired to learn every syntax. Ok, that makes no sense, shall we try again?........... um............. er....................... I got it! It is hard wired to learn an abstract syntax! If only we could find one!!! Chomsky failed except for that bit about modifiers miraculously always appearing close in sentences to the thing being modified.  Yeah, how come no language ever came up with "The little giant slowly balloon over drifted the mansion red white."? Because the language organ rejected all those! &lt;sigh&gt; Where was I?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ah, flexible language acquisition, computer or otherwise. No, it is not the brain, it is the shoes. Basketball no, programming yes. No, Michael did not reach new heights because his sneakers opened new doors for him, but yes: expose someone to Lisp and (as many before me have observed) they become a better programmer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Chomsky saw the infinite variability of actual syntaxes as a severe objection to his hypothesis, and he was right to do so. Indeed, look at it from the other direction and we see the light: forget infants' ease of language acquisition, look at the difference between those who know one language and those who know five. Something happens after one has learned a bunch of languages -- acquisition of the next becomes a snap. No, I do not have that backwards. There is a small effect of "hey, anyone who has learned five just digs languages and does because they are easy for them", but I learn natural languages insanely easy and get a huge kick out of stumbling thru a conversation in French or Mandarin and learning a new language is &lt;span class="Apple-style-span" style="font-style: italic;"&gt;still&lt;/span&gt; hard for me because circumstances never led me to learn more than what I needed to get out of high school. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No, what is going on is the same as any learning process: the more we do the more the brain wires up metaskill at that activity. Babies are not born with a language organ, they just happen to have nice blank slates and speech is to them obviously something utterly compelling to master, it seems to control these big creatures moving about before them. Nothing like insane motivation for apt learning, eh Dr. Chomsky? But later on in life when a second language is an amusement? Acquisition is brutal. Where's the language organ now? Withered? Why does it come back after I have learned four the hard way? Ooops.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Was I supposed to be answering Jeff's question? My bad. Chomsky was wrong, McCarthy was right: a language in which code can be data and verse visa is one in which the programmer is stripped of structure and stricture and as Sartre warned us is not free to be not free. In mastering any art true freedom comes only within the constraints of the form, but Lisp offers us no such handholding. Some brilliant wag once observed that Lisp gives us a million ways to do anything but (1- million) of them are wrong -- a working Lisper like one who has learned the hard way five natural languages learns a metalanguage of programming that would delight and disappoint Chomsky, because the learned metalanguage is just one more demonstration of the brain's ability to find patterns in whatever it is immersed in long enough. ie, Organ, schmorgan, neural nets simply rock.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lispers are not smarter, they just fell into a pool and learned to swim -- ah, good analogy, nothing to hold them up, had to make do in a medium that would not support them, they had to add energy to the system to stay afloat, something like that. Lisp not only supports every paradigm, worse, it even allows any paradigm you can invent one as I thought I did with Cells until I looked up the prior art, but that does not change the fact that while working on a little GUI geometry problem a new paradigm jumped into my code... deal with this kind of language and... well, imagine sneakers that really did have wings. Wear those for a year and then climb back into ordinary sneakers...I'll give you a minute to think. What happens?&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;.&lt;/div&gt;&lt;div&gt;Disappointment? Some. Depression? No. End of flying? Never. You have tasted flight, you know what is possible, and you want to be there again. Now the analogy breaks down, because guess what? Lisp is just another language. When you do not have it, you can Greenspun it. When subjected to a toad of a language you grouse for fun but you also have code to write and you shrug off the downgrade and fly with the sneakers you have. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my first programming job I astounded the team so badly they kinda fired me, gave me only the maximum raise and blew me off when I asked for more because in nine months I had finished every system they had in development. At my going away they said they did not go out on a limb for me to exceed the maximum because they knew I would be leaving anyway. They did not know how much I loved the company bowling league or softball beer league. What was my secret in this Cobol shop? I had been programming in Basic on an Apple II. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One day I came upon a senior guy (OK,they were all senior, I had been there three months at the time) staring at my code as he tried cloning it to his assigned, well, clone. Concerned, I paused and asked if there was a problem. He waved me away, saying, No, I just have never seen Cobol like this. I understood. I knew even as I did it that I had been programming Cobol in Basic. I think I have that backwards. I remember asking them -- I was just learning Cobol at the time -- if a subscripted variable could be a subscript and I remember a very nice twenty-year Cobol veteran asking me very gently if I might not be making things a little too complicated. Nah, just trying to do Basic in these Cobol sneakers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lisp then is a substitute in itself for learning five natural languages, because it itself is not Chomsky's language organ, it is the universal syntax Chomsky had to identify for his imagined language organ to have been hardwired to learn. Lisp is the programming language embodiment of Sartre's curse: we are not free to be not free. Program this language and one will first use the wrong language feature at the wrong time (hang out on comp.lang.lisp to witness the hijinx of Lisp noobs trying to do things "The Lisp Way") and eventually get to the point where one can look at problems and see the paradigms they bring with them aided always by your language which is being utterly useless at telling you what paradigm to use, it could care less. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ie, It's the shoes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5640318785057335551?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5640318785057335551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5640318785057335551' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5640318785057335551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5640318785057335551'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/07/its-shoes-jeff-its-shoes.html' title='It&apos;s the shoes, Jeff! It&apos;s the shoes!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-5714570011002078729</id><published>2008-05-30T16:52:00.005-04:00</published><updated>2008-05-30T18:47:57.608-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='30day'/><title type='text'>30Day Death March: If They Can't Take a Joke, F**k 'Em</title><content type='html'>The title? Part one is &lt;a href="http://kalzumeus.com/2008/05/25/more-talking-and-more-doing/"&gt;someone's idea&lt;/a&gt; on how to distract programmers from working so as to make it even less likely we will get anything done in thirty days but at least we'll have company. Part two is how we pull it off and is what we used to say about the customer on my summer job in the automobile brake repair shop when we felt our work was a little sketchy. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I poked around on the feed and can confirm what someone said: I totally killed myself over the years by thinking certain edge features were indispensible. In my head an imagined reviewer was  going batsh*t over something that could be better, like a Consumer's Report automobile editor knocking off two stars from a sport sedan review because their test football linebackers found access to the rear seat problematic. Did you notice it was a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sports sedan?!&lt;/span&gt; The linebackers can take the frickin &lt;span class="Apple-style-span" style="font-style: italic;"&gt;bus&lt;/span&gt;, OK?!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even knowing this I did it again this time around (this is version two of something I did in the last century) and I blame Lisp because it made it so damn easy. At first. I failed to notice quickly enough the ensuing death by a thousand cuts for which I thus had signed up. That sentence reminds me of diagramming sentences in the ninth grade when I should have known I would be a social failure when the English teacher and I were doing high fives over the corner cases while the other kids in the class were silently writing me off as... I digress, just watch out for Lisp, it is a two-edged sword.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The crazy thing is that I also know damn well and will tell anyone who asks that this is one of those 80-20 or 90-10 deals, pick yer own damn ratio, OK?: almost all of the value is in the first feature. [kick kick kick] &lt;kick-kick-kick&gt; That was for me, not you. Who are you, anyway?&lt;/kick-kick-kick&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One caveat: sitting in my cubicle above cloud level one day on one of five floors dedicated to IT drones I was stunned to overhear an intelligent abstract discussion of technology. Someone had a theory. I &lt;span class="Apple-style-span" style="font-style: italic;"&gt;love&lt;/span&gt; a good theory. This one said, Don't ship too soon. The point was and my experience had already confirmed that shipping costs. Period. Suddenly one is working on all sorts of crap that does not move the product forward. Once one ships being live costs. This microISV stuff is about one-person operations so guess who is dealing with the cost/burden of being live? And guess another thing: how completely ineradicable are first impressions? Can I write a survey question guaranteed to elicit unbiased responder input or not?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oops, what am I? The Anti-30day-Christ? OK, let me finish on a positive note. True story.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"These drawings are wonderful," marvelled aloud the pre-school parent to the children's teacher. "You have a great gift for art instruction."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"No," the teacher demurred. "I just know when to take their drawings away from them."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We few, we happy few Actually Writing Applications have as our mission should we choose to accept to take from ourselves our own applications. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-5714570011002078729?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/5714570011002078729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=5714570011002078729' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5714570011002078729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/5714570011002078729'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/05/30day-death-march-if-they-cant-take.html' title='30Day Death March: If They Can&apos;t Take a Joke, F**k &apos;Em'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-4553396327363092058</id><published>2008-03-22T17:45:00.006-04:00</published><updated>2008-03-24T22:19:41.095-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming design Taoism'/><title type='text'>"We Can Live With the Way You Handled That"</title><content type='html'>Tilton's Lemma had come under attack and the title of this entry was the happy result. You forgot Tilton's Lemma? Here ya go:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Refinements to requirements cannot vary fundamentally from the original.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;The point is that careful design is worth the effort so that software can be successfully rolled out even though users naturally produce RFE after RFE during user acceptance testing. No matter what they come up with the software will adapt to it with a minimum of refurbishing.&lt;br /&gt;&lt;br /&gt;So what was the attack? We must begin with the launch meeting of the relevant project, where my conduct was such I rarely again got asked to meetings, but as a tease I will share that this was one of the most profound God is speaking to you experiences I have had in software development, one of those moments where one senses forces unknown at play.&lt;br /&gt;&lt;br /&gt;I was being given a nice new standalone task perfect for a cowboy contractor such as myself who was good with code but not with teams. My manager Frank would be perfect for such a loose cannon, one who cared not about how loud I snored when I catnapped or at what hour I showed up or how badly my lunch reeked as I ate it over the keyboard but only if the code worked so he could sleep at night.&lt;br /&gt;&lt;br /&gt;Just one problem. I walk into the launch meeting and sit down having no idea what is happening. After thirty minutes of sitting quietly at one corner of the table having nothing to do with any of the discussion I have deduced that a foreign branch of the bank has accounting software that will be shut down and covered by the software at our central location and that I will be writing the interface to take the feed from an off-the-shelf humongoid accounting package and feed it into the central system in such a way that it replicates their existing system.&lt;br /&gt;&lt;br /&gt;I have grown increasingly intrigued at this prospect as the meeting drags on because our group has more than a few people assigned to supporting the massive off-the-shelf system (shall we call it Isis?) and it seemed worthy of months of apprenticeship. On top of that I certainly had no knowledge of the foreign branch's system. Best of all I knew less than nothing about accounting. Okay, no, best of all was that no one was talking to me at the meeting so I developed this crazy idea that they were just going to turn to me at the end and say, Need anything else, Ken?&lt;br /&gt;&lt;br /&gt;Then Tony the Senior AVP turned to me.&lt;br /&gt;&lt;br /&gt;"Need anything else, Ken?"&lt;br /&gt;&lt;br /&gt;Left to my own devices for the first 99% of the meeting I had had time not only to deduce its ending but also prepare an answer. My fans from comp.lang.lisp can tell you His Kennyness likes nothing better than a good analogy and it had occurred to Himself that the developing situation resonated strongly with an image that formed spontaneously in his mind of a couple with a dog on a leash standing on some corner in the middle of Manhattan deciding how best to get to the Botanical Gardens in Brooklyn and after considerable discussion and perhaps even a consultation with maps street, bus, and subway settling on a means and path of transveyance and turning to the dog and saying, "Lead on, Fido!"&lt;br /&gt;&lt;br /&gt;Hence my prepared answer, before not one but two AVPs and the users on conference call from Canada:&lt;br /&gt;&lt;br /&gt;"Woof! Woof!", I offered, and looking back I regret only not having thought to wiggle my ass in my chair to signify enthusiastic tail wagging.&lt;br /&gt;&lt;br /&gt;When it became clear that the import of my barking had eluded those present and had at least stunned Canada into silence I expanded on it by observing that I knew neither the sending application nor the application I was meant to replicate nor the entire subject of accounting and concluded by wondering aloud if the guy outside tending the falafel cart might not be a better fit since he at least knew how to make change.&lt;br /&gt;&lt;br /&gt;The Canadians had heretofore been utterly thrilled at the idea of having their accounting taken over by our central gang that could not shoot straight (I'll wait while those of you who missed the irony go back for a look) and now they had White Fang as the contractor assigned to the task, confirming their worst nightmares.&lt;br /&gt;&lt;br /&gt;They agreed to provide a thorough specification and the AVP and I ever after when meeting in the hallway would bark at each other in greeting and at his going away dinner -- well, after the second round of shots it was pretty much non-stop howling, thank god for private rooms, we should have had one. I digress.&lt;br /&gt;&lt;br /&gt;Remember: this is about users not being able to change requirements discontinuously. So now we know how I ended up with the most beautiful requirements from which I have ever worked. Requirements? Bah, this was pseudo code. Just brilliant. They identified a dozen kind of transactions/situations/circumstances I could expect from Isis and they specified exactly how each should be handled.&lt;br /&gt;&lt;br /&gt;And this "exactly" was not just exact. There was this tremendous regularity in how they specified the handing of each case. Each was expressed cleanly as so many debit this, credit that, debit this subtransactions. These subtransactions just begged to be viewed as microcode for the larger instructions specifying how each case was to be handled.&lt;br /&gt;&lt;br /&gt;So that is the code I wrote, after effusively praising Team Canada to themselves and anyone else I could find. The high-level code read Isis transactions, identified the high-level case, and invoked its handler, each handler dispatching one or more microcode subtask handlers. We are talking easy work and soon we sail into user acceptance done thoroughly for a couple of months because I mentioned they did not trust us. I also know it was a long time because by the time the call came through with the title of this entry I had forgotten about the entire issue to which they referred, which was this:&lt;br /&gt;&lt;br /&gt;After a week my bugs had been rooted out and IRs were being handled by letting them know how they had screwed up the test. Frank was happy, I was snoring, life was good, we had time to buzz about this new write once run anywhere language called Java that would let browsers run applets.&lt;br /&gt;&lt;br /&gt;Then well into the test when the IRs had slowed to a drip I got a call from Canada. I had blown a transaction. Lemme see it... OK, sorry, that is what the spec says. No, these have to be handled this way, the debit goes over here and credit goes over there when X is Y.&lt;br /&gt;&lt;br /&gt;Now as usually happens in these deals I still did not know anything about accounting but some of the words had taken on glimmers of meaning and I asked, But isn't this the same as whatever? And then I threw around some terms and said that from my poor understanding what they were suggesting seemed wrong. Nope, that is how we do it. OK. Bye. Bye.&lt;br /&gt;&lt;br /&gt;And now comes the good part. I invoked Tilton's Lemma -- not because Kenny could not see the legitimacy of their accounting, though that encouraged me, but because of something else I found to be strangely compelling: my code would not do what they wanted.&lt;br /&gt;&lt;br /&gt;I tried to see how I could patch in the exception and there was no way. I would have needed action at a distance and Einstein had already spoken on that. What was needed was for the microcode to behave differently based on information (X and Y) available only at the top level in which the higher level transactions were being identified and their handlers invoked. The only way to give Canada what they wanted was either to add a parameter to everything in the call chain (which I would have called woof-woof, I think) or even more elegantly to set a global variable at the higher level that this one microcode handler could watch out for. Ewwww.&lt;br /&gt;&lt;br /&gt;Now please do not think I am posing as a person of integrity or principle or anything because I am the most miserably pragmatic soul you can hope to meet, but I got back on the phone to Canada.&lt;br /&gt;&lt;br /&gt;"Marcia, Kenny. My code does not want to do what you want, eh? Your spec is pretty clear on all these things and just from the sound of it it seems the way I am handling it now is right anyway. I can kludge things up to get what you want, but I will hate myself in the morning."&lt;br /&gt;&lt;br /&gt;Marcia said she would talk to Bernie, her VP, and get back to me. She did not do so for so long that I forgot about it and to her credit she did not even have to make the call but she did.&lt;br /&gt;&lt;br /&gt;"Kenny, Marcia. I spoke to Bernie. The way you are handling that transaction will be OK. We can live with the way you are doing it."&lt;br /&gt;&lt;br /&gt;Tilton's Lemma lived on. Somehow clean design (starting I freely acknowledge with a great spec) had flushed out a faulty business practice. The users had indeed offered an RFE discontinuous with all their other stated requirements, but it turned out to be such an egregious error that they agreed to fix it. (To their credit again!)&lt;br /&gt;&lt;br /&gt;Why does this war story give me goose bumps? Yes, I need to get out more. And OK, maybe it is not such a big deal. The careful architecture forced on us by having to program these godawful machines makes it easy for programmers to see inconsistencies the business experts miss.&lt;br /&gt;&lt;br /&gt;I just get a kick out of it -- a sense of God or Plato or the Tao throwing their weight around as long as we take design seriously and hop on the phone over such things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-4553396327363092058?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/4553396327363092058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=4553396327363092058' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/4553396327363092058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/4553396327363092058'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/we-can-live-with-way-you-handled-that.html' title='&quot;We Can Live With the Way You Handled That&quot;'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-2475597964318051331</id><published>2008-03-22T12:11:00.006-04:00</published><updated>2008-03-22T15:01:37.673-04:00</updated><title type='text'>TLOP: The Worst Thing You Can Say About Software Is That It Works</title><content type='html'>I walked out of my cubicle, turned left, went up one maze turn, turned into the next cubicle. This was clearly a while ago, before email and even before I had reached the point where I would phone a guy ten feet away in case they were not there so I could leave voice mail.&lt;br /&gt;&lt;br /&gt;I wanted to tell Mike that I had enhanced the julian date function he had shared with me so he could replace his with mine instead of the system growing a multiplicity of julian date functions.&lt;br /&gt;&lt;br /&gt;Mike was another contractor on some godforsakenly dreary application being developed at cruising altitude in some megabank, a great guy always joking well and laughing about everything including his obsession with the real estate scheme infomercials he apparently watched non-stop in his free time.&lt;br /&gt;&lt;br /&gt;I told Mike I had snazzed his function up nicely, generalizing it or adding some whiz-bang feature or something, and mentioned he could now modify his program to use the new version.&lt;br /&gt;&lt;br /&gt;Something I need to get across to My Cherished Reader is the utter and profound honesty of Mike's reaction. Indeed, sufficient googling may well surface Mike's blog entry detailing in turn his astonishment and horror at what I had proposed. For when I finished there was a brief moment of incomprehension and then a dawning and his eyes grew wide and his jaw dropped and then a huge smile of wonder spread across his face, his palms rose in supplication for any possible justification of my madness and at last words came to him.&lt;br /&gt;&lt;br /&gt;"But...but...," he stammered for effect. "My code already works!"&lt;br /&gt;&lt;br /&gt;It was a grand moment, two solid technologists sincere in their craft standing face to face with not one scintilla of common ground on the simplest of questions.&lt;br /&gt;&lt;br /&gt;Mike was reeling at the idea that a working module should be touched. He repeated his encomium ("It works!") and then with no offense intended and with solid good-feeling camaraderie just started laughing at me.&lt;br /&gt;&lt;br /&gt;Meanwhile I knew without doubt that swapping in my version would likely take one minute (what's that? about sixty seconds?) and that application systems should be kept as simple as possible (and so not have two julian date functions (can you say Y2K?)).&lt;br /&gt;&lt;br /&gt;I shrugged -- it was a small matter -- and retraced my path back to my cubicle before the pheromone trail could grow cold. Well, this is my blog, so Mike was wrong. Tilton's Law:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;The worst thing you can say about software is that it works. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;I think I can prove that with geometry: if a pile of code does not work it is not software, we'll talk about its merit when it works, OK? Therefore to say software works is to say nothing. Therefore anything substantive one can say about software is better than to say it works. QED. (That last bit is the geometry.)&lt;br /&gt;&lt;br /&gt;So what else besides that it works can you say about software, especially about applications written in tall buildings? Well, unless one is banking on the relatively high probability that the project will get canceled before ever it sees light of day, the software will eventually be asked to do new things or to do old things differently.&lt;br /&gt;&lt;br /&gt;So the software must not be brittle and must not have any more built-in assumptions than necessary and where one builds in the assumptions it would be nice if they were abstracted out of the core so that new requirements can be handled as gracefully as possible.&lt;br /&gt;&lt;br /&gt;Note that new and changed requirements come along not just after a successful deployment but also during development, perhaps even more so because only when users see software do they realize what they wanted. They should do a study: I bet requirements change more just implementing the software than they do ever after. Brittle, inflexible software can be so hard to change during development that projects never make it out the door no matter how well the software "works" on the original requirements.&lt;br /&gt;&lt;br /&gt;Reminds me of another war story. Schedule "B".&lt;br /&gt;&lt;br /&gt;The law on tax shelters had just been changed eliminating the bogus write-offs those things produced and some financial establishment needed some contractor to write the software to generate statements for clients detailing exactly how badly they would be hosed by the new law. Apparently they had tried it in-house and the guy assigned to it had quit after working on it for a couple of months to no avail. Jobs were everywhere back then in the Eighties, why not?&lt;br /&gt;&lt;br /&gt;God forbid I should digress: it was a fun interview, really nice group and nice manager. The best point was when he asked His Kennyness what was His greatest weakness. Neat question!&lt;br /&gt;&lt;br /&gt;Lemme see...no...no...no... I was looking at the floor going through coding, debugging, DB design, and it was taking a while which I thought was pretty funny and I am sure they were all enjoying it but I &lt;span style="font-style: italic;"&gt;really &lt;/span&gt;wanted to come up with something and then it came to me.&lt;br /&gt;&lt;br /&gt;"Testing!" I almost yelled. "I am terrible at testing!"&lt;br /&gt;&lt;br /&gt;Whew! Reminds me of the time I had a little team (this was before people realized I should just be chained to an out-of-the-way workstation and hosed down and thrown food as needed on big projects) and was assigned a junior nooby who asked me the same question about three times and who hated me because apparently Hell hath no fury like a woman gently suggested she might take notes,  which was great (that she hated me) because she was so useless we just had her testing my code and believe me no software has ever been subjected to such merciless, sustained, and deliberate abuse as was mine. Every twenty or thirty minutes we would hear this triumphant rejoicing "Ha!" explode from her cubicle as she found another bug and imagined another dagger plunged between my ribs when in fact I was loving the whole thing because to me testing is just God and Abraham and Isaac all over again. Where was I? Schedule "B".&lt;br /&gt;&lt;br /&gt;Anyway, the task went very well. The manager (another Mike) gave me a very clear spec and I did my usual structured architectural blah-blah-blah and the users were very nice and called me every once and a while with RFEs. Bringing me to my point.&lt;br /&gt;&lt;br /&gt;Mike was a great guy but also button-downed and into process and told me not to listen to the users, make them ask him and he would tell them, No.  So I was always very nice with the users and said I welcomed their thoughtful consideration and input and could barely restrain myself from just dashing it off right now if I could just put them on hold for a second and I will indeed start looking at the matter while it would help very much if they could just run this great idea past Mike, he's a bit of a stickler for protocol, terrible bother I know, hate to ask this of you.&lt;br /&gt;&lt;br /&gt;OK, they would say.&lt;br /&gt;&lt;br /&gt;Then I would put down the phone and look at the code to see what was needed. Oh. Scratch, scratch, poke. Done.&lt;br /&gt;&lt;br /&gt;Then I would go into Mike's office and tell him the users had asked for X and he would make a face and I would say I had already made the change if that would affect his decision.&lt;br /&gt;&lt;br /&gt;Mind you this did not happen because I consciously planned for change, I just worried about things besides whether the code worked. Simple architectural tidiness went straight to the business bottom line: the users got exactly what they needed at no extra cost to the enterprise. How does simple clean design make RFEs easy to handle? Tilton's Lemma:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Refinements to requirements cannot vary fundamentally from the original.&lt;/span&gt; &lt;/li&gt;&lt;/ul&gt;It is possible for users to say, Oh my, you have the runners running the bases clockwise? We wanted them going &lt;span style="font-style: italic;"&gt;counterclockwise&lt;/span&gt;. It is &lt;span style="font-style: italic;"&gt;not &lt;/span&gt;possible for the users to come back and say, We wanted them going first to second base, then over to first, then to third, and then home. Some fundamental force of nature constrains how we can screw up and keeps it within a metalevel such that refinements to requirements will never break code all that badly.&lt;br /&gt;&lt;br /&gt;[Keep your eyes open for the "We Can Live With the Way You Handled That" mind-bending illustration of the power of clean design.]&lt;br /&gt;&lt;br /&gt;The flipside war story was in a different tall building working on a system so badly designed that after a certain point it pretty much stopped evolving at all.&lt;br /&gt;&lt;br /&gt;I walked up to my manager and said I had an idea on how to improve something I was working on for her so that it could be used for other things.&lt;br /&gt;&lt;br /&gt;"No, no, no," she said. "I just need this one thing working before Thursday's meeting so I can score one on the users. They are out to get us."&lt;br /&gt;&lt;br /&gt;Ah, systems development as an act of war. The system they had developed was such a horror that the only thing that ever moved it forward was a team of very well-paid outside contractors who managed against all odds to add new functionality, pausing from their toils every several days when one of them would take a design two-by-four across his skull from said system and lean back and poll the others on how badly each felt the system hindered them, an order of magnitude generally being settled on as no exaggeration however often it usually is.&lt;br /&gt;&lt;br /&gt;The IT department ended up with a bunker mentality lobbing back hand grenade code releases to suppress fire from users strafing us with gratuitous RFEs as the organization staggered towards collapse and acquisition, and it being a financial institution to no small degree dependent on how well it processed information I cannot help thinking this system was to blame.&lt;br /&gt;&lt;br /&gt;But it &lt;span style="font-style: italic;"&gt;did &lt;/span&gt;work.&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Oh, sorry. Lisp? Well, the more powerful the language the more time one has for that much easier a job of designing an application as opposed to banging out whatever source code passes the unit tests. And when it comes to separating specifics out into a configuration area that drives a more universal engine... can you say DSL? Sher ya can.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-2475597964318051331?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/2475597964318051331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=2475597964318051331' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2475597964318051331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2475597964318051331'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/tlop-worst-thing-you-can-say-about.html' title='TLOP: The Worst Thing You Can Say About Software Is That It Works'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7485653456246616310</id><published>2008-03-10T18:21:00.004-04:00</published><updated>2008-03-13T04:47:56.889-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tilton&apos;s Law DBMS bugs Tandy COBOL'/><title type='text'>Tilton's Law: Solve the First Problem</title><content type='html'>This was such a weird project. Scheduled for five days altogether. My friend from &lt;a href="http://smuglispweeny.blogspot.com/2008/03/my-biggest-lisp-project.html"&gt;the clinical drug trial venture&lt;/a&gt; was also a tech recruiter who got me about half my tech jobs over the years and this one was a real throwaway.&lt;br /&gt;&lt;br /&gt;What we had was a mid-80s start-up in the educational software game producing exactly the kind of mind-numbing drill and practice software that was supposed to revolutionize education because Look, Ma! We used computers!&lt;br /&gt;&lt;br /&gt;Now they were stuck on some software problem and needed help fast. Their stack was Tandy, Cobol, and some micro database package. My skills were Apple, Cobol, and ISAM and in those days that was a deerskin glove fit so off I went for a mutual look-see.&lt;br /&gt;&lt;br /&gt;I was on the beach, why not?&lt;br /&gt;&lt;br /&gt;The next morning I am walking up to an apartment building where this enterprise had wedged itself into what was meant to be doctor's offices. Inside I sit down with the top guy in his office and the entire company joins us.&lt;br /&gt;&lt;br /&gt;The staff unleashes a thirty minute nightmare tale of software crashes, dysfunctions, anomalies, and disrepair as each person takes turns reciting some utterly bizarre malfunction of the application, all with the database software as the likely culprit. It was a tag-team misery report, a through the looking glass panoply of software non-determinsim. It was wonderful.&lt;br /&gt;&lt;br /&gt;A half dozen times I formulated "Explanatory Guess X" only to hear in the speaker's next sentence that they had thought it might be X and but no luck. I mean it was really wonderful and then finally it ended. My head was spinning.&lt;br /&gt;&lt;br /&gt;"Have you worked with the Tandy OS," the manager asked.&lt;br /&gt;"No."&lt;br /&gt;"Cobol?"&lt;br /&gt;"Yes, but it does not sound like Cobol is your problem."&lt;br /&gt;"No. I don't suppose you have worked with this DBMS?"&lt;br /&gt;"No."&lt;br /&gt;A pause.&lt;br /&gt;&lt;br /&gt;"Can you help us?" See straw. Clutch,&lt;br /&gt;&lt;br /&gt;I have no idea what to tell them.&lt;br /&gt;&lt;br /&gt;"Is the DBMS any good?", I recover enough to ask.&lt;br /&gt;"I checked it out pretty well. It got great reviews, it is supposed to be the best."&lt;br /&gt;I look down at my shoes.&lt;br /&gt;&lt;br /&gt;The contract was for five days. The longest any single glitch had stopped me was for five days. Do the arithmetic.&lt;br /&gt;&lt;br /&gt;"Yes," I say.&lt;br /&gt;&lt;br /&gt;It took seven. They paid up front for the first five, never paid for the last two probably because they did not have it or maybe because of the way things went. You'll see. And I am surprised it came to seven days, I only remember one or two. I never ran their software once and I do not remember even touching a computer. Here is what happened.&lt;br /&gt;&lt;br /&gt;After signing on I took home the manuals for their DBMS and a listing of their schema definition. It took maybe a day to decide that everything looked right. The next day I ask Tom the programmer how hard it would be to just initialize an empty database and start over entering the data.&lt;br /&gt;&lt;br /&gt;"Easy", says Tom.&lt;br /&gt;&lt;br /&gt;Welcome to Tilton's Law: Solve the First Problem. They had described to me twenty distinct failures and that was too many for me, I am not smart like you guys, I cannot just figure these things out in the shower.&lt;br /&gt;&lt;br /&gt;I wanted to turn the software off and turn it back on with a clean slate and see what went wrong first and &lt;i&gt;stop right there&lt;/i&gt;. I just wanted to see what went wrong first and fix that. I suspect that needs no explanation, but what am I doing up on this soapbox if I am not going to explain these things?&lt;br /&gt;&lt;br /&gt;Here goes. Once upon a time my sleazebag ward politician buddy and I were cruising the singles bars back when they had such things and he got nicely eviscerated by a woman we were chatting up. My buddy had said something cynical and she had challenged him on it.&lt;br /&gt;&lt;br /&gt;"Oh, I have compromised my principles a few times," he conceded with a sly grin.&lt;br /&gt;&lt;br /&gt;"You can only compromise your principles once," she replied. "After that you don't have any."&lt;br /&gt;&lt;br /&gt;Software is the same. This stuff is hard enough to get right when things are working nominally, but once they go wrong we no longer have a system that even &lt;span style="font-style: italic;"&gt;should &lt;/span&gt;work.&lt;br /&gt;&lt;br /&gt;Back on the project, the next day I get a call.&lt;br /&gt;&lt;br /&gt;"Bad news," Tom says. Uh-oh.&lt;br /&gt;&lt;br /&gt;"What happened?"&lt;br /&gt;"Same thing. Mary was entering the 118th record and the program crashed."&lt;br /&gt;&lt;br /&gt;I pretty much fell out of my chair. Somewhere in the thirty minute firestorm of issues I had heard the number 118.&lt;br /&gt;&lt;br /&gt;"118 sounds familiar."&lt;br /&gt;"Yep," Tom moaned inconsolably. "That's what happened before. Sorry, no difference."&lt;br /&gt;I was doing cartwheels.&lt;br /&gt;&lt;br /&gt;"Tom, how hard would it be to write a program to just write out a couple hundred records, just put in dummy data, 1-2-3-4-5...?"&lt;br /&gt;"That would be easy."&lt;br /&gt;"Awesome, do that and let's see what happens in batch mode," says me.&lt;br /&gt;"OK."&lt;br /&gt;"And reinitialize the DB first, OK?"&lt;br /&gt;"OK."&lt;br /&gt;&lt;br /&gt;The next day I hear from Tom. Sounds like he is calling from the morgue.&lt;br /&gt;&lt;br /&gt;"Bad news, Kenny."&lt;br /&gt;Oh, no. It worked.&lt;br /&gt;&lt;br /&gt;"What happened?"&lt;br /&gt;"Same thing. The program wrote out 118 records and crashed. Sorry, Kenny."&lt;br /&gt;Oh, yeah, I just hate easily reproducible errors. Not!&lt;br /&gt;&lt;br /&gt;"Listen, Tom, let's try making the buffer allocation bigger."&lt;br /&gt;"OK."&lt;br /&gt;&lt;br /&gt;The next day, "Bad news. Same thing."&lt;br /&gt;I am icing the champagne; this is one solid, reproducible bug. But what about the others?&lt;br /&gt;&lt;br /&gt;"Tom,  remember the first time this thing crashed, before I came on board?"&lt;br /&gt;"Yeah."&lt;br /&gt;"Did you start over from a fresh database or just resume working on the one that had been open when the DBMS had crashed?"&lt;br /&gt;"We just continued working with the same DB."&lt;br /&gt;"Oh. OK."&lt;br /&gt;&lt;br /&gt;Tilton's Law (Solve the First Problem) had been broken as badly as broken can be. A DBMS had failed while writing data and they had tried to continue using the same physical DB. This transgression is so severe it almost does not count.&lt;br /&gt;&lt;br /&gt;Normally Tilton's Law refers to two or three observed issues that do not necessarily seem even to be in the same ballpark. The law says pick out the one that seems most firstish and work on that and only that until it is solved. The other problems might just go away and even if not the last thing we need to do while working on one problem is to be looking over our shoulders at possible collateral damage from some other problem.&lt;br /&gt;&lt;br /&gt;Two minutes later I am on the phone to DBMS tech support .&lt;br /&gt;&lt;br /&gt;"Hi, we're reliably crashing after adding 118 records in one sitting."&lt;br /&gt;"Yes, that is a known problem."&lt;br /&gt;Oh. My. God.&lt;br /&gt;&lt;br /&gt;"Would you like us to send you the patch for that?", she asks.&lt;br /&gt;"That would be lovely."&lt;br /&gt;&lt;br /&gt;This being before the advent of the Interweb we confirmed our mailing address and asked for it to be sent out ASAP and overnight delivery. But we are not done yet. Tilton's Law or no, all I have solved is P1, the first problem.&lt;br /&gt;&lt;br /&gt;"One more thing," I say.&lt;br /&gt;"Shoot."&lt;br /&gt;"If we continue working with the DB after this crash..."&lt;br /&gt;"Oh, no. Don't do that. It's hopelessly corrupted at that point."&lt;br /&gt;&lt;br /&gt;Were some of the other issues unrelated to the first crash? I will let you know as soon as this test I have running to solve &lt;a href="http://en.wikipedia.org/wiki/Halting_problem"&gt;the halting problem&lt;/a&gt; finishes.&lt;br /&gt;&lt;br /&gt;Meanwhile, the conversation had suggested how we might get them up and entering data &lt;span style="font-style: italic;"&gt;now&lt;/span&gt;. Apparently we were crashing because of a bug that surfaced when more than so many records were being held in the buffer before being written out. We had tried making the buffer bigger, only making things worse.&lt;br /&gt;&lt;br /&gt;"Tom, we can wait for the patch, but I have one last idea in mind that might get this thing working for you. Want to try one more thing?"&lt;br /&gt;"Sure."&lt;br /&gt;"Try making the buffer &lt;span style="font-style: italic;"&gt;half &lt;/span&gt;the size it was when we started."&lt;br /&gt;"OK."&lt;br /&gt;A few minutes later he comes back.&lt;br /&gt;&lt;br /&gt;"It works now."&lt;br /&gt;"Yeah, baby!"&lt;br /&gt;"I had it loop to one thousand. No problem."&lt;br /&gt;"Cool. Let's tell the others and go get drunk."&lt;br /&gt;&lt;br /&gt;Nope. Something is wrong. Tom is just standing in the doorway all deer and headlights.&lt;br /&gt;&lt;br /&gt;"Can I ask you something?", Tom asks quietly.&lt;br /&gt;"Sure."&lt;br /&gt;"I do not understand why making the buffer smaller made the program work."&lt;br /&gt;"Well there was this bug that had to do with being unable to keep more than so many records in memory and with a smaller buffer the software did not try to keep so many in memory."&lt;br /&gt;Long pause.&lt;br /&gt;&lt;br /&gt;"OK, but why does it work now?"&lt;br /&gt;Hmm.&lt;br /&gt;&lt;br /&gt;"Maybe 118 multiplied by the record size is more than 16,384 and somewhere in the DBMS logic there was an integer overflow so the problem does not come up if the cache is smaller and the software flushes the cache before it gets to 16,384."&lt;br /&gt;&lt;br /&gt;"All right," says Tom "But I do not understand why we make the buffer smaller and now the software works."&lt;br /&gt;&lt;br /&gt;This was surreal. I try a different tack, a really dumb one, but sometimes when a grizzly bear has your back to the wall all you can do is tap dance.&lt;br /&gt;&lt;br /&gt;"Look. There are multiple code paths in an application, right? Every conditional is a fork in the path. A bug exists in some branch or other out of all the code paths, right? By changing a fundamental parameter we send the code down a different code path. Avoiding the bug."&lt;br /&gt;Pause.&lt;br /&gt;&lt;br /&gt;"I just don't understand why making the buffer smaller makes the program work."&lt;br /&gt;&lt;br /&gt;Then it came to me. I was Dr. Chandra in 2010 trying to get Hal to fire the rockets, and Tom was Hal stuck in a Mobius loop unable to resolve my &lt;a href="http://www.xs4all.nl/%7Eace/Literaria/Poem-Graves.html"&gt;understanding of the confusion&lt;/a&gt; with his confusion of the understanding.&lt;br /&gt;&lt;br /&gt;"I don't know, Tom," I say. "I don't know why it works now."&lt;br /&gt;Tom nods.&lt;br /&gt;&lt;br /&gt;Suddenly Mike, the project lead, appears.&lt;br /&gt;&lt;br /&gt;"Kenny, Tom. In my office. Now."&lt;br /&gt;Whoa.&lt;br /&gt;&lt;br /&gt;"OK, this has to stop. Kenny, I am paying you to solve this problem and you have Tom doing all your work.  He has his own work to do. From now on you work on this problem and Tom you do what you are supposed to be doing. Have I made myself clear?"&lt;br /&gt;&lt;br /&gt;Remember in Annie Hall when Woody Allen turns to the camera and asks, Why can't real life be like this?&lt;br /&gt;&lt;br /&gt;"Actually...I think I'm done."&lt;br /&gt;&lt;br /&gt;Leaving Mike and his facial expression frozen in spacetime, I turn to Tom with raised eyebrows for his assent and Tom nods. I turn back to Mike, who no longer knows where he is.&lt;br /&gt;&lt;br /&gt;"It turns out this is a known bug. You'll have a patch tomorrow or the next day. In the meantime we found a workaround and you are up and running. Mary can start entering your data, um, now."&lt;br /&gt;&lt;br /&gt;Mike recovers.&lt;br /&gt;&lt;br /&gt;"So basically I am sitting here making a complete ass out of myself?"&lt;br /&gt;&lt;br /&gt;Good for him. We all had a good laugh, shook hands and I was on my way and Tilton's Law of Programming was  reaffirmed: Always solve the first problem. The corollary: there only ever is the first problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7485653456246616310?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7485653456246616310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7485653456246616310' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7485653456246616310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7485653456246616310'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/tiltons-law-solve-first-problem.html' title='Tilton&apos;s Law: Solve the First Problem'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-8404412940321029749</id><published>2008-03-10T04:40:00.006-04:00</published><updated>2008-03-10T08:49:10.643-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cobol Macros Tall Buildings Metaprogramming'/><title type='text'>Kenny and The Firing Squad, Episode II: COBOL Has Macros?!!</title><content type='html'>[[If it is good enough for George Lucas (random release of episodes) it is good enough for me.]&lt;br /&gt;&lt;br /&gt;Roll the trailer: Kenny hanging with one hand onto the rear axle of a runaway Cobol stagecoach headed straight for a cliff off which a team of otherwise sensible horses soon will be jumping reaching with his other hand to his ankle sheath and pulling out... COPY...REPLACING!]&lt;br /&gt;&lt;br /&gt;Well, someone on comp.lang.lisp made a joke about Cobol and Lisp so I thought I would tell this  twenty years later still astonishing cobol-and-lisp-separated-at-birth? war story within a war story about how COPY...REPLACING -- no, that is  real Cobol , not a Cobol joke -- ended up taking away the award for Best Supporting Language Feature.&lt;br /&gt;&lt;br /&gt;A war story within a war story, with the same theme because I guess they shared a central figure, a young project lead we will call (...thinking of a name...) Reggie.  That is good. I got it from Regular Guy and I want to make clear that Reggie was a good guy with a good sense of humor, someone I would party with any time, a young guy his manager (another good guy... look, all these people working in tall buildings are good guys tolerating loose cannon per diems like me to get their code written but not inviting us to the company Christmas party (in the cafeteria -- no loss -- I would have showered had I known) actually causing a boycott by one great guy who could not believe I was left sitting alone at my workstation) ... a young guy his manager trusted implicitly I am sure because of Reggie's technical triumphs past.&lt;br /&gt;&lt;br /&gt;The outer story is that I was not even supposed to be working on the task from which I was about to be fired for incompetence. I had not even interviewed with Reggie. (Was that the problem? Hmm.) Reggie had gone to an RDB training class and done his first relational schema and an in-house consulting team had deemed it faulty. Reggie's manager backed him so I was brought in as an out-house... hang on... external consultant to provide a second opinion.&lt;br /&gt;&lt;br /&gt;I agreed with the in-house team but Reggie would not budge and the manager &lt;span style="font-style: italic;"&gt;still &lt;/span&gt;backed him (and I need to admit no one was able to make Reggie see his confusion which must be a story in itself because he &lt;span style="font-style: italic;"&gt;was &lt;/span&gt;listening to us, he really &lt;span style="font-style: italic;"&gt;was &lt;/span&gt;a good guy). The schema stayed, and a stage was now a phase:&lt;br /&gt;&lt;br /&gt;Reggie's mistake was that he saw that two drug trial business objects (phase and stage) both had a one-to-many relationship with the sample biz object, so he treated stage as a phase. But a stage is not a phase. In Phase IV of testing the samples from Phase III were divided into different stages.) But Reg was fixated on that one abstract commonality and could not get past it.&lt;br /&gt;&lt;br /&gt;So? Going away lunch for Kenny? Maybe just handshakes all around since I had only been there a couple of weeks? Nope. It turns out I was there for another reason besides my brilliant mastery of relational DB design: they needed someone to grind out nineteen nearly identical query screens which can best be described as exactly what 4GL packages provide at the push of a button.&lt;br /&gt;&lt;br /&gt;Feel free to groan.&lt;br /&gt;&lt;br /&gt;Yep. Nineteen screens, each aimed at some node in the DB hierarchy. A few fields at the top constituting key fields and selection criteria, while below was a scrolling list of matching items, each column showing some attribute. Select a row, hit the zoom key and.... sorry, could those of you still awake please nudge the ones who are snoring?&lt;br /&gt;&lt;br /&gt;The stack was VAX/VMS, COBOL, TDMS for forms management, and I forget what RDB. Based on the nineteen identical screens take one down pass it around eighteen screens to code on the wall functional spec a child of three could see some template approach was in order, if only through the miracle of cut and paste. But I had been around long enough to know how fast the Red Sea can collapse when after cutting and pasting nineteen screens the user comes along and says could these screens work just a wee bit differently?&lt;br /&gt;&lt;br /&gt;Now it happens I had been on a project run by a team of English yobbos who had nothing but contempt for us the few American cowboys (they called us) hired to fill some chairs but they were great fun and pretty good and we had together discovered that Cobol not only had copy-replacing but it could even replace part of a name. I forget what it took, but we found just one letter in the ASCII character set (pretend it was the octothorpe) that lets us code:&lt;br /&gt;&lt;pre&gt;perform edit-#fieldname.&lt;/pre&gt;&lt;br /&gt;...in a template and then (guessing at much of this syntax):&lt;br /&gt;&lt;pre&gt;copy "edit-template" &lt;template&gt; replacing #fieldname with customer-id.&lt;/template&gt;&lt;/pre&gt;&lt;br /&gt;Well, one was all we needed, so away we went and life was good and now here I am staring at nineteen screens and I forgot to mention Cobol's MOVE-CORRESPONDING which could populate TDMS data records from DB data records if I was bright enough to name things the same and stand back Argentina! Here come the screens!&lt;br /&gt;&lt;br /&gt;I told Reggie what I was going to do. He said, Fine. I said it would help knowing which of the nineteen screens was the nastiest (OK, they were not all that identical). He got it. Fourteen, is a beast. It pulls in data from two yadda yadda. Off I went.&lt;br /&gt;&lt;br /&gt;You all know how it goes. I spend a week on screen fourteen, not because it takes a week but because I am building a framework, with one eye on the other eighteen screens sitting in the corner. Hell, I even built an IDE.&lt;br /&gt;&lt;br /&gt;The command language for VMS was DCL, a gorgeous little thing. This was all before the multi-window days of VMS. Things got a little tedious as I bounced from editing the TDMS form to the Cobol template to the screen-specific Cobol copy-replacing the template to testing the thing, so I wrote a DCL script that just needed to know on which screen I was working and what I wanted to do and then did The Right Thing. When I exited I fell back into the script, which asked what now? Way cool and productive.&lt;br /&gt;&lt;br /&gt;Where was I? Oh. You know how it goes. With screen fourteen working I launch into screen one, hoping it Just Works because Reggie and I had picked out A Beast. Ah, not bad. Screen two. Check. Screen three. Here's a twist. Scribble scribble... good.&lt;br /&gt;&lt;br /&gt;Screen four. Excuse me? Two lines of info in order to display one detail? Ouch, did not see that one coming. Bang bang hammer thwack... OK. And on we go. Sure, I still had to build a TDMS form for each screen, but I will live. Or so I thought.&lt;br /&gt;&lt;br /&gt;It is Monday of week three and Reggie is standing at the door to my windowless little room.&lt;br /&gt;&lt;br /&gt;"Morning."&lt;br /&gt;"Morning."&lt;br /&gt;"How's it going?"&lt;br /&gt;"Great."&lt;br /&gt;"I ask because I haven't seen anything yet."&lt;br /&gt;"Sorry?" Hairs on end.&lt;br /&gt;&lt;br /&gt;In five years of programming including three as a pricey independent consultant I had yet to hear one discouraging word from a manager unless you count the time the guy (a very big guy) stood over me beet red literally spitting "Sh*t! Sh*t! You didn't test it, did you?!" as my program gleefully copied only every third record in its first production run because I had left in the bit that did that to make tests run faster. Another day.&lt;br /&gt;&lt;br /&gt;"Well it has been two weeks and I haven't seen one screen yet."&lt;br /&gt;"I told you. I am doing all nineteen, not one."&lt;br /&gt;"That's all well and good, but I will be at a class all week, won't be back till Friday, and I need to see something by then."&lt;br /&gt;"Fine." Not sure if you can see the smoke rising from my collar.&lt;br /&gt;&lt;br /&gt;It is now Friday noon. Kenny has logged no overtime, but Kenny has had his game face on for four solid days. Co-workers discovered they could rewarm their coffee faster than the microwave if they just put it in the same room with me.&lt;br /&gt;&lt;br /&gt;Kenny has little hope of a Hollywood ending, but suddenly Reggie is standing in the doorway, right where he was when he hung the sword over my neck.&lt;br /&gt;&lt;br /&gt;"How's it going?&lt;br /&gt;"Good. How was the class?"&lt;br /&gt;"Good."&lt;br /&gt;Silence.&lt;br /&gt;"So where do we stand?"&lt;br /&gt;"With the screens?"&lt;br /&gt;"Yeah."&lt;br /&gt;"They're done."&lt;br /&gt;"They're done? All of them?"&lt;br /&gt;"Yep."&lt;br /&gt;Silence.&lt;br /&gt;"Well, if that's true, that's great."&lt;br /&gt;Withering look. And the fun has only begun.&lt;br /&gt;&lt;br /&gt;Late Monday Reggie swings by with a list of trivial bugs and issues.&lt;br /&gt;&lt;br /&gt;"Thanks."&lt;br /&gt;"I really like the way it works."&lt;br /&gt;"It's your design."&lt;br /&gt;"Right," and reaches over his shoulder to pat himself on the back.&lt;br /&gt;Did I mention he was a good guy?&lt;br /&gt;&lt;br /&gt;"Could you print out the source code for me? I'll read it on the train."&lt;br /&gt;"Will do," looking forward to the praise and astonishment soon to be heaped on me.&lt;br /&gt;&lt;br /&gt;Tuesday. My turn to stand in the door of his office.&lt;br /&gt;&lt;br /&gt;"Kenny, I was trying to read your code on the train home."&lt;br /&gt;Uh-oh.&lt;br /&gt;&lt;br /&gt;"First I'm up here, it says perform this, I have to flip down to find it, then there it says perform that, I'm flipping down again, then I flip back up and it says perform something else and I am flipping down again. Then up then down then up again. What's up with that?"&lt;br /&gt;&lt;br /&gt;"It's called structured programming. It's in all the books."&lt;br /&gt;&lt;br /&gt;I forgot to mention that by this point I had already given notice. I explained that I thought I was signing on for a short DB design review, not a job in a body shop. They reacted with all the chagrin of the monks at learning Ace Ventura was leaving the temple.&lt;br /&gt;&lt;br /&gt;"Yeah, well that's all well and good, but if I cannot understand your code we won't be able to use it."&lt;br /&gt;&lt;br /&gt;Well, I was right about one thing, only it turned out to be the &lt;span style="font-style: italic;"&gt;garbage &lt;/span&gt;heap. By now I think I have made clear to my Honored Reader that I do not consider myself an exemplar of human social interaction including especially the delicacy required by the workplace, but what I did next disappointed even myself but felt great because it was so perfectly honest: I slowly closed my eyes, leaned my head against the door jam, and just stayed that way.&lt;br /&gt;&lt;br /&gt;Reggie could not help laughing. Did I mention... yeah, I did.&lt;br /&gt;&lt;br /&gt;"All, right. Look. We'll do a code walk-through with Roger [his co-lead] this afternoon, see if we can figure this out."&lt;br /&gt;&lt;br /&gt;"Fine."&lt;br /&gt;&lt;br /&gt;This afternoon. Twenty-thirty minutes. Copy-replacing. Here is the template, here is a usage. The usage has all and only the stuff specific to that screen. The template. blah blah blah. This is here because of screen eight, two lines to show one detail. If you get other screens like that use eight as your starting point. Oh, this is because of fourteen, that special XYZ requirement. Yadda yadda yadda but there was one strange thing and I was deeply worried.&lt;br /&gt;&lt;br /&gt;Neither of them asked a question. Ever. Not one. Have I conveyed the smallness of the questioning? This cannot be good, but I had no more to say.&lt;br /&gt;&lt;br /&gt;"Any questions? Reg?"&lt;br /&gt;"No."&lt;br /&gt;"Rog?"&lt;br /&gt;"No." Pause. "Pretty obvious, actually."&lt;br /&gt;&lt;br /&gt;And then silence.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-8404412940321029749?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/8404412940321029749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=8404412940321029749' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8404412940321029749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8404412940321029749'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/kenny-and-firing-squad-episode-ii-cobol.html' title='Kenny and The Firing Squad, Episode II: COBOL Has Macros?!!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-6170791459359150344</id><published>2008-03-09T05:42:00.005-04:00</published><updated>2008-03-11T05:56:59.110-04:00</updated><title type='text'>Tilton's Law of Programming: Fear No Evil</title><content type='html'>We just had this exchange on comp.lang.lisp:&lt;br /&gt;&lt;br /&gt;&lt;div class="moz-text-flowed" style="font-family: -moz-fixed; font-size: 13px;" lang="x-western"&gt;&lt;br /&gt;srdjan.m wrote:&lt;br /&gt;&lt;blockquote type="cite"&gt;On Mar 9, 12:01 am, Ken Tilton wrote:&lt;br /&gt;&lt;br /&gt;&lt;blockquote type="cite"&gt;danb wrote:&lt;br /&gt;&lt;br /&gt;&lt;blockquote type="cite"&gt;On Mar 8, 10:59 am, "srdjan.m"  wrote:&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote type="cite"&gt;&lt;blockquote type="cite"&gt;(defun test ()&lt;br /&gt;(let ((x '(1)))&lt;br /&gt;(not-ok x)&lt;br /&gt;x))&lt;br /&gt;CL-USER&gt; (test)&lt;br /&gt;(1 C)&lt;br /&gt;CL-USER&gt; (test)&lt;br /&gt;(1 C C)&lt;br /&gt;&lt;/blockquote&gt;&lt;/blockquote&gt; &lt;blockquote type="cite"&gt;&lt;blockquote type="cite"&gt;I really do not understand why let is not initializing x&lt;br /&gt;&lt;/blockquote&gt;&lt;/blockquote&gt; &lt;blockquote type="cite"&gt;quote (the single quotation mark) doesn't create a new list, and of&lt;br /&gt;course nconc alters x in place.  So you're repeatedly binding x to the&lt;br /&gt;same list and appending 'c to that list.&lt;br /&gt;&lt;/blockquote&gt; &lt;blockquote type="cite"&gt;Incidentally, this is the universal beginner's question.  It's been&lt;br /&gt;asked at least three or four times in the last few months.  So you&lt;br /&gt;have plenty of company &lt;span class="moz-smiley-s1"&gt;&lt;span&gt; :) &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;IIANM somewhere in here is either a list or a pointer to a list of these&lt;br /&gt;common nooby coding gotchas:&lt;br /&gt;&lt;br /&gt;&lt;a class="moz-txt-link-freetext" href="http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/top.html"&gt;http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/top.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;kenny&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Indeed there it is &lt;a class="moz-txt-link-freetext" href="http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/faq-doc-4.html"&gt;http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/faq-doc-4.html&lt;/a&gt;.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Oh my: "Destructive operations, such as NCONC, SORT, DELETE, RPLACA, and RPLACD, should be used carefully and sparingly. In general, trust the garbage collector: allocate new data structures when you need them."&lt;br /&gt;&lt;br /&gt;That's nuts! It sows fear and trembling while offering no actual guidance as to when to use destructive operations and when not.&lt;br /&gt;&lt;br /&gt;"Use them when you need them." I wonder what the next question will be. (Hint: "When do I need them?".)&lt;br /&gt;&lt;br /&gt;As for using them sparingly, what on earth does that mean? What if I "need them" twenty-five times, should I spare a few of them because twenty-five is too many?&lt;br /&gt;&lt;br /&gt;Technology is like an ill-tempered dog: never show it fear. If you are not sure how X works do not start inventing weird usage rules unrelated to how the technology works hoping they will somehow keep you safe. You will end up worrying a lot, not get the most out of your tool, and still get bit in the ass.&lt;br /&gt;&lt;br /&gt;Instead, take a minute or hour to find out how X works. In this case, there is nothing "in general" or "sparingly" or "as a rule" about it: if you own all the list structure on which you are about to operate, always use the destructive variant. If not, never use the destructive variant.&lt;br /&gt;&lt;br /&gt;The non-excepting exception is when the function you are writing is &lt;span style="font-style: italic;"&gt;meant &lt;/span&gt;to be destructive, in which case the caller is responsible for using it as they would any other destructive function.&lt;br /&gt;&lt;br /&gt;So when do I own structure? When I have created it, or called functions that have created it for me. When do I not own structure? When it has been passed to me.&lt;br /&gt;&lt;br /&gt;Suppose we have a silly function like this:&lt;br /&gt;&lt;pre&gt;(defun do-filter-and-flatten (lists do test)&lt;br /&gt;(apply 'append&lt;br /&gt; (delete-if-not test&lt;br /&gt;   (mapcar do lists))&lt;/pre&gt;&lt;span style="font-style: italic;"&gt;mapcar &lt;/span&gt;generates fresh structure, so I can use &lt;span style="font-style: italic;"&gt;delete-if-not&lt;/span&gt; instead of &lt;span style="font-style: italic;"&gt;remove-if-not&lt;/span&gt; on the list produced by &lt;span style="font-style: italic;"&gt;mapcar&lt;/span&gt;. But the lists themselves -- the members of the input parameter &lt;span style="font-style: italic;"&gt;lists &lt;/span&gt;-- came from somewhere else and might be in use, so they cannot be touched. Note that the &lt;span style="font-style: italic;"&gt;lists &lt;/span&gt;structure itself came from someplace else but does not come into play in this example because we begin by effectively copying that structure while mapcar-ing the do function.&lt;br /&gt;&lt;br /&gt;We can turn that around to drive home the point, by applying the filter first (and getting a much different function):&lt;br /&gt;&lt;pre&gt;(defun filter-do-and-flatten (lists do test)&lt;br /&gt;(apply #'append&lt;br /&gt; (let ((tmp (loop for list in lists&lt;br /&gt;                  when (funcall test list)&lt;br /&gt;                  collect list)))&lt;br /&gt;   (map-into tmp do tmp))))&lt;/pre&gt;We cannot touch &lt;span style="font-style: italic;"&gt;lists &lt;/span&gt;(via &lt;span style="font-style: italic;"&gt;delete-if-not&lt;/span&gt;) because it has been passed to us, so we test and collect&lt;span style="font-style: italic;"&gt;&lt;/span&gt;. But now we own the returned cons cells bound to &lt;span style="font-style: italic;"&gt;tmp &lt;span style="font-family: monospace;"&gt;and &lt;/span&gt;&lt;/span&gt;are free to whack their CARs with the mutating &lt;span style="font-style: italic;"&gt;map-into &lt;/span&gt;-- which Stanislaw Halik just pointed out to me and which I do not think I had even &lt;span style="font-style: italic;"&gt;heard of&lt;/span&gt; in thirteen years of Lisping!&lt;br /&gt;&lt;br /&gt;But if I may digress, Kenny don't play &lt;i&gt;let&lt;/i&gt;, certainly not in the middle of a Grahamanian cascade:&lt;br /&gt;&lt;pre&gt;(defun filter-do-and-flatten (lists do test)&lt;br /&gt;(loop for list in lists&lt;br /&gt;      when (funcall test list)&lt;br /&gt;      nconc (funcall do list)))&lt;/pre&gt;A final note. What if in this last version we knew that any "do" function would massage every element returning a new list along the way. Could we make &lt;span style="font-style: italic;"&gt;nconc &lt;/span&gt;the last step? I would not. Sometimes functions like these decide they have no work to do and then return the input list structure. We use destructive functions only when we &lt;span style="font-style: italic;"&gt;know&lt;/span&gt; we own the structure we will be altering, otherwise not.&lt;br /&gt;&lt;br /&gt;Then and only then shall we fear no evil.&lt;br /&gt;&lt;br /&gt;[All code above Just Typed In, corrections are welcome (and thanks to Anonymous for further reminding me that the non-destructive remove-if-not cannot be assumed to copy -- it might return the input list untouched).]&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-6170791459359150344?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/6170791459359150344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=6170791459359150344' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6170791459359150344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6170791459359150344'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/tiltons-law-of-programming-fear-no-evil_09.html' title='Tilton&apos;s Law of Programming: Fear No Evil'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-6996542634259171889</id><published>2008-03-08T05:36:00.006-05:00</published><updated>2008-03-10T15:24:33.926-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Clinical drug trial management software Lisp'/><title type='text'>My Biggest Lisp Project</title><content type='html'>Someone asked how much Lisp I have really done. I am building a resume these days getting ready to look for some Lisp work, so I thought I would kill two birds with one stone and write up my experience as the architect and lead developer (out of two, for the most part) of a clinical drug trial management system.&lt;br /&gt;&lt;br /&gt;Over a couple of years we built a system consisting of eighty thousand lines of Lisp, having probably thrown away another fifty thousand along the way. We were in the classic situation described by Paul Graham in On Lisp: not knowing exactly what program we were writing when we set out on our mission. We also used C libraries for: writing and reading 2D barcodes; forms scanning; character recognition; generating TIFFs, and probably a couple I am forgetting.&lt;br /&gt;&lt;br /&gt;The application was a nasty one:&lt;br /&gt;&lt;br /&gt;-- capture clinical drug trial patient data as it was generated on paper at the participating physician's site, using scanner and handwriting recognition tools;&lt;br /&gt;&lt;br /&gt;-- validate as much as possible with arbitrary edits; such as complex cross-edits against other data;&lt;br /&gt;&lt;br /&gt;-- allow a distributed workgroup to monitor sites and correct high-order mistakes;&lt;br /&gt;&lt;br /&gt;-- track all changes and corrections; and&lt;br /&gt;&lt;br /&gt;-- do everything with an impeccable audit trail, because the FDA has very strict requirements along these lines.&lt;br /&gt;&lt;br /&gt;Making things worse, doctors are often as sloppy about trial details as the FDA is strict about having the rules followed. But drug companies cannot run trials themselves because the FDA demands that investigators be independent to avoid conflict of interest. Getting compliance is tough, and that is the opportunity we were targeting   -- more better compliance through automation at a granular, near real-time level sufficient to give drug companies effective oversight over investigator performance.&lt;br /&gt;&lt;br /&gt;The stakes are tremendous. Blockbuster drugs can earn millions of dollars a day but only while under patent protection. Unfortunately, patents must be acquired at the start of the trial process, which can run for many years. A third or more of the revenue-rich patent life is spent just getting to market. Big snafus in trials can force months of delay with an opportunity cost of millions a day.&lt;br /&gt;&lt;br /&gt;When I got the call from my good friend who was the angel and visionary on this project, he was two years in with not a lot to show for it and his last top developer had just given notice. I went in to hear what they were up to and do an exit interview with the dearly departing.&lt;br /&gt;&lt;br /&gt;The business plan was to score big by handling hundreds of trials a year. This would be especially tough because every trial was different. Each involved a custom set of forms to be collected over a series of patient exams. These forms varied from exam to exam. Business logic dictated validation of the forms and how the trial was to run and varied from trial to trial as dictated by what is known as a trial protocol.&lt;br /&gt;&lt;br /&gt;When I heard all this I knew we would have to find a solution that did not involve custom programming for each trial. The application would have to be configurable without programming, by a power user trained in the software. If Lisp is the programmable programming language, we needed a programmable application.&lt;br /&gt;&lt;br /&gt;Later I learned that competitors in our space had half our functionality and could not handle more than fifteen trials a year and were not profitable. They attempted what they called a "technology transfer" to the drug companies, translating as "we cannot scale this approach but maybe you can". Hmm.&lt;br /&gt;&lt;br /&gt;The departing guru showed me what they had so far, which was a system built in Visual Basic with an SQL database. First came the demo of the interactive module, a pure mockup with no substance behind it. Then he showed me the scanning and forms recognition tools in action. He printed out a form built using Word or Visio, scanned it back in, then opened the JPEG file in a manual training tool that came with the recognition software. Field by field he painfully showed the software where each field was, what its name should be, and whether it was numeric, or alpha, yadda yadda.&lt;br /&gt;&lt;br /&gt;Ouch. The process was slow and created a brittle bridge from form to application. Worse, these forms might be redesigned at any time leading up to trial commencement in response to concerns from external trial review panels and they can change during a trial in response to field experience. At any given time multiple versions of the same form could be in existence (trials at different sites do not start and stop together), so not only would developers be forever retraining the recognition and then modifying the software to know about new or changed fields, but they also would have to keep alive all the multiple versions of form definitions and match them to specific forms as they got scanned back in or opened for editing.&lt;br /&gt;&lt;br /&gt;I was already thinking about automating everything and this process was one that had to be automated. I asked the departing guru if the forms recognition software could be trained via an API instead of via the utility program he was using. He looked at me a moment and said, Yes, realizing I think that is what they should have done. &lt;span style="font-style: italic;"&gt;I &lt;/span&gt;realized he was leaving in part because he was just a systems guy at heart and this was one deadly application problem to undertake.&lt;br /&gt;&lt;br /&gt;To my friend's relief I agreed to give his vision a try. Now it was my turn, but I did not consider for a moment switching to Lisp. This was a serious business application and I knew my friend would never go for it. Nowadays with more experience that is exactly where I would have begun, back then I did not even consider fighting that fight.&lt;br /&gt;&lt;br /&gt;No problem. I had pulled off table-driven designs in the past using COBOL and the table-driven design was going to be the key to our success, not the language. Making the table thing work also meant we would want a custom language so we could express the table data easily.&lt;br /&gt;&lt;br /&gt;Back home, I looked up at my bookshelf for the manuals to various Lex/Yacc tools I had bought over the years. But I did not look for very long. I knew I could at least use Lisp to quickly prototype the language using a few clever macros, while Lex/Yacc were known to be bears to use --and I had only bought the tools, never really played with either in anger. So Lisp it would be to prototype the trial specification language.&lt;br /&gt;&lt;br /&gt;Then I noticed something, my latest hobby creation using Lisp and my cherished Cells hack: an &lt;a href="http://www.tilton-technology.com/Acrostic.html"&gt;interactive version&lt;/a&gt; of the New York Times Double-Acrostic puzzle. It had individual boxes for each letter like any good crossword and that is what we needed for the patient data! So I was halfway home, and sure enough after a few hours I was looking at a perfect mockup of the first page of the sample clinical trial we were using to build the software. And my mouth dropped open at what I saw.&lt;br /&gt;&lt;br /&gt;A blinking cursor. In the first character box on the page. I saw that and knew we would be using Lisp for the project. Hunh?&lt;br /&gt;&lt;br /&gt;Well, we had to print these forms out, train the forms recognition software, scan the forms back in, feed the scan image to the trained software, and then -- wait for it -- let the users make corrections to the data. And there it was, the blinking cursor waiting for my input. I had been so concerned first with getting the form laid out and ready for printing that I had forgotten that I had cannibalized the code from the crossword puzzle software.&lt;br /&gt;&lt;br /&gt;We're done! How famous are those last words? Anyway, my next step was to make sure this wonderful stuff running on my Macintosh under &lt;a href="http://www.digitool.com/"&gt;Digitool MCL&lt;/a&gt; would run on Windows NT, the planned deployment platform. I figured Lisp I could sell, but the Mac? In 1998? Not.&lt;br /&gt;&lt;br /&gt;So on my own dime I acquired an entry-level version of &lt;a href="http://www.franz.com/"&gt;AllegroCL&lt;/a&gt; and spent a few weeks porting everything to Windows and it was more of an OS port because Common Lisp is an ANSI standard with which vendors comply pretty well. When I saw everything working on Windows I called my friend, took a deep breath, and said I wanted to use Lisp.&lt;br /&gt;&lt;br /&gt;"OK," he said.&lt;br /&gt;"And an OODB," I said.&lt;br /&gt;"OK."&lt;br /&gt;&lt;br /&gt;Some fight. The OODB was AllegroStore, then the vendor's solution for persistent CLOS. (Now they push AllegroCache, a native solution where AStore was built atop the C++ OODB ObjectStore.)&lt;br /&gt;&lt;br /&gt;Why the OODB? I had noticed something while playing with the database design for the system: I missed objects. I had done some intense relational design back in the day and enjoyed it but by the time in question I had also done a ton of OO and I missed it in my schema design. Not only would AStore give me OO in my DB, it would do so in the form of persistent CLOS, meaning my persistent data would be very much like all my other application data. The whole problem of mapping from runtime data structures to the database -- something programmers have long taken for granted -- would go away.&lt;br /&gt;&lt;br /&gt;About a year later we had the whole thing working and I was about to take a working vacation traveling first to San Francisco for &lt;a href="http://www.alu.org/luv/99/photos/t-shirt.jpeg"&gt;LUGM '99&lt;/a&gt;, the annual Lisp meeting (here is &lt;a href="http://naggum.no/lugm-time.html"&gt;the best talk&lt;/a&gt;) and then on to Taiwan for two weeks of work and socializing with friends. I decided to use this time to tackle a performance problem that had reached "The Point of Being Dealt With". The solution I had in mind seemed like it would be fun (more famous last words) and nicely self-contained and not too onerous for a working holiday.&lt;br /&gt;&lt;br /&gt;Basically my approach to performance is not to worry about it until I have introduced enough nonsense that the application is running slow enough to hurt my productivity. Then it is time for what I call Speed Week, a true break from new development dedicated purely to making the system hum again. And we had reached that point.&lt;br /&gt;&lt;br /&gt;Otherwise the application was wonderful, just as planned. A trial form was specified using defform, defpage, defpanel, deffield, etc etc. From that single specification came beautifully typeset paper forms, the corresponding DB schema, the unrestricted business logic, the automatic training, scanning, and recognition, and screen forms for on-line editing of the data once scanned in.&lt;br /&gt;&lt;br /&gt;Life was good, but run-time instantiation of a form was a pig. It occurred to me that each time a page was instantiated the exact same layout rules were being invoked to calculate where all the text and input fields should fall. The forms author merely specified the content and simple layout such as rows and columns and Cell rules used fontmetrics to decide how big things were and then how to arrange them neatly. The author simply eyeballed the result and decided how many panels (semantically related groups of fields) would fit on a page. So coming straight from the source there was a load of working being done coming up with exactly the same values each time. Some timing runs showed this was where I had my performance problem.&lt;br /&gt;&lt;br /&gt;What to do? Sure, we could (and did!) memoize the results and then reuse the values when the same page was loaded a second time, or we could... and then my mouth dropped open again. The alternative (described soon) would let me handle the six hundred pound gorilla I have not mentioned.&lt;br /&gt;&lt;br /&gt;First I have to tell you about an overarching problem. One prime directive was that trial sites be fully functional even if they were off the network. Thin-client solutions need not apply. So we had to get client sites set up with information specific to all and only those trials they would be doing. And keep that information current as specifications changed during a trial. My six hundred pound gorilla was version control of the software and forms.&lt;br /&gt;&lt;br /&gt;Now here is the alternative. What if we instantiate a form in memory, let the cells compute the layout, and then traverse the form writing out a persistent mirror image of what we find, including computed layout coordinates? Business logic can be written out symbolically and read back in because thanks to Dr. McCarthy code is data. We avoid the redundant computations, but more importantly we now had a changed form specification as a second set of data instead of as a software release. Work on the original performance problem had serendipitously dispatched Kong, because now the replication scheme we would be doing &lt;span style="font-style: italic;"&gt;anyway &lt;/span&gt;would be moving not just trial data &lt;span style="font-style: italic;"&gt;in &lt;/span&gt;from the clinical sites but also the configuration data from the drug companies &lt;span style="font-style: italic;"&gt;out &lt;/span&gt;to the sites. We're done!&lt;br /&gt;&lt;br /&gt;If it works. The test of the concept was simple. I designed one of the forms using the trial specification DSL (the macros), compiled, loaded, instantiated, displayed, printed it, did some interactive data entry. Cool, it all works.&lt;br /&gt;&lt;br /&gt;Then I "compiled" the form as described above, writing everything out to the OODB. Then I ended my Lisp session to erase any knowledge of the original form source specification.&lt;br /&gt;&lt;br /&gt;Now I start a new Lisp session and do &lt;span style="font-style: italic;"&gt;not &lt;/span&gt;load the source code specifying the form. Using a second utility to read the form information back in from the database, I instantiate the form in memory. And it works the same as I had with the one instantiated from the original specifications. Life was good and about to get better.&lt;br /&gt;&lt;br /&gt;Round about now we had the whole thing working, by which I mean all the hard or interesting pieces had been solved and seen to run from form design to printing to capture and validation. Work remained, such as the partial replication hack, but the DB design had taken this requirement into account and was set up nicely to support such a beast. That in turn would let us toss off the workgroup requirement by which remote trial monitors hired by drug companies could keep an eye on the doctors. But then came a four-day Fourth of July and I decided to treat myself to some fun.&lt;br /&gt;&lt;br /&gt;For eighteen months we had been working with exactly one specific form from the sample trial. It occurred to me to see how powerful was my DSL, the mechanism by which eventually power users would be describing an arbitrary clinical drug trial to the generic trial manager application, and actually build out the remaining forms of the eighteen visit trial. The experiment would be compromised two ways.&lt;br /&gt;&lt;br /&gt;First, I would be the power user. Talk about cheating. But we understood the friendliness of the specification language would have to be developed over time as folks other than me came to grips with it, and also that those power users would have push-button access to software experts when they got stuck -- we were developing an in-house application, not a presentation authoring tool for the general public.&lt;br /&gt;&lt;br /&gt;The second compromise went the other way, making things harder. As I proceeded through the new forms I would be encountering specific layout requirements for the first time, and writing new implementation code as much as I would be simply designing the forms in power user mode. Regarding this, I imposed a constraint on myself: I would design the forms to match exactly the forms as they had been designed in Word, even though in reality one normally takes shortcuts and tells the user "you know, if you laid it out this way (which actually looks better) we would not have to change the layout code". But I wanted to put the principle to test that we had developed a general-purpose forms design language.&lt;br /&gt;&lt;br /&gt;What happened? It was a four day weekend and I worked hard all four days but the weather was great and I a good dose of Central Park each day skating and fruitlessly pursuing romance. (I liked to concentrate on new skaters because they cannot skate well enough to get away from me.) On the development side as predicted I spent at least half my time extending the framework to handle new layout requirements presented by different forms. But by the end of the weekend I was done with the entire trial. Yippee.&lt;br /&gt;&lt;br /&gt;I spent a day writing out the pseudo-code for the partial replication scheme and the other guy started on that while I started thinking about the workgroup aspect. It occurred to me that the mechanism for storing forms describing patient visits could be used for any coherent set of trial information, such as a monitor's so-called "data query" in which they did a sanity check on something that had passed validation but still looked wrong. The only difference with these forms compared to the trial data forms (already working) would be that they would not be printed and scanned, so... we're done!&lt;br /&gt;&lt;br /&gt;Talk about code re-use. Somewhere along the way I had accidentally created a 4GL in which one simply designed a screen form and went to work, the database work all done for you.&lt;br /&gt;&lt;br /&gt;Now I started working on the interface that would knit all this together. GUIs are insanely easy with my Cells hack. Downright fun, in fact. So much fun, so easy to do, and then so foolproof that I missed them almost immediately. The persistent CLOS database lacked Cells technology. Of course. It was just persistent data as stored by the AllegroStore ODB.&lt;br /&gt;&lt;br /&gt;But Cells at the time was implemented as a CLOS metaclass, and so was AllegroStore... no, you are kidding... multiple-inheritance at the metaclass level?! That and a little glue and... we're done! The GUI code now simply read the database and showed what it found to the user. When anything changed in the database, the display was updated automatically. (I always enjoy so much seeking out the Windows "Refresh view" menu item. Not!)&lt;br /&gt;&lt;br /&gt;For example, the status of form Visit #1 for Patient XYZ might be "Printed". Or -- since one business rule said forms should be printed and scanned in short order so the sytem could tell when forms had been lost -- it might say "Overdue for Scanning". So now the user looks around, finds the form, puts it in the sheet feeder of the scanner and hits the scan button. In a moment the user sees the status change to "Ready for Review".&lt;br /&gt;&lt;br /&gt;The beauty of having wired up the database with Cells is that the scanning/recognizing logic does not need to know that the user is staring at an "Overdue" indicator on the screen that no longer applies. Tech support will &lt;span style="font-style: italic;"&gt;not &lt;/span&gt;be fielding calls from confused users saying "I scanned it six times and it still says overdue!" The scanning logic simply does its job and writes to the database. The Cells wiring notices that certain GUI elements had been looking for this &lt;span style="font-style: italic;"&gt;specific &lt;/span&gt;information and automatically triggers a refresh. And as always with Cells, the GUI programmer did not write any special code to make this happen, they simply read that specific bit of the database. Cells machinery transparently recorded the dependency just as it automatically propagates any change.&lt;br /&gt;&lt;br /&gt;In the end we had taught Cells and the ODB a few kinds of tricks. It was possible for a dynamic slot of a (dynamic) GUI instance to depend on the persistent slot of a DB instance, or on the &lt;span style="font-style: italic;"&gt;population &lt;/span&gt;of a peristent class ("oh, look, a new data query just came in"). Persistent instances can have dynamic slots in AllegroStore and these could depend on persistent slots, and perhaps the scariest bit: persistent slots could depend on other persistent data. The database was alive!&lt;br /&gt;&lt;br /&gt;One change could ripple out to cause other change in the database. For example, "Overdue Form" was a persistent attribute calculated from the fact that a form had been printed but that it had not been scanned. If that status held for a day the database automatically grew a new persistent instance, an "Alert" instance visible to trial monitors who could intervene to see why the clinical site was not taking care of business. When the form got scanned, Cells logic caused the status to move up to "Scanned/ready for review" and the "Alert" instance got deleted. All in classic Cells declarative fashion: "an Alert exists if a document is overdue for one day" takes care of both creating and destroying the instance.&lt;br /&gt;&lt;br /&gt;I'll never forget a religious moment I had scanning forms so I could work on the interface's mechanism for correcting scanner or recognition errors. When I called up page two of some form all the fields were blank. I had never seen the scanner/recognition software completely miss a page, but a peek at the log file showed the page had indeed gone unrecognized. (We used 2-D barcodes to identify pages.) Stunned at this first ever failure (out of hundreds of trials) I just grabbed the second page, put it back in the sheet feeder and hit the scan button.&lt;br /&gt;&lt;br /&gt;The nice thing about the barcodes is that I could just do that, I did not have to tell the software "OK, now I am scanning page two of form 1 for patient XYZ." The barcode data was in fact nothing but the GUID we assigned to the page when creating it in the ODB, so the printed paper had object identity. :) The other neat thing here is what when instantiating a page we linked it to the version of the form template from which it was derived. This took care of the version control problem created by changing forms -- a scanned page was able to look in the database to find the template from which it was created and scan and open itself. Users never had to say what they were dropping into the sheet feeder or worry about the order. Back to my missing page...&lt;br /&gt;&lt;br /&gt;The scanner started whirring, the page went through, and then log diagnostics from the recognition process started zooming by (OK, this time we recognized the page, the last time was truly a fluke) and then even before it happened I realized (Omigod!) what was about to happen.&lt;br /&gt;&lt;br /&gt;I turned my eyes to the blank page still up on my screen and waited...Boom! The data appeared. Having wired the database to the screen, what happened was this: the recognition logic simply read the forms and wrote out the results as usual, updating each persistent form field with a value. The screen field widget had gotten its display value by reading that DB field. Cells told the screen field widget to "calculate" again its display value. It was different, so the Cell observer for the screen field generated an update event for the field. The application redrew the field in response to the update event.&lt;br /&gt;&lt;br /&gt;That was so cool to see happen.&lt;br /&gt;&lt;br /&gt;We're done! Literally. :( Eventually our tiny little operation was never able to persuade big pharma we could handle the grave responsibility of not screwing up trials, even though IBM itself loved our work and worked with us to pitch it to pharma. But that is another story.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-6996542634259171889?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/6996542634259171889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=6996542634259171889' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6996542634259171889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6996542634259171889'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/my-biggest-lisp-project.html' title='My Biggest Lisp Project'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-2688188888762985333</id><published>2008-03-08T00:19:00.004-05:00</published><updated>2008-03-08T02:25:54.062-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OpenLaszlo Cells dataflow FRP reactive programming'/><title type='text'>OpenLaszlo-Cells Smackdown 2008</title><content type='html'>Yes, I pointed this out before on c.l.lisp but there has to be some upside to senility and freely repeating myself is it: an OpenLaszlo introductory &lt;a href="http://weblog.openlaszlo.org/archives/2007/05/openlaszlo-4-programming-tutorial"&gt;video&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pretty far into the video, after some horrifyingly dirty language like "JDOM" which was all the more horrifying for the speaker clearly believing he was talking plainly (driving home my dinosaurosity and at the same time making me feel a whole lot better about it) we learn that OpenLaszlo includes as one bell amidst all the whistles...wait for it... dataflow! ta-dum!!! Pretty damn transparently, to boot.&lt;br /&gt;&lt;br /&gt;Meanwhile over in the comp.lang.lisp archives you'll find the author of the latest Common Lisp &lt;a href="http://www.gigamonkeys.com/book/"&gt;tome&lt;/a&gt; saying he cannot see the point of my equivalent &lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;Cells&lt;/a&gt; library and news of my invitation to &lt;a href="http://www.weitz.de/eclm2008/"&gt;ECLM 2008&lt;/a&gt; where I have been invited to unravel this profound mystery live and in color as if that will make any difference. &lt;br /&gt;&lt;br /&gt;Meanwhile back in the above video we discover the speaker presuming the advantages are obvious to his audience and offering no further explanation beyond pointing it out.&lt;br /&gt;&lt;br /&gt;Tilton's Law: Solve the Right Problem. Maybe I do not need to explain dataflow better, maybe I need a new audience.&lt;br /&gt;&lt;br /&gt;...sigh...&lt;br /&gt;&lt;br /&gt;ps. In the yobbos's defense, I just checked the Laszlo white paper on their product and they do not even mention dataflow explicitly. Just a couple of mentions of layout being "declarative". :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-2688188888762985333?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/2688188888762985333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=2688188888762985333' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2688188888762985333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/2688188888762985333'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/openlaszlo-cells-smackdown-2008.html' title='OpenLaszlo-Cells Smackdown 2008'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7232320569754796113</id><published>2008-03-05T19:49:00.005-05:00</published><updated>2008-03-06T00:03:21.092-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Macros Arc Common Lisp Python'/><title type='text'>My Nastiest Macro Ever?!</title><content type='html'>[WARNING: Do not try at home. The following code relies on extensions not included here. Plz visit the &lt;a href="http://arclanguage.org/item?id=4247"&gt;DSB&lt;/a&gt; thread for something you can play with]&lt;br /&gt;&lt;br /&gt;It all started because a Lisp/Arc noob "got it" when they saw how I used Lisp destructuring to make some code a little more readable. That in turn started with a &lt;a href="http://arclanguage.org/item?id=3968"&gt;challenge&lt;/a&gt; to improve some code to write an SQL query or something.&lt;br /&gt;&lt;br /&gt;I suggested rearranging the Lisp query spec to be friendlier to the consumer, then used Arc destructuring as the first improvement (and then greatly missed CL format):&lt;br /&gt;&lt;pre&gt;(let (tbl key . fields) *sql-template*&lt;br /&gt;   (prn (string "insert into " tbl&lt;br /&gt;           " ( " (let c nil&lt;br /&gt;                   (each (f . rest) fields ;; more destructuring&lt;br /&gt;                     (when c (= c (string c ", ")))&lt;br /&gt;                     (= c (string c f)))&lt;br /&gt;                   c)&lt;br /&gt;          ", " (car key)&lt;br /&gt;          " ) values ( "&lt;br /&gt;          (let c nil&lt;br /&gt;            (each (f . rest) fields&lt;br /&gt;              (when c (= c (string c ", ")))&lt;br /&gt;              (= c (string c ":" f)))&lt;br /&gt;            c)&lt;br /&gt;          ", " (last key) ".nextVal"&lt;br /&gt;          " ) returning " (car key) " into " (string ":" (car key)))))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When the "got it" came in, I decided to dust off my lite version of CL's destructuring-bind (actually done to implement a CL-style defun for Arc since its DEF has only optional args) and really give the Arcers an eyeful. &lt;br /&gt;&lt;br /&gt;The functionality we are after, by example:&lt;br /&gt;&lt;pre&gt;(let data (list 1 2 7 nil 'p 5)&lt;br /&gt;  (dsb (x y &amp;o (a (+ y 1)) (z 4) &amp;k (p 98) (q (+ a 1))) data&lt;br /&gt;    ;; we want to see identical pairs, cuz next I&lt;br /&gt;    ;; print first a variables runtime binding&lt;br /&gt;    ;; and then its expected value&lt;br /&gt;    (prs "args" x 1 y a 7 z nil p 5 q 8)&lt;br /&gt;    (prn)))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above should produce "args 1 1 2 2 7 7 nil nil 5 5 8 8". Yes, I apologized to the Arc forum for my lame test "utility". Anyway, here is what I came up with, and even though I have written well over five hundred macros this one just might be the most mind-bending I have done. &lt;br /&gt;&lt;br /&gt;First, the final form (probably still buggy!):&lt;br /&gt;&lt;pre&gt;(mac dsb (params data . body)&lt;br /&gt;  (w/uniq (tree kvs)&lt;br /&gt;    `(withs (,tree ,data&lt;br /&gt;              ,@(with (reqs nil key? nil opt? nil keys nil opts nil)&lt;br /&gt;                  (each p params&lt;br /&gt;                    (if&lt;br /&gt;                        (is p '&amp;o) (do (assert (no opt?) "Duplicate &amp;o:" ',params)&lt;br /&gt;                                       (assert (no key?) "&amp;k cannot precede &amp;o:" ',params)&lt;br /&gt;                                     (= opt? t))&lt;br /&gt;                      (is p '&amp;k) (do (assert (no key?) "Duplicate &amp;k:" ',params)&lt;br /&gt;                                     (= key? t))&lt;br /&gt;                   key? (push-end p keys)&lt;br /&gt;                   opt? (push-end p opts)&lt;br /&gt;                   (do (assert (~acons p) "Reqd parameters need not be defaulted:" p)&lt;br /&gt;                       (push-end p reqs))))&lt;br /&gt;                  (with (n -1)&lt;br /&gt;                    (+ (mappend [list _ `(nth ,(++ n) ,tree)] reqs)&lt;br /&gt;                      (mappend [list (carif _) `(if (&lt; ,(++ n) (len ,tree))&lt;br /&gt;                                                    (nth ,n ,tree)&lt;br /&gt;                                                  ,(cadrif _))] opts)&lt;br /&gt;                      `(,kvs (pair (nthcdr ,(++ n) ,tree)))&lt;br /&gt;                      (mappend [list (carif _)&lt;br /&gt;                                 `(aif (member',(carif _) ,kvs)&lt;br /&gt;                                    (cadr it)&lt;br /&gt;                                    ,(cadrif _))] keys)))))&lt;br /&gt;       ,@body)))&lt;/pre&gt;&lt;br /&gt;That hurt. But why is it possibly the wildest one I have ever written? It certainly is not the longest. Let me put it this way: macros are always tricky but most of them only go up to ten; this one goes to eleven. &lt;br /&gt;&lt;br /&gt;First, let's look at a simpler example:&lt;br /&gt;&lt;pre&gt;(dsb (x &amp;k (y (++ x))) (list 1 'y 2)&lt;br /&gt;   (list x y))&lt;/pre&gt;&lt;br /&gt;...and the desired expansion:&lt;br /&gt;&lt;pre&gt;(withs (u1 (list 1 2)&lt;br /&gt;         x (nth 0 u1)&lt;br /&gt;         (u2 (pair (nthcdr 2 u1)))&lt;br /&gt;         y (bif (assoc 'y u2) (cadr it) (++ x)))&lt;br /&gt;  (list x y))&lt;/pre&gt;&lt;br /&gt;Come to think of it, next time I have to write a macro this tricky I just might write out the expansion I have in mind rather than try to hold it in my imagination as I code. Lesson learned, although macros normally arise after we have indeed written several long versions and &lt;i&gt;then&lt;/i&gt; decide to write a macro, so we do have expansions to stare at. Anyway...&lt;br /&gt;&lt;br /&gt;Macro writing does present a challenge in all but the simplest token-replacing cases: while writing the macro we are working in two different times at once, macro-expansion time and run-time. I am writing macro code M (to run at macro-expansion time) whose input is source code S and whose output is code R that will Actually Run &lt;i&gt;at run-time&lt;/i&gt;. As the macro author, I start a macro function in mindset M, then use a backquote to start specifying code in mindset R, then use the unquoting comma to jump back to mindset M. It is as if my time machine went haywire and I am experiencing now and the future on alternate blinks of the eye.&lt;br /&gt;&lt;br /&gt;When this becomes second nature, btw, you can add Lisp to your resume.&lt;br /&gt;&lt;br /&gt;So why is this example worse than usual? How does it go to eleven? Look at the binding of U2 (which for the cognoscenti is my fakery of the unique symbol uniq (CL's gensym) would produce). Omigod! The runtime code R is finishing the job of parsing the list being destructured by taking arguments beyond the last optional position and building them into an a-list to be read by the value forms of each keyword, themselves doing more parsing to decide if a runtime value was supplied or if they should use &lt;gasp!&gt; the &lt;i&gt;form&lt;/i&gt; (if any!!!) specified as the default in the parameter list!!! &lt;br /&gt;&lt;br /&gt;Aaaaaargghh!!! Maybe this one goes to twelve. I observed on the Arc forum while describing all this that it was a good thing I had written the macro before thinking about it. But there we were, so before closing the thread I decided to mention some simple macro-writing tips:&lt;br /&gt;&lt;br /&gt;1. The nice thing about CL-style and now Arc-style macros is that they are just like any other code we write, so we can debug them the same way, e.g, by placing print statements in the M code, if you recall my naming convention. This will be a mind-bender at first, or it was for me anywho. &lt;br /&gt;&lt;br /&gt;2. If when you test a macro it dies on the compile of a usage (not the run) your bug is in the M code, not the produced runtime R code. Let's go into some detail:&lt;br /&gt;&lt;br /&gt;I can write a macro and have that not compile:&lt;br /&gt;&lt;pre&gt;(mac surprise! (f1 f2)&lt;br /&gt;      `(do1 ,f1, f2, ,f3))&lt;/pre&gt;&lt;br /&gt;... because &lt;i&gt;f3&lt;/i&gt; is undefined. Duh. Easy enough to nail those. Once I fix the macro:&lt;br /&gt;&lt;pre&gt;(mac surprise! (f1 f2)&lt;br /&gt;      `(do1 ,f1, (/ ,f2 0))&lt;/pre&gt;&lt;br /&gt;...I can try it out and come to grief on a reasonable looking usage because the macro generates buggy code:&lt;br /&gt;&lt;pre&gt;(surprise! 10 11)&lt;/pre&gt;&lt;br /&gt;...which should produce a division by zero error by expanding to:&lt;br /&gt;&lt;pre&gt;(do1 10 (/ 11 0))&lt;/pre&gt;&lt;br /&gt;But there is another way to mess up! Isn't this fun! You can have macro code M that &lt;i&gt;compiles&lt;/i&gt; OK but has a bug of its own that will be encountered while the M code is running (to produce the R code for the compiler):&lt;br /&gt;&lt;pre&gt;(mac surprise! (f1 f2)&lt;br /&gt;      (let x (len f2) ;; golly I hope f2 is a proper list&lt;br /&gt;        `(do1 ,f1, (/ ,f2 0))&lt;/pre&gt;&lt;br /&gt;That version of the macro &lt;i&gt;compiles&lt;/i&gt;, but now:&lt;br /&gt;&lt;pre&gt;(def three-two-one ()&lt;br /&gt;         (surprise! 10 11)&lt;/pre&gt;&lt;br /&gt;...should &lt;i&gt;not&lt;/i&gt; compile, Arc should squawk during compilation of three-two-one about 11 not being a proper list.&lt;br /&gt;&lt;br /&gt;In summary, when and how a macro usage goes South tells you in which of these many ways possible you have screwed up. Until you develop an instinct for that, this will help:&lt;br /&gt;&lt;br /&gt;2. Once your macro itself compiles (not a use thereof), use &lt;i&gt;macex&lt;/i&gt; to preview and debug the R code your macro will pass on to the compiler:&lt;br /&gt;&lt;pre&gt;(prn (macex '(surprise! 10 11)))&lt;/pre&gt;&lt;br /&gt;The above may fail if, as we discussed, you have a runtime bug in your macro expansion code M. If you are developing a macro and testing it in your application and get confused as to when the wheels are coming off, take a step back and cut-and-paste the failing usage into the above, not forgetting the quote.&lt;br /&gt;&lt;br /&gt;This by the way is a helpful reminder that macros eat symbolic source code, not text strings, and not runtime values, by which latter I mean this next bit should work even though the variables hi and mom do not exist -- at this point again it is all just symbols:&lt;br /&gt;&lt;pre&gt;(prn (macex '(surprise! hi mom)))&lt;/pre&gt;&lt;br /&gt;Use macex also when you simply do not get the behavior you want, when a macro usage compiles and runs but gives the wrong result. It might be that a macro expansion is writing bad code, and it is easier to see in the expanded form of an actual usage than it is staring at the slicing-dicing of a macro function. Come to think of it, we can see that with this example:&lt;br /&gt;&lt;pre&gt;(surprise! 1 2)&lt;br /&gt; -&gt; 1&lt;/pre&gt;&lt;br /&gt;Puzzled as to why we get 1 instead of 2, we use &lt;i&gt;macex&lt;/i&gt;:&lt;br /&gt;&lt;pre&gt;(macex '(surprise! 1 2))&lt;br /&gt;-&gt;(do1 1 2)&lt;/pre&gt;&lt;br /&gt;Aha! That is supposed to be &lt;i&gt;do&lt;/i&gt;! The &lt;i&gt;do1&lt;/i&gt; is left over from an earlier version where it made sense. Something like that.&lt;br /&gt;&lt;br /&gt;3. Divide and Conquer I: first I did DSB just with required params, then with optional params, then with keyword params, then with default values, then with computed default values, yadda yadda yadda, nothing new in this tip but there ya go.&lt;br /&gt;&lt;br /&gt;4. Divide and Conquer II: This gets back to tip #1: macros are like any other code, meaning we can break complex chunks out into standalone functions to be tested separately. See that little state machine at the beginning of DSB that parses the parameter list? That is a nice little standalone chunk with a big job to do, let's give it its own home:&lt;br /&gt;&lt;pre&gt;(def dsb-params-parse (params)&lt;br /&gt;  (with (reqs nil key? nil opt? nil keys nil opts nil)&lt;br /&gt;    (each p params&lt;br /&gt;      (if&lt;br /&gt;          (is p '&amp;o) (do (assert (no opt?) "Duplicate &amp;o:" ',params)&lt;br /&gt;                         (assert (no key?) "&amp;k cannot precede &amp;o:" ',params)&lt;br /&gt;                       (= opt? t))&lt;br /&gt;        (is p '&amp;k) (do (assert (no key?) "Duplicate &amp;k:" ',params)&lt;br /&gt;                       (= key? t))&lt;br /&gt;        key? (push-end p keys)&lt;br /&gt;        opt? (push-end p opts)&lt;br /&gt;        (do (assert (~acons p) "Reqd parameters need not be defaulted:" p)&lt;br /&gt;            (push-end p reqs))))&lt;br /&gt;    (list reqs opts keys)))&lt;/pre&gt;&lt;br /&gt;And test:&lt;br /&gt;&lt;pre&gt;(prn (dsb-params-parse '(x y &amp;o (a (+ y 1)) z &amp;k (p 98) (q (+ a 1)))))&lt;br /&gt;-&gt; ((x y)((a (+ y 1)) z)((p 98) (q (+ a 1))))&lt;/pre&gt;&lt;br /&gt;Awesome. Now look at DSB:&lt;br /&gt;&lt;pre&gt;(mac dsb (params data . body)&lt;br /&gt;  (w/uniq (tree kvs)&lt;br /&gt;    `(withs (,tree ,data&lt;br /&gt;              ,@(let (reqs opts keys) (dsb-params-parse params)&lt;br /&gt;                  (with (n -1)&lt;br /&gt;                    (+ (mappend [list _ `(nth ,(++ n) ,tree)] reqs)&lt;br /&gt;                      (mappend [list (carif _) `(if (&lt; ,(++ n) (len ,tree))&lt;br /&gt;                                                    (nth ,n ,tree)&lt;br /&gt;                                                  ,(cadrif _))] opts)&lt;br /&gt;                      `(,kvs (pair (nthcdr ,(++ n) ,tree)))&lt;br /&gt;                      (mappend [list (carif _)&lt;br /&gt;                                 `(aif (assoc ',(carif _) ,kvs)&lt;br /&gt;                                    (cadr it)&lt;br /&gt;                                    ,(cadrif _))] keys)))))&lt;br /&gt;       ,@body)))&lt;/pre&gt;&lt;br /&gt;Sweet! Now we can give Arc a Cl-style &lt;i&gt;defun&lt;/i&gt; if like me we are fond of them:&lt;br /&gt;&lt;pre&gt;(mac defun (name params . body)&lt;br /&gt;  (w/uniq (args)&lt;br /&gt;    `(def ,name ,args&lt;br /&gt;       (dsb ,params ,args ,@body))))&lt;/pre&gt;&lt;br /&gt;Applied, we create the CL poster boy for mixed optional and keyword args:&lt;br /&gt;&lt;pre&gt;(defun read-from-string (s &amp;o eoferr? eofval &amp;k start end keep-whitey?)&lt;br /&gt;        ....)&lt;/pre&gt;&lt;br /&gt;Too easy? :) &lt;br /&gt;&lt;br /&gt;Somewhere out there some Pythonista believes the sky is falling, that I have forked Arc, and that no one will ever be able to read my code. (a) They are wrong, and (b) this is a wonderfully extreme example in which we really are (yes!) extending the language. If they do not like this, maybe they will like some of the simpler transformations &lt;i&gt;mac&lt;/i&gt; allows.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7232320569754796113?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7232320569754796113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7232320569754796113' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7232320569754796113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7232320569754796113'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/03/my-nastiest-macro-ever.html' title='My Nastiest Macro Ever?!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7128429749128353129</id><published>2008-02-28T04:35:00.008-05:00</published><updated>2008-03-03T16:29:18.393-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp Macros Python C'/><title type='text'>Macro-ro-ro Your Code Gently Down the Screen...</title><content type='html'>Sorry about the title but I just feel a little silly having to explain why macros rock so hard when the C preprocessor has been doing them almost as long as Lisp. It just ain't that hard an idea to get. It seems to me anyone writing a sufficient amount of code will notice recurring patterns not susceptible to attack by encapsulation in a function. Consider OpenGL.&lt;br /&gt;&lt;br /&gt;With OpenGL, certain things have to happen between a glBegin and a glEnd, and certaing things are not allowed between a glBegin/End pair. One of them being a second glBegin. The poor OpenGL programmer now has one more thing to worry about, and tedious boilerplate to write like a robot (in this case just a one-liner glEnd() but try not to lose the big picture principle, OK Sparky? This is a deliberately simple example). Is there any way to alleviate this drudgery?&lt;br /&gt;&lt;br /&gt;Well, quite a few statements will be squeezed of between glBegin and glEnd, cuz OpenGL is no joy to code. We can write a function called do-between-begin-end and pass it a first class function (unless your BDFL does not see the need), but then (in CL) we end up with:&lt;br /&gt;&lt;pre&gt;(do-between-begin-end&lt;br /&gt;     (lambda ()&lt;br /&gt;        ...your dozen lines of code here...&lt;br /&gt;        ))&lt;/pre&gt;&lt;br /&gt;Not the end of the world, but remember, I am just warming up. These macro posts will go on forever. Anyway, with a macro we lose the lambda speed bump:&lt;br /&gt;&lt;pre&gt;(with-gl-begun ()&lt;br /&gt;...your dozen lines here...)&lt;/pre&gt;&lt;br /&gt;What's with the ()? Well, truth is glBegin takes a parameter that says what we are beginning (line strip? triangles? quads?) so I kinda lied, the contrast should be...&lt;br /&gt;&lt;pre&gt;(do-between-begin-end gl_quads&lt;br /&gt;     (lambda ()&lt;br /&gt;        ...your dozen lines of code here...))&lt;/pre&gt;&lt;br /&gt;and:&lt;br /&gt;&lt;pre&gt;(with-gl-begun (gl_quads)&lt;br /&gt;     ...your dozen lines here...)&lt;/pre&gt;&lt;br /&gt;So, yeah, I can write do-between-gl-begin-end and never worry about begin and end again, but I am stuck with a little line noise there.&lt;br /&gt;&lt;br /&gt;If we look at a classic example of how Lisp macros hide boilerplate, we see this more egregious after/before pair:&lt;br /&gt;&lt;pre&gt;(with-open-file (f "xxx")&lt;br /&gt;   (print "line 1 of xxx:")&lt;br /&gt;   (print (read-line f)))&lt;/pre&gt;&lt;br /&gt;Versus what I have to write without with-open-file:&lt;br /&gt;&lt;pre&gt;(let ((f (open "xxx"))&lt;br /&gt;     (success nil))&lt;br /&gt;    (unwind-protect&lt;br /&gt;      (multiple-value-prog1&lt;br /&gt;        (progn&lt;br /&gt;          (print "line 1 of xxx follows:")&lt;br /&gt;          (print (read-line f))&lt;br /&gt;          (close f))&lt;br /&gt;        (setf success t))&lt;br /&gt; (unless success&lt;br /&gt;   (close f :abort t))))&lt;/pre&gt;&lt;br /&gt;The odd thing is that Pythonistas reject macros while fervently embracing tidy code -- and Python code &lt;i&gt;does&lt;/i&gt; look very clean -- but all we are doing with macros (so far) is making code neater. Well, no, we are also releaving the programmer of drudgery and making the code more reliable by automating the insertion of necessary boilerplate such as error checking.&lt;br /&gt;&lt;br /&gt;Let's turn now to a dead simple hiding of boilerplate, Paul Graham's AIF swiped from the inestimable &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;(defmacro aif (test-form then-form &amp;amp;optional else-form)&lt;br /&gt;    ‘(let ((it ,test-form))&lt;br /&gt;        (if it ,then-form ,else-form)))&lt;/pre&gt;&lt;br /&gt;The alternative is:&lt;br /&gt;&lt;pre&gt;(let ((temp (big-long-fn a b c)))&lt;br /&gt;    (if temp&lt;br /&gt;       (handle-it temp x y)&lt;br /&gt;      (do-something-else a x))&lt;/pre&gt;&lt;br /&gt;By the way, if you do not like Graham's anaphoric thing (using "it" as the implicit temporary variable), use my BIF which takes a mnemonic for the intermediate result:&lt;br /&gt;&lt;pre&gt;(defmacro bif (bindvar boundform yup &amp;amp;optional nope)&lt;br /&gt;  `(let ((,bindvar ,boundform))&lt;br /&gt;     (if ,bindvar ,yup ,nope)))&lt;/pre&gt;&lt;br /&gt;And then a more realistic use:&lt;br /&gt;&lt;pre&gt;(bif sol (math-problem-solution prb mx)&lt;br /&gt;  (display-solution sol)&lt;br /&gt; (tell-user "No can do!"))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this just my first offering on macros I have discussed only the advantages of automatically generating boilerplate. There is much more to come, but I would like to close by reiterating my befuddlement that this even needs explaining, and in the context of the C preprocessor precedent mentioned above:&lt;br /&gt;&lt;br /&gt;I just dug into the old C version of my Algebra software for just one out of hundreds of macros, one which iterates over the children of a node (a custom tree struct in my application) in something akin to the C "for" statement:&lt;br /&gt;&lt;pre&gt;#define fork(PAR,TMP_KID,NXT_KID)      \&lt;br /&gt;    for ( NXT_KID = (TMP_KID = firstk( PAR))? nexts(TMP_KID):NIL \&lt;br /&gt;     ; TMP_KID  \&lt;br /&gt;     ; NXT_KID = (TMP_KID = NXT_KID)? nexts(TMP_KID):NIL)&lt;/pre&gt;&lt;br /&gt;The crucial thing to note is that this macro is meant to allow children to be unlinked from the parent during the traversal, so it is necessary to capture the next child after the current child before processing the current child, because parents only see their first and last child as I had things arranged. &lt;br /&gt;&lt;br /&gt;So now I could write code like this (instead of something like the macro definition above):&lt;br /&gt;&lt;pre&gt;fork( usg, tusg, nusg) {&lt;br /&gt;    kidDetach( tusg); ;; losing the "next child" link&lt;br /&gt;    xInsKid( tpar, pusg, tusg);&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;Next time we will do something even jazzier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7128429749128353129?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7128429749128353129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7128429749128353129' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7128429749128353129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7128429749128353129'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/macro-ro-ro-your-code-gently-down-page.html' title='Macro-ro-ro Your Code Gently Down the Screen...'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-6101353996848059915</id><published>2008-02-26T14:10:00.002-05:00</published><updated>2008-02-27T00:25:10.267-05:00</updated><title type='text'>Ooh! Ooh! My turn! Why Lisp?</title><content type='html'>Brace yourself. The first reason you should be using Lisp is a non-reason, an answer to an objection, a negation, a let-down: Lisp is just an ordinary programming language.&lt;br /&gt;&lt;br /&gt;I'll wait while you pick yourself off the floor. What a terrible place to start! But it must be said. It is the first hurdle on the road to Lisp. Xenophobia never feels like fear of the strange, it feels like dislike. But one of the best young Lispers to show up at a &lt;a href="http://www.lispnyc.org/home.clp"&gt;Lisp-NYC&lt;/a&gt; meeting sat down, ordered a beer, and was smart enough to make it his first question: Can you use Lisp for conventional programming? Can it read a database? Can it run a GUI?&lt;br /&gt;&lt;br /&gt;Yep.&lt;br /&gt;&lt;br /&gt;Lisp at one level of understanding is just a normal high level programming language. Those parentheses &lt;span style="font-style: italic;"&gt;look&lt;/span&gt; quite different but constitute only a superficial difference from the conventional chicken scratch syntax of semi-colons, braces, full stops, and brackets.  When a conventional programmer sits down to program Lisp, they feel quickly at home: Lisp is just another 3GL.&lt;br /&gt;&lt;br /&gt;I feel terrible about this. I am supposed to be up on a soapbox preaching eternal salvation and ecstasies glorious and unknown and we will touch on that below but in the end your correspondent is just a simple application programmer and if you check &lt;a href="http://smuglispweeny.blogspot.com/2008/02/my-road-to-lisp.html"&gt;my Road to Lisp&lt;/a&gt; you will discover that I (re)discovered Lisp just to find an easier way to create &lt;a href="http://www.theoryyalgebra.com/"&gt;educational math software&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Lispers are accused of religous fanaticism and zealotry -- nope, our enthusiasm is all about getting applications built faster with less pain. Which brings me to the bad news: the next reason I have to offer for using Lisp is almost as boring as the first: Lisp is mature. Turns fifty or so in 2008. In 1994 when it was old enough to be President of the United States it got an &lt;a href="http://www.lisp.org/table/references.htm"&gt;ANSI Standard&lt;/a&gt;. How stable can you get?&lt;br /&gt;&lt;br /&gt;So far we have ordinary, old, and codified and I am losing my audience. Send in the clowns!&lt;br /&gt;&lt;br /&gt;Fine, a little pizazz: it ain't just old. The old translates to polish. Lisp did not begin with a standard and it did not begin as a single-implementation BDFL strangulation such as Python or Perl or Ruby. It began as...an experiment?&lt;br /&gt;&lt;br /&gt;Two score and ten years ago our foregeeks started from the simple idea that code and data were one and began evolving a huge tool chest of HLL functionality spread across several competing dialects. For some reason they took the engineering so seriously that whenever a nooby picks up one of these tools surprise! surprise! it turns out to work precisely the way they need it to. It seems like magic but it is not. The magic is just a long history of use and careful refinement by very good engineers and was possible precisely because there was no&lt;span style="font-style: italic;"&gt;&lt;/span&gt; standard and there was no &lt;span style="font-style: italic;"&gt;&lt;/span&gt; BDFL.&lt;br /&gt;&lt;br /&gt;Back to the yawns: most Common Lisp implementations are native compiled. Yeah, yeah, I know, computers are fast and we are all doing Web apps where network latency decides all but I work on a desktop interactive expert system that needs all the horsepower it can get and to tell you the truth when building something like that more horsepower makes more better features possible so isn't it nice to compile down to the metal?&lt;br /&gt;&lt;br /&gt;More yawns: ephemeral GC, the best OO model you can imagine, multiple implementations to choose from including free ones.... hey, even I am getting bored. But my Road also reveals that I stumbled onto this staid dependable workhorse only after squandering mucho dollars and hours on half-baked gleams-in-the-eye programming tools that promised a world of productivity and delivered only reboots. At which point boring looks pretty damn exciting.&lt;br /&gt;&lt;br /&gt;Left as an exercise is connecting the stable/standard/refined dot with other dots of dynamic interactive languages still emerging from sea and periodically burying their installed bases in volcanic ash. Can you scream Perl 6? Sher ya can. Has Guido finally axed first-class functions yet? It is fun watching languages evolve, but if you will excuse me I really &lt;span style="font-style: italic;"&gt;do &lt;/span&gt;have an application to get out.&lt;br /&gt;&lt;br /&gt;With the dull stuff out of the way we can indulge at long last in some Why Lisp? fireworks.&lt;br /&gt;&lt;br /&gt;We'll build slowly, starting with Lisp being interactive, dynamic, reflective, functional, compiled, mature, standardized, has a vast array of library functions and data structures (including the wonderful and ubiquitous list), multiple value return, special variables, CLOS (including multiple inheritance and multi-methods), the &lt;a href="http://www.lisp.org/mop/index.html"&gt;MOP&lt;/a&gt;, first-class functions and omigod! closures, destructuring-bind, LOOP, lexical scope, untyped variables, typed data, object identity for everything but numbers and characters and now repeat a few of those things a few times to make clear how helpful they are to getting applications built, such as the vast toolchest. Gasp.&lt;br /&gt;&lt;br /&gt;I call that starting slowly because everything above can be found in some language. It is wonderful that only Common Lisp has them all, but is there anything that really sets Lisp off? Is there some protein that cannot be mimicked by other invading dynamic language organisms, some shibboleth their tongues cannot form?&lt;br /&gt;&lt;br /&gt;More prosaically, is there some quality those languages cannot copy without becoming Lisp?&lt;br /&gt;&lt;br /&gt;At &lt;a href="http://www.international-lisp-conference.org/2002/index.html"&gt;ILC 2002&lt;/a&gt; former Lisp giant now Python advocate Peter Norvig was for some reason allowed to give the keynote address like Martin Luther leading Easter Sunday mass at the Vatican &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; pitching Protestantism because in his talk Peter bravely repeated his &lt;a href="http://norvig.com/python-lisp.html"&gt;claim&lt;/a&gt; that Python is a Lisp.&lt;br /&gt;&lt;br /&gt;When he finished Peter took questions and to my surprise called first on the rumpled old guy who had wandered in just before the talk began and eased himself into a chair just across the aisle from me and a few rows up.&lt;br /&gt;&lt;br /&gt;This guy had wild white hair and a scraggly white beard and looked hopelessly lost as if he had gotten separated from the tour group and wandered in mostly to rest his feet and just a little to see what we were all up to. My first thought was that he would be terribly disappointed by our bizarre topic and my second thought was that he would be about the right age, Stanford is just down the road, I think he is still at Stanford -- could it be?&lt;br /&gt;&lt;br /&gt;"Yes, John?" Peter said.&lt;br /&gt;&lt;br /&gt;I won't pretend to remember Lisp inventor &lt;a href="http://www-formal.stanford.edu/jmc/"&gt;John McCarthy&lt;/a&gt;'s exact words which is odd because there were only about ten but he simply asked if Python could gracefully manipulate Python code as data.&lt;br /&gt;&lt;br /&gt;"No, John, it can't," said Peter and nothing more, graciously assenting to the professor's critique, and McCarthy said no more though Peter waited a moment to see if he would and in the silence a thousand words were said.&lt;br /&gt;&lt;br /&gt;Come to think of it...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-6101353996848059915?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/6101353996848059915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=6101353996848059915' title='47 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6101353996848059915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/6101353996848059915'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/ooh-ooh-my-turn-why-lisp.html' title='Ooh! Ooh! My turn! Why Lisp?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>47</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-397035100861529645</id><published>2008-02-18T20:54:00.004-05:00</published><updated>2008-02-18T21:43:22.078-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dataflow'/><category scheme='http://www.blogger.com/atom/ns#' term='Functional reactive programming'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='Cells'/><title type='text'>Arc!Cells: It's Alive!!!</title><content type='html'>In the &lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;Cells Manifesto&lt;/a&gt; I explained what all the Cells hoopla was about, including the vast array of other people doing the same thing only not as well as His Kennyness.&lt;br /&gt;&lt;br /&gt;In the &lt;a href="http://smuglispweeny.blogspot.com/2008/02/arc-cells-baby-steps_14.html"&gt;Baby Steps&lt;/a&gt; article we saw a primitive exploration of the mere beginnings of a partial implementation.&lt;br /&gt;&lt;br /&gt;Well I am through kidding around! Below the fold you will find what should be standalone code for a solid Arc implementation (albeit not as fully splediferous as The Real (Common Lisp) Deal) of vanilla Cells. Also available from &lt;a href="http://common-lisp.net/cgi-bin/viewcvs.cgi/arccells/arccells-its-alive.arc?rev=1.1&amp;root=cells&amp;view=log"&gt;CVS&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The furnace example at the end will (a) provoke even more nutty ads for furnace installations (sigh) and provide a rough idea of the magic: make one state change and like so many dominoes other state change follows as effect follows cause, with user-defined observer callbacks invoked so our virtual models can act on the world outside the model, all under a declarative paradigm the academics call &lt;a href="http://en.wikipedia.org/wiki/Reactive_programming"&gt;reactive programming&lt;/a&gt; because a better name like &lt;a href="http://en.wikipedia.org/wiki/Dataflow"&gt;dataflow&lt;/a&gt; would not make them sound so... I digress.&lt;br /&gt;&lt;br /&gt;Enjoy. Arc code enhancements always welcome, especially where I have reinvented built-in Arc constructs.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;;; - - - - - - - - - - - - -  cut here - - - - - - - - - - - - - - &lt;br /&gt;;;&lt;br /&gt;;; copyright 2008 by Kenny Tilton&lt;br /&gt;;;&lt;br /&gt;;; License: MIT Open Source&lt;br /&gt;;;&lt;br /&gt;;;&lt;br /&gt;&lt;br /&gt;;;; --- detritus ------------&lt;br /&gt;;;;&lt;br /&gt;&lt;br /&gt;(def prt args&lt;br /&gt;  ; why on earth does prn run the output together?&lt;br /&gt;  (apply prs args)&lt;br /&gt;  (prn))&lt;br /&gt;&lt;br /&gt;(def tablemap (table fn)&lt;br /&gt;  ; fns are always huge and then a tiny little table ref just hangs off the end&lt;br /&gt;  (maptable fn table)&lt;br /&gt;  table)&lt;br /&gt;&lt;br /&gt;(def cadrif (x) (when (acons x) (cadr x)))&lt;br /&gt;&lt;br /&gt;(mac withs* (parms . body)&lt;br /&gt;  ; faux dynamic binding&lt;br /&gt;  (let uparms (map1 [cons (uniq) _] (pair parms))&lt;br /&gt;    `(do ,@(map1 (fn ((save curr val))&lt;br /&gt;                   `(= ,save ,curr ,curr ,val)) uparms)&lt;br /&gt;       (do1&lt;br /&gt;           (do ,@body)&lt;br /&gt;         ,@(map1 (fn ((save curr val))&lt;br /&gt;                   `(= ,curr ,save)) uparms)))))&lt;br /&gt;&lt;br /&gt;;;; -------------------- Cells ----------------------&lt;br /&gt;;;;&lt;br /&gt;;;;  A partial implementation of the Cells Manifesto:&lt;br /&gt;;;;      http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html&lt;br /&gt;;;;   &lt;br /&gt;;;; --- globals --------------------&lt;br /&gt;&lt;br /&gt;(= datapulse* 0) ;; "clock" used to ensure synchronization/data integrity&lt;br /&gt;(= caller* nil) ;; cell whose rule is currently running, if any&lt;br /&gt;(= mds* (table)) ;; model dictionary&lt;br /&gt;(= obs* (table)) ;; global "observer" dictionary&lt;br /&gt;&lt;br /&gt;;;; --- md -&gt; modelling ----------------------------------------&lt;br /&gt;&lt;br /&gt;(mac defmd ((type-name (o includes)&lt;br /&gt;              (o pfx (string type-name "-")))&lt;br /&gt;            . slot-defs)&lt;br /&gt;  `(do&lt;br /&gt;       (deftem (,type-name ,@includes)&lt;br /&gt;           ctype ',type-name&lt;br /&gt;         cells nil&lt;br /&gt;         ,@(mappend (fn (sd) (list (carif sd)(cadrif sd))) slot-defs))&lt;br /&gt;       ; define readers&lt;br /&gt;       ,@(map (fn (sd)&lt;br /&gt;                `(def ,(coerce (+ (string pfx) (string sd)) 'sym) (i)&lt;br /&gt;                   (slot-value i ',sd)))&lt;br /&gt;           (map carif slot-defs))&lt;br /&gt;     ; define writers&lt;br /&gt;     ,@(map (fn (sd)&lt;br /&gt;              `(def ,(coerce (+ "set-" (string pfx) (string sd)) 'sym) (i v)&lt;br /&gt;                 (set-slot-value i ',sd v)))&lt;br /&gt;         (map carif slot-defs))))&lt;br /&gt;&lt;br /&gt;;;; --- model initialization&lt;br /&gt;&lt;br /&gt;(def to-be (i)&lt;br /&gt;  (do1 i&lt;br /&gt;    (md-finalize i)&lt;br /&gt;    (md-awaken i)))&lt;br /&gt;&lt;br /&gt;(def md-finalize (i)&lt;br /&gt;  (do1 i&lt;br /&gt;    (if (acons i)&lt;br /&gt;        (map md-finalize i)&lt;br /&gt;      (do&lt;br /&gt;          ; register instance in a namespace for inter-i dependency&lt;br /&gt;          (= (mds* (md-name i)) i)&lt;br /&gt;          &lt;br /&gt;          ; move cells out of mediated slots into 'cells slot&lt;br /&gt;          (tablemap i&lt;br /&gt;            (fn (k v)&lt;br /&gt;              (when (c-isa v 'cell)&lt;br /&gt;                (= v!model i v!slot k)&lt;br /&gt;                (push (list k v) i!cells)&lt;br /&gt;                (= (i k) 'unbound))))))))&lt;br /&gt;&lt;br /&gt;(def md-awaken (i)&lt;br /&gt;  (do1 i&lt;br /&gt;    (if (acons i)&lt;br /&gt;        (map md-awaken i)&lt;br /&gt;      (do ; bring each slot "to life"&lt;br /&gt;          (tablemap i&lt;br /&gt;            (fn (k v)&lt;br /&gt;              (aif (md-slot-cell i k)&lt;br /&gt;                (slot-ensure-current it)&lt;br /&gt;                (slot-value-observe i k v 'unbound))))))))&lt;br /&gt;&lt;br /&gt;(def md? (name)&lt;br /&gt;  mds*.name)&lt;br /&gt;&lt;br /&gt;;; --- start of cells stuff ------------------&lt;br /&gt;&lt;br /&gt;(def cells-reset ()&lt;br /&gt;  (= datapulse* 1) ; not sure why can't start at zero&lt;br /&gt;  (= caller* nil)&lt;br /&gt;  (= mds* (table)))&lt;br /&gt;&lt;br /&gt;(def ctype-of (x)&lt;br /&gt;  (when (isa x 'table)&lt;br /&gt;    x!ctype))&lt;br /&gt;&lt;br /&gt;(def c-isa (s type)&lt;br /&gt;  (is ctype-of.s type))&lt;br /&gt;&lt;br /&gt;(defmd (cell nil c-) ;; the c- gets prefixed to all accessor names&lt;br /&gt;    awake &lt;br /&gt;  (pulse 0)&lt;br /&gt;  (pulse-last-changed 0)&lt;br /&gt;  (cache 'unbound)&lt;br /&gt;  model&lt;br /&gt;  slot&lt;br /&gt;  rule&lt;br /&gt;  users&lt;br /&gt;  useds&lt;br /&gt;  observers)&lt;br /&gt;&lt;br /&gt;(defmd (model nil md-)&lt;br /&gt;    ; any template to be mediated by cells must include model&lt;br /&gt;  name ; used so one instance can find another by name&lt;br /&gt;  cells&lt;br /&gt;  observers)&lt;br /&gt;&lt;br /&gt;(def md-slot-cell (i s)&lt;br /&gt;  (alref i!cells s))&lt;br /&gt;&lt;br /&gt;;;; --- reading a slot -------------------------&lt;br /&gt;&lt;br /&gt;(def slot-value (i s)&lt;br /&gt;  (aif (md-slot-cell i s)&lt;br /&gt;    (do (when caller*&lt;br /&gt;          (pushnew caller* it!users)&lt;br /&gt;          (pushnew it caller*!useds))&lt;br /&gt;        (slot-ensure-current it))&lt;br /&gt;    (i s)))&lt;br /&gt;&lt;br /&gt;(def calculate-and-set (c)&lt;br /&gt;  ; clear dependencies so we get a fresh set after each rule run&lt;br /&gt;  (each used c!useds&lt;br /&gt;    (= used!users (rem c used!users)))&lt;br /&gt;  (= c!useds nil)&lt;br /&gt;&lt;br /&gt;  ; run the rule&lt;br /&gt;  (let nv (withs* (caller* c)&lt;br /&gt;            (c!rule c!model))&lt;br /&gt;    (unless c!useds&lt;br /&gt;      ; losing rules with no dependencies &lt;br /&gt;      ; is a big performance win&lt;br /&gt;      (optimize-away c))&lt;br /&gt;    (slot-value-assume c nv)))&lt;br /&gt;&lt;br /&gt;(def optimize-away (c)&lt;br /&gt;  (pull (assoc c!slot ((c-model c) 'cells)) ((c-model c) 'cells))&lt;br /&gt;  (each user c!users&lt;br /&gt;    (pull c user!useds)&lt;br /&gt;    (unless user!useds ; rarely happens&lt;br /&gt;      (optimize-away user))))&lt;br /&gt;&lt;br /&gt;(def slot-ensure-current (c)&lt;br /&gt;  ; It would be fun to figure out a more readable&lt;br /&gt;  ; version of the next consition. I tried, can't.&lt;br /&gt;  (when (and c!rule&lt;br /&gt;          (or (is 0 c!pulse-last-changed)&lt;br /&gt;            (no (or (is c!pulse datapulse*)&lt;br /&gt;                   (no (any-used-changed c c!useds))))))&lt;br /&gt;    (calculate-and-set c))&lt;br /&gt;&lt;br /&gt;  (= c!pulse datapulse*)&lt;br /&gt;&lt;br /&gt;  (when (is 0 c!pulse-last-changed) ;; proxy for nascent state&lt;br /&gt;    (= c!pulse-last-changed datapulse*)&lt;br /&gt;    (slot-value-observe c!model c!slot c!cache 'unbound))&lt;br /&gt;  c!cache)&lt;br /&gt;&lt;br /&gt;(def any-used-changed (c useds)&lt;br /&gt;  (when useds&lt;br /&gt;    ; So happens that FIFO is better order for this&lt;br /&gt;    (or (any-used-changed c (cdr useds))&lt;br /&gt;      (let used (car useds)&lt;br /&gt;        (slot-ensure-current used)&lt;br /&gt;        (&gt; used!pulse-last-changed c!pulse)))))&lt;br /&gt;&lt;br /&gt;;;; --- writing to a slot -----------------------&lt;br /&gt;&lt;br /&gt;(def set-slot-value (i s v)&lt;br /&gt;  (aif (md-slot-cell i s)&lt;br /&gt;    (do (++ datapulse*)&lt;br /&gt;        (slot-value-assume it v))&lt;br /&gt;    (prt "you cannot assign to a slot without a cell" i s)))&lt;br /&gt;&lt;br /&gt;(def slot-value-assume (c v)&lt;br /&gt;  (= c!pulse datapulse*)&lt;br /&gt;  (with (i c!model ov c!cache)&lt;br /&gt;    (unless (is v ov)&lt;br /&gt;      (= c!cache v)&lt;br /&gt;      (= (i c!slot) v) &lt;br /&gt;      (= c!pulse-last-changed datapulse*)&lt;br /&gt;      (slot-propagate c ov)))&lt;br /&gt;    v)&lt;br /&gt;&lt;br /&gt;;;; --- dataflow --------------------------------&lt;br /&gt;;;; Propagate state change from cell to cell and&lt;br /&gt;;;; as needed from Cell to outside world&lt;br /&gt;;;;&lt;br /&gt;(def slot-propagate (c ov)&lt;br /&gt;  (let caller* nil&lt;br /&gt;    (each user c!users&lt;br /&gt;      (slot-ensure-current user))&lt;br /&gt;    (slot-value-observe c!model c!slot c!cache ov)))&lt;br /&gt;&lt;br /&gt;(def slot-value-observe (i s v ov)&lt;br /&gt;  (awhen (md-slot-cell i s)&lt;br /&gt;    (observe it!observers i s v ov))&lt;br /&gt;  (observe (alref i!observers s) i s v ov)&lt;br /&gt;  (observe obs*.s i s v ov))&lt;br /&gt;&lt;br /&gt;(def observe (o i s v ov)&lt;br /&gt;  (if (acons o)&lt;br /&gt;      (map (fn (o2) (o2 i s v ov)) o)&lt;br /&gt;    o (o i s v ov)))&lt;br /&gt;&lt;br /&gt;;;; --- constructor sugar --------------------&lt;br /&gt;&lt;br /&gt;(mac imd (name (type) . inits)&lt;br /&gt;  `(inst ',type 'name ',name&lt;br /&gt;     ,@(mappend (fn ((s v)) `(',s ,v)) (pair inits))))&lt;br /&gt;&lt;br /&gt;(def c-in (v)&lt;br /&gt;  (inst 'cell 'cache v))&lt;br /&gt;&lt;br /&gt;(mac c? (rule . observers)&lt;br /&gt;  `(inst 'cell&lt;br /&gt;     'rule ,rule&lt;br /&gt;     'observers (list ,@observers)))&lt;br /&gt;&lt;br /&gt;;;; --- example --------------------------------&lt;br /&gt;&lt;br /&gt;(defmd (furnace (model) fur-)&lt;br /&gt;  on temp (fuel 0)&lt;br /&gt;  ;;; another way to do observers, at the class level&lt;br /&gt;  ;;;  observers `((fuel ,(fn (i s v ov)&lt;br /&gt;  ;;;                       (prt 'md-defined-observer-sees i!name s v ov))))&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;(defmd (thermostat (model) thermo-)&lt;br /&gt;    preferred actual)&lt;br /&gt;&lt;br /&gt;(def test-furnace ()&lt;br /&gt;  (do (cells-reset)&lt;br /&gt;      (prt '----------start-------------------)&lt;br /&gt;    (let (th f) (to-be&lt;br /&gt;                 (list&lt;br /&gt;                  (imd th42 (thermostat) preferred (c-in 70) actual 70)&lt;br /&gt;                  (imd f-1 (furnace) &lt;br /&gt;                    fuel 10&lt;br /&gt;                    on (c? [let th (md? 'th42)&lt;br /&gt;                             (&lt; (thermo-actual th)(thermo-preferred th))]&lt;br /&gt;                         ; an instance-level observer&lt;br /&gt;                         (fn (i s v ov)&lt;br /&gt;                           (prt "Sending"(if v 'on 'off) "control sequence to furnace f-1"))))))&lt;br /&gt;      ;;; A global observer of any slot called "on"&lt;br /&gt;      ;;;      (push (fn (i s v ov)&lt;br /&gt;      ;;;              (prt 'on-global-obs-1 i!name s v ov))&lt;br /&gt;      ;;;        obs*!on)&lt;br /&gt;      &lt;br /&gt;      (prt "After awakening the model the furnace is" (if (fur-on f) 'on 'off))&lt;br /&gt;      (set-thermo-preferred th 72) ;; the furnace comes on cuz we want it warmer&lt;br /&gt;      )))&lt;br /&gt;&lt;br /&gt;(test-furnace)&lt;br /&gt;&lt;br /&gt;;;; Output:&lt;br /&gt;; ----------start-------------------&lt;br /&gt;; Sending off control sequence to furnace f-1&lt;br /&gt;; After awakening the model the furnace is off&lt;br /&gt;; Sending on control sequence to furnace f-1&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-397035100861529645?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/397035100861529645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=397035100861529645' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/397035100861529645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/397035100861529645'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/arccells-its-alive.html' title='Arc!Cells: It&apos;s Alive!!!'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7612624747958143449</id><published>2008-02-18T00:07:00.004-05:00</published><updated>2008-02-18T02:32:20.371-05:00</updated><title type='text'>A Terrible Thing</title><content type='html'>some comp.lang.lisp yobbo wrote:&lt;br /&gt;&lt;i&gt; You know, with you, I just don't know how to read your posts (I mean all the stuff about arc).  You're like one of those oriental mysteries that this sub-linear mind just cannot fathom.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Google Adsense feels your pain. This is a Lisp blog and I have seen ads for furnace installations and nursing jobs in Hawaii. Well, what do you want from people who use Python? &lt;br /&gt;&lt;br /&gt;Lemme help. In your country, do you have the game "in plain view"? The inventor was a genius of psychology, especially perception. Here in Umaguhwallaweeland we like to do it with chocolate candies on Easter aka find-the-candy-day. We take little candies (or for the adults splits of vodka) and scatter them around the house in plain view of anyone standing in any normal location. &lt;br /&gt;&lt;br /&gt;The seekers run about frantically freaking out over the fact that they know they are missing chocolates or Stolys just there for the taking while the hiders try not to lose bladder control looking straight at the candies watching the seekers burn more calories than a seagull in a headwind. &lt;br /&gt;&lt;br /&gt;Something like this:: &lt;a href="http://smuglispweeny.blogspot.com/2008/02/maybe-i-was-too-hard-on-sohail.html"&gt;Maybe I was too hard on Sohail&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That said, your confession indicates you are almost ready to leave the temple. You just need to make the Giant Kenny Leap (GKL). This was when I realized that when I had these weird feelings of dissonance that G*d was speaking to me so  I would never be wrong if I just listened, that the dissonance meant something and that for the love of G*d I should not ignore the dissonance. &lt;br /&gt;&lt;br /&gt;When writing code, that is, but I recognize the rule in your inner conflict.&lt;br /&gt;&lt;br /&gt;Bullseye. Arrow. Just let go.&lt;br /&gt;&lt;br /&gt;The GKL moment came working on The Greatest Lisp Application ever now sadly lost to mankind (another story) but during whose creation I realized nothing more sophisticated than that if it feels bad stop it and if it feels good yadda yadda. As you in your temple-leavingness detected this is not and should not be subjected to the impotence of conscious reason, the mistake that doomed AI but I digress.&lt;br /&gt;&lt;br /&gt;One of the quotations in my &lt;a href="http://smuglispweeny.blogspot.com/2008/02/what-hell-is-fortune-cookie-file-anyway.html"&gt;fortune cookie file&lt;/a&gt; covers someone who came close but in the end failed on one of my he-cannot-be-serious posts and decided I was serious... when your pattern recognition system recognizes irony, why are you are arguing? Your PRS safely jaywalks you across a dimly lit four-lane highway in a driving rainstorm while it is a crapshoot whether that is deoderant or hairspray your cortex is applying to your underarm.&lt;br /&gt;&lt;br /&gt;Just Listen to these vagosities percolating up from neural regions unknown--there is no truer guide. Shakespeare almost had it right: &lt;br /&gt;&lt;pre&gt;What a tangled web we weave when first we reason. &lt;/pre&gt;&lt;br /&gt;And the United Negro College Fund was just a hair outside as well:&lt;br /&gt;&lt;pre&gt;The mind is a terrible thing.&lt;/pre&gt;&lt;br /&gt;Oops, here comes The Odd Couple re-run, gotta go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7612624747958143449?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7612624747958143449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7612624747958143449' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7612624747958143449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7612624747958143449'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/some-cll-yobbo-wrote-you-know-with-you.html' title='A Terrible Thing'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-1408346765547848856</id><published>2008-02-15T03:10:00.005-05:00</published><updated>2008-02-15T19:17:23.610-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dynamic binding'/><category scheme='http://www.blogger.com/atom/ns#' term='Common Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='special variables'/><title type='text'>Faux dynamic binding for Arc</title><content type='html'>The objective in what follows is to simulate one of my favorite features of CL, which is dynamic binding of special variables. If you ever programmed QuickDraw for the Mac and tediously had to code up GetPort, SetPort, and then a SetPort back when finished drawing, just imagine having the ability simply to code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (let grafport* (grafPort my-window)&lt;br /&gt;      ...)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;...and get the whole save, re-bind, and restore taken care of for you. Does not come up a lot, but when it does this rocks (and Cells uses it for its core behavior of tracking dependencies). You see this sort of thing especially in cases exactly like the drawing GrafPort, something so fundamental that the lowest level functions will need it so it is either a global of some kind or every function in the API needs it as a parameter.&lt;br /&gt;&lt;br /&gt;In the case of Cells, without dynamic binding almost every function in the application would need it. Not a pretty thought. &lt;br /&gt;&lt;br /&gt;Caveat emptor: The following has been lightly tested with only one variable pseudo-dynamically bound. Bug reports welcome, but if the report is "Listen, dummy, Arc already has that."...well, I'll just be a normallispweeny for a week:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(mac withs* (parms . body)&lt;br /&gt;  (let uparms (map1 [cons (uniq) _] (pair parms))&lt;br /&gt;    `(do ,@(map1 (fn ((save curr val))&lt;br /&gt;                   `(= ,save ,curr ,curr ,val)) uparms)&lt;br /&gt;       (do1&lt;br /&gt;           (do ,@body)&lt;br /&gt;         ,@(map1 (fn ((save curr val))&lt;br /&gt;                   `(= ,curr ,save)) uparms)))))&lt;br /&gt;&lt;br /&gt;(= stak* (list 'top))&lt;br /&gt;&lt;br /&gt;(def pstack (k)&lt;br /&gt;  (prs k stak*)(prn))&lt;br /&gt;&lt;br /&gt;(do&lt;br /&gt;  (pstack 'start)&lt;br /&gt;  (with* (stak* (cons 'me stak*))&lt;br /&gt;      (prt 'with-me stak*)&lt;br /&gt;      (pstack 'confirm-with-me))&lt;br /&gt;  (pstack 'bye-bye))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output should be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  start (top)&lt;br /&gt;  with-me (me top)&lt;br /&gt;  confirm-with-me (me top)&lt;br /&gt;  bye-bye (top)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Enjoy. (And with* left as an exercise. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-1408346765547848856?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/1408346765547848856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=1408346765547848856' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1408346765547848856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/1408346765547848856'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/faux-dynamic-binding-for-arc.html' title='Faux dynamic binding for Arc'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-8462070087117294747</id><published>2008-02-14T18:41:00.004-05:00</published><updated>2008-02-14T19:14:49.299-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='McCarthy'/><category scheme='http://www.blogger.com/atom/ns#' term='Common Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='Cells'/><title type='text'>Meaningless First Impressions of Arc</title><content type='html'>Almost posted on comp.lang.lisp:&lt;br /&gt;&lt;br /&gt;&gt; I think porting Cells is a very good test of Arc as a practical&lt;br /&gt;&gt; language (even at this early stage),&lt;br /&gt;&lt;br /&gt;Yep, but it occurred to me that Mr. Graham would protest that transliterating a project however interesting is about as far as one can get from exploratory programming and he would be right. Hell, even someone working from a system spec still has to come up with the code.&lt;br /&gt;&lt;br /&gt;&gt;  I appreciate you jumping in&lt;br /&gt;&gt; as the guinea pig.&lt;br /&gt;&lt;br /&gt;I must confess, it is more like guinea frog (inside cll joke). But this dry material probably will not make me the next Imus in the Morning.&lt;br /&gt;&lt;br /&gt;&gt; I think it's much more informative than the "I&lt;br /&gt;&gt; wrote a wiki in 10 lines" that we've been seeing. What's your&lt;br /&gt;&gt; impression so far? Is there anything that really stands out, good or&lt;br /&gt;&gt; bad, while you've been working on the Cells port?&lt;br /&gt;&lt;br /&gt;With 1% of the polls reporting, I miss my mud (the forty-six page index of Common Lisp the Language). No matter whether I reach for the #3 Torx driver or the articulating socket wrench extender I come up with the same vice-grip. I doubt I will ever get over this.&lt;br /&gt;&lt;br /&gt;As for the brevity, that feels more like friction than grease, and I cannot even touch type.&lt;br /&gt;&lt;br /&gt;But most of all I feel like I was right: it will be hard to tell until I have done a lot more Arc coding, because the brevity might feel like friction only because I have not gotten used to it. Especially fun is stuff that newly appeared in &lt;a href="http://ycombinator.com/arc/arc1.tar"&gt;Arc 1&lt;/a&gt; (click only to download) such as a hashtable lookup normally coded thus:&lt;br /&gt;&lt;pre&gt; (my-table sought-key)&lt;/pre&gt;&lt;br /&gt;...which can now be coded thus:&lt;br /&gt;&lt;pre&gt; my-table.sought-key&lt;/pre&gt;&lt;br /&gt;...and when the key is a literal we can rewrite:&lt;br /&gt;&lt;pre&gt;  (oed 'peloria) as oed!peloria&lt;/pre&gt;&lt;br /&gt;This notation is generally applicable where one has a one-parameter function:&lt;br /&gt;&lt;pre&gt;  abs.-42 -&gt; 42&lt;/pre&gt;&lt;br /&gt;So the potential for code obfuscation is terrific. :) To get Cells to work I will have to write readers and writers, so you might see code like:&lt;br /&gt;&lt;pre&gt; (pressure my-boiler)&lt;/pre&gt;&lt;br /&gt;...which could as well be:&lt;br /&gt;&lt;pre&gt; pressure.my-boiler&lt;/pre&gt;&lt;br /&gt;...and since the boiler will be a hashtable, one would normally read the hashtable like this:&lt;br /&gt;&lt;pre&gt; my-boiler!pressure&lt;/pre&gt;&lt;br /&gt;My head is spinning. With Cells that would be a backdoor which would bypass the Cells mechanism entirely a la slot-value in Common Lisp. Bad client! Bad!&lt;br /&gt;&lt;br /&gt;If Lisp is a local maximum in language design, all-sexprs-all-the-time might be the knife-edge ridge on which it stands. See we will.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-8462070087117294747?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/8462070087117294747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=8462070087117294747' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8462070087117294747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8462070087117294747'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/meaningless-first-impressions-of-arc.html' title='Meaningless First Impressions of Arc'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-8175879427274734770</id><published>2008-02-14T05:19:00.013-05:00</published><updated>2008-02-14T17:05:49.592-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Functional reactive programming'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='Cells'/><title type='text'>Arc!Cells: Baby Steps</title><content type='html'>[This first article on doing Cells (see the "Cells Manifesto" entry in this blog) in Arc serves more to motivate the idea than anything else. In a nutshell, we want to be able to do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(= a (ci 3))&lt;br /&gt;(= b (ci 4))&lt;br /&gt;(defobserver c ()&lt;br /&gt;    (prs "Hey, C is now" new-value&lt;br /&gt;         "was" old-value))&lt;br /&gt;(= c (c? (sqrt (+ (expt (cval a) 2)&lt;br /&gt;                  (expt (cval b) 2)))))&lt;br /&gt;Hey, C is now 5 was unbound&lt;br /&gt;(cset a 6 b 8)&lt;br /&gt;Hey, C is now 10 was 5&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In other words, values are not just functions of values but also active bits of state which can have arbitrary observer logic bound to them.&lt;br /&gt;              &lt;br /&gt;In a subsequent (next?) blog I plan to easy up on the tutorial angle and just present a decent port of what I called Cells II, which was powerful but had theoretical holes closed in Cells3.&lt;br /&gt;&lt;br /&gt;A close version of what follows is in CVS here (as cells-1.arc in case this link does not fly):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   http://common-lisp.net/cgi-bin/viewcvs.cgi/kennysarc2&lt;br /&gt;                /cells-1.arc?rev=1.1&amp;root=cells&amp;view=log&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Enjoy.]&lt;br /&gt;&lt;br /&gt;First a couple of utilities:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def prt args&lt;br /&gt;  (apply prs args)&lt;br /&gt;  (prn))&lt;br /&gt;&lt;br /&gt;(mac prun (banner . forms)&lt;br /&gt;  `(do (prn ,banner)&lt;br /&gt;       (prn '(do ,@forms))&lt;br /&gt;     (prn)&lt;br /&gt;     ,@forms))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let's start with the moral equivalent of a C++ member function, or at least I think that's what they call it. Something that looks like a stored data member or slot of an attribute of an object but is in fact implemented as a function of that object.&lt;br /&gt;&lt;br /&gt;An example would be having a rectangle object with data members where one could store length and width and then have an area attribute implemented (in C++) as:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   area = this.length * this.width;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Aside from saving a little memory, one gets a guarantee that the area will always be consistent with the length and width, which is not the case if one is writing code that says oh gosh I just changed the length I better go change the area.&lt;br /&gt;&lt;br /&gt;As our 'application pushing down on the core' we'll use my favorite, a furnace boiler.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b* (obj outside-temp 72&lt;br /&gt;         on? [&lt; _!outside-temp 50])))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No, the outside temp is not an attribute of a boiler, we're just keeping things in one table as a convenience until we get the ball rolling, later on we'll deal with multiple objects.&lt;br /&gt;&lt;br /&gt;That anonymous function above boils down to:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   If the outside temp is less than 50,&lt;br /&gt;     then turn on the boiler,&lt;br /&gt;     otherwise turn it off. &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;First, let's see if the rule works (not a big accomplishment)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (prt 'boiler b*!outside-temp (if (b*!on? b*) 'on 'off)))&lt;br /&gt;&lt;br /&gt;  -&gt; boiler 72 off&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Good, now change temp to 32 and see if the boiler comes on:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b*!outside-temp 32)&lt;br /&gt;  (prt 'boiler b*!outside-temp (if (b*!on? b*) 'on 'off)))&lt;br /&gt;&lt;br /&gt;  -&gt; boiler 32 on&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Super. Now let's hide the fact that on? is a function&lt;br /&gt;behind a reader function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (def on? (i) (i!on? i)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;...and ease inspection:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def pr-boiler (b)&lt;br /&gt;  (prt 'boiler 'temp b*!outside-temp (if (on? b) 'on 'off)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Test new slot reader, setting temp high enough this time&lt;br /&gt;so that the boiler should go off:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b*!outside-temp 80)&lt;br /&gt;  (pr-boiler b*))&lt;br /&gt;&lt;br /&gt;  -&gt; boiler temp 80 off&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But we want more flexibility than having an attribute &lt;i&gt;always&lt;/i&gt; defined by a function. Maybe we just want to store nil or t in &lt;code&gt;on?&lt;/code&gt; and maintain it as usual, via assignment. Now &lt;code&gt;on?&lt;/code&gt; can no longer be assumed to be a function. Fortunately we already have it behind a reader in our burgeoning little OO system, so we just need to enhance that (and get a redefinition warning):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def on? (i)&lt;br /&gt;  (awhen i!on?&lt;br /&gt;    (if (isa it 'fn)&lt;br /&gt;        (it i)&lt;br /&gt;      it)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just test that our new accessor for &lt;code&gt;on?&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b* (obj outside-temp -10&lt;br /&gt;             on? nil)) ;; we'll ignore the outside-temp for this test&lt;br /&gt;  (pr-boiler b*))&lt;br /&gt;&lt;br /&gt;  boiler temp -10 off&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now assign t to &lt;code&gt;on?&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b*!on? t) ; We'll hide the assignment implementation later.&lt;br /&gt;  (pr-boiler b*))&lt;br /&gt;&lt;br /&gt;  boiler temp -10 on&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Good. We will want all our attributes to work this way, so we may as well generalize the &lt;code&gt;on?&lt;/code&gt; behavior now:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def slot-value (i slot-name) ;; i is like self ala Smalltalk&lt;br /&gt;   (awhen i.slot-name&lt;br /&gt;      (if (isa it 'fn)&lt;br /&gt;          (it i)&lt;br /&gt;        it))))&lt;br /&gt;&lt;br /&gt;(mac defslot (name)&lt;br /&gt;  `(def ,name (i) (slot-value i ',name)))&lt;br /&gt;&lt;br /&gt;(defslot outside-temp)&lt;br /&gt;(defslot on?)&lt;br /&gt;(defslot inside-temp) ;; Let's start elaborating the model&lt;br /&gt;&lt;br /&gt;(def pr-boiler (i)&lt;br /&gt;  (prt 'boiler&lt;br /&gt;    'outside-temp (outside-temp i)&lt;br /&gt;    (if (on? i) 'on 'off)&lt;br /&gt;    'inside-temp (inside-temp i)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And test:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(= b* (obj outside-temp 20&lt;br /&gt;         on? nil&lt;br /&gt;         inside-temp [if (on? _)&lt;br /&gt;                         72&lt;br /&gt;                       _!outside-temp])))&lt;br /&gt;&lt;br /&gt;boiler outside-temp 20 off inside-temp 20&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let's bring back the automatic boiler:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (= b*!on? [&lt; _!outside-temp 50]))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;...and step the outside temperature up from freezing to torrid.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (loop (= b*!outside-temp 30)&lt;br /&gt;        (&lt; b*!outside-temp 100)&lt;br /&gt;        (= b*!outside-temp (+ b*!outside-temp 10))&lt;br /&gt;     (pr-boiler b*)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Looks like we need an air conditioner. And let's get more realistic about the model&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(= outside* (obj temp 20))&lt;br /&gt;(defslot temp)&lt;br /&gt;&lt;br /&gt;(= furnace* (obj on? [&lt; (temp outside*) 50]))&lt;br /&gt;(= ac* (obj on? [&gt; (temp outside*) 75])) ;; air conditioner&lt;br /&gt;(= inside* [if (on? furnace*) 72&lt;br /&gt;             (on? ac*) 68&lt;br /&gt;             (temp outside*)])&lt;br /&gt;&lt;br /&gt;(def dumpworld ()&lt;br /&gt;  (prt "outside" (temp outside*))&lt;br /&gt;  (prt "furnace" (if (on? furnace*) 'on 'off))&lt;br /&gt;  (prt "a/c" (if (on? ac*) 'on 'off))&lt;br /&gt;  (prt "inside" (temp inside*)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Step temperature up from freezing to torrid, but with an air-conditioner:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(loop (= outside*!temp 30)&lt;br /&gt;      (&lt; outside*!temp 100)&lt;br /&gt;      (= outside*!temp (+ outside*!temp 10))&lt;br /&gt;   (prn)&lt;br /&gt;   (dumpworld)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nice. We have built a working model that runs by itself given simple declarative rules, meaning we state the rules and an engine sees to it that the model runs. But we have a problem. Let's add a debug option to our slots:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def slot-value (i slot-name (o debug))&lt;br /&gt;    (awhen i.slot-name&lt;br /&gt;      (if (isa it 'fn)&lt;br /&gt;          (do&lt;br /&gt;              (when debug (prt "Running the rule for slot" slot-name))&lt;br /&gt;              (let result (it i)&lt;br /&gt;                (when debug (prt "...slot" slot-name "is" result))&lt;br /&gt;                result))&lt;br /&gt;        it)))&lt;br /&gt;&lt;br /&gt;(mac defslot (name (o debug))&lt;br /&gt;  `(def ,name (i) (slot-value i ',name ,debug)))&lt;br /&gt;&lt;br /&gt;(defslot on? t)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Same test tracing the &lt;code&gt;on?&lt;/code&gt; slots&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(loop (= outside*!temp 30)&lt;br /&gt;      (&lt; outside*!temp 100)&lt;br /&gt;      (= outside*!temp (+ outside*!temp 10))&lt;br /&gt;   (prn)&lt;br /&gt;   (dumpworld)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Looks OK, but watch what happens even if nothing is going on:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(dumpworld))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ah, the downside of the functional paradigm: the code runs and runs. For simple functions that is no problem, but if we build an entire application this way things bog down (we learned the usual way).&lt;br /&gt;&lt;br /&gt;What we need to cache the result of a calculation and then return the cached result when queried a second time. But then there is a new problem: when do we refresh the cache? Answer: when we have to in order to stay current with the changing world arounds us, more plainly when one of the values used in a calculation changes.&lt;br /&gt;&lt;br /&gt;So we need to keep track of who uses whom in their calculations, and when one value changes notify its users that they need to recalculate.&lt;br /&gt;&lt;br /&gt;Tomorrow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-8175879427274734770?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/8175879427274734770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=8175879427274734770' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8175879427274734770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/8175879427274734770'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/arc-cells-baby-steps_14.html' title='Arc!Cells: Baby Steps'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7426155296207864676</id><published>2008-02-13T16:56:00.006-05:00</published><updated>2008-02-14T02:40:03.179-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reading comprehension'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><title type='text'>Maybe I Was Too Hard On Sohail</title><content type='html'>&lt;span style="font-style: italic;"&gt;Background: Sohail tried to contradict an article of mine on comp.lang.lisp in which I compared Arc unfavorably to Common Lisp with some code proving CL was almost as good as Arc. Think about that for a second. I ripped him a new one for poor reading comprehension and guessed correctly (he confirmed) that his understanding was blinded by another mistake, misconstruing my impatience with Arc's detractors as meaning somehow a preference of Arc over CL.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Great &lt;a href="http://lispnyc.org/"&gt;Lisp-NYC&lt;/a&gt; &lt;a href="http://lispnyc.org/wiki.clp?page=locations"&gt;chug-a-lug&lt;/a&gt; last night. But... everyone who came up to me to talk about &lt;a href="http://www.arclanguage.org/"&gt;Arc&lt;/a&gt; said, "So you like Arc, eh?" Every last one. And most of those who did are smarter than I.&lt;br /&gt;&lt;br /&gt;Each time I responded, "No, I never said that. I just rag on people for ragging on Arc without trying it."&lt;br /&gt;&lt;br /&gt;It gets worse. Half the people responded they were in fact aware that I had merely ragged on naysayers for their unreasoned opining. And they &lt;span style="font-style: italic;"&gt;still &lt;/span&gt;thought I liked Arc.&lt;br /&gt;&lt;br /&gt;Meanwhile over on Reddit someone wants to know if I am gay because I whined &lt;a href="http://smuglispweeny.blogspot.com/2008/02/all-your-parentheses-are-belong-to-us.html"&gt;publicly&lt;/a&gt; about Turing being persecuted for being gay. Sure and I am also black, Comanche, Jewish, Palestinian, Mexican, an Iraqi civilian, and I died in the plane that hit the South Tower of the WTC.&lt;br /&gt;&lt;br /&gt;We all know everyone sees the world differently. What I realized last night is that the differences go beyond the differences in the observers themselves, their different tastes, upbringings, cultures, and DNA. People just plain get things wrong.&lt;br /&gt;&lt;br /&gt;We get things wrong all the time. As a matter of course. Our world views form a scatter plot around the bullseye of reality.&lt;br /&gt;&lt;br /&gt;Not because of lack of intellect or through lack of attention, though those explain the worst misses. Just because the brain registers new information using a sloppy indexing scheme that settles for bad matches because they are the closest matches and because those matches are affected by what we had for lunch.&lt;br /&gt;&lt;br /&gt;We need a new song. Maybe "I say potato, you say Hunh? More day-glo?".&lt;br /&gt;&lt;br /&gt;One of my favorite lines to deliver upon completing a task: "That's close enough for government work." I think the brain's ethic is "That's close enough for this bozo carrying me around."&lt;br /&gt;&lt;br /&gt;Super. Billions of us walking around trying to deal with each other while each of us is working from more or less faulty copies of reality. Explains a lot.&lt;br /&gt;&lt;br /&gt;I realize now I never bought having conflict and injustice explained as the natural consequence of different tastes and life experiences. Nope.  We are all just more or less wrong about more or less everything, each of us in different ways, and so no, &lt;a href="http://en.wikipedia.org/wiki/Rodney_King"&gt;Rodney&lt;/a&gt;, we can never just get along. We will always be in conflict because we will never agree because we are all carrying around different broken realities and broken realities will clash more violently than realities varying merely by taste.&lt;br /&gt;&lt;br /&gt;Why do I find this so comforting?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7426155296207864676?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7426155296207864676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7426155296207864676' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7426155296207864676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7426155296207864676'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/maybe-i-was-too-hard-on-sohail.html' title='Maybe I Was Too Hard On Sohail'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-654129569605990475</id><published>2008-02-11T06:48:00.001-05:00</published><updated>2008-02-11T18:34:48.136-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='academia'/><category scheme='http://www.blogger.com/atom/ns#' term='Common Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='language design'/><title type='text'>A Tall Ship and a Star to Steer Her By</title><content type='html'>A few things collided yesterday. Background: I slammed Scheme and academia for the star by which they chose to steer Scheme's design, namely purity and a small specification. Yep, you heard me right. A design goal was a small spec, nothing to do with making programming easier. From the &lt;a href="http://www.faqs.org/faqs/lisp-faq/part1/section-2.html"&gt;FAQ&lt;/a&gt;:&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family:arial;"&gt;Advocates of Scheme often find it amusing that the Scheme standard is shorter than the index to CLtL2.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/blockquote&gt;Amuse this. Anyway, after that I got yelled at for being mean to Scheme and academia. Hey, I thought that was what blogs were for.&lt;br /&gt;&lt;br /&gt;Now the other thing that happened. Paul Graham released a new Lisp called &lt;a href="http://www.arclanguage.org/"&gt;Arc&lt;/a&gt; for which his guiding star is the brevity of the *application code* written in Arc. (He also likes a language to be small but I cannot be mean to him because he once was nice enough to give me a tip on how my &lt;a href="http://www.robocup.org/"&gt;RoboCup&lt;/a&gt; team could play better defense.)&lt;br /&gt;&lt;br /&gt;Mr. Graham further mentioned that Arc development includes a Web app library because he wants there to be a real-world application "pushing down" on the core language design. This reminds me of my cherished &lt;a href="http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html"&gt;Cells&lt;/a&gt; library whose twelve-year evolution has always been pushed by application development mostly because I am just a simple application programmer not smart enough to come up with fancy theories in the abstract so I just use things till they break and then fix them just well enough to get them working again. But I digress.&lt;br /&gt;&lt;br /&gt;The idea of having an application shape Arc went down well -- no one whined about it and on Usenet that is tantamount to a standing ovation -- but Mr. Graham's choice of brevity as a pole star in navigating his Arc led to a raucous of blogwar and I still had that defender of academia challenging me with "Hey, McCarthy was an academic". Things got ugly, the lights went out, I took a chair over the head, and here is what we (I) decided.&lt;br /&gt;&lt;br /&gt;First principles are Good Things. In Lisp, every form returns a value. That first principle works great. This despite Tilton's Law of Programming:&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt; All X all the time is the root of all evil.&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Examples: Prolog where it is all logic and unification and Smalltalk and Java where it is all objects. So how did "every form returns a value" get past Tilton's Law? Beats me, must be a Deep Truth somewhere about the power of the functional paradigm which is not all that hard to understand if one has worked on even a small amount of stateful code. At any rate, we will not reject out of hand the idea of one idea shaping a language, but we do see that we gots to pick the right idea.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Next question: are we OK with shorter being better, all other things being equal? Yes, that is correct. Note that reductio adsurbum counterexamples such as APL and K and Perl do not work because in those cases the shorterness takes us out of the space of all other things being equal. Changing  Lisp's lambda to Arc's fn makes it shorter without making it obscurer, but changing lambda to a hieroglyphic would.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Next issue: the shorter specs of Scheme and Arc. Would you walk up to a working programmer and start jumping up and down about this amazing new language guess what it's spec fits on one page!!! The working programmer would worry about you. Yeah it makes the &lt;span style="font-style: italic;"&gt;compiler&lt;/span&gt; easier to write but do we working programmers tell you compiler writers our problems?&lt;/p&gt;&lt;p&gt;Small specs. Pfft. Ever walk into an auto garage and see one of those huge red chests filled with drawer after drawer of tools? Those chests are the seven years of med school for a mechanic. We civilians might think it an overwhelming selection but the mechanic knows it by heart, even those tools used like every two months.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Mr. Graham talked at one point about a language being small enough to keep in one's head. I think the mistake there is the assessment of how big that small can be. People using something a lot (and I hope we are talking about designing a language for someone using it every day) can keep quite a bit in their heads. Meanwhile, hey, these are computers, a good IDE lets us zero in on documentation with a minimum of keystrokes to get the details of a keyword we forget, including zero keystrokes cuz as I finish typing the name of a function my IDE status bar shows the expected parameter list.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;On the flip side of big, a scanty starting tool chest means everyone either reinvents the missing bits or grabs one or another incompatible library off the shelf which is why Scheme programmers cannot share their work. Some of them point to specific implementations such as DrScheme and say Hey, it has everything! in which case what was the point of the small standard? You now have a big language unlike anyone else's. Juusst peachy.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;All that has been achieved with a small starting standard is making my code incompatible with someone else using some other big Scheme implementation. Lisp went through that without trying to because it too started small, insanely small, but then they cured the natural outcome (a fragmented community) when that threatened its DARPA contracts by creating Common Lisp &lt;span style="font-style: italic;"&gt;the standard&lt;/span&gt; and everyone saluted and conformed. They still lost the DARPA contracts but those will be back eventually because the standard now has the Common Lisp community all pulling in the same direction: I can use Other People's Code and they can use mine.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The subtext here is that CL may be a big language but I use all of it (except series, but give me time, it has only been thirteen years). One of the classic auto mechanic sayings is that any given task is easy when you have the right tool, and all of us shade tree mechanics forced into retirement by ever more complex automobiles remember how great were those moments when someone handed us the right tool and we were able to put down the Vice-Grips.&lt;/p&gt;&lt;p&gt;Brevity of application code? Great! Brevity of spec, not so much. Scheme needs to close up shop because if they fix what is wrong with it (hygienic macros, NIL not being false, a tiny standard) they end up with CL.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Arc is differentiated by its use of syntax to yield shorter applications, so it can stay, but it does need to add some drawers to the tool chest. And academia needs to start writing applications at the same time they are having bright ideas so they stop designing cool things that happen to be useless for programming. More on constraints later.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-654129569605990475?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/654129569605990475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=654129569605990475' title='25 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/654129569605990475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/654129569605990475'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/tall-ship-and-star-to-steer-her-by.html' title='A Tall Ship and a Star to Steer Her By'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>25</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-9104505413724552951</id><published>2008-02-11T03:31:00.005-05:00</published><updated>2008-03-26T16:28:37.866-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quotations'/><category scheme='http://www.blogger.com/atom/ns#' term='Kenny Tilton'/><title type='text'>What the Hell is a Fortune Cookie File Anyway?</title><content type='html'>Just to get strangers up to speed quickly on your correspondent, here is what other people say I said, according to their sigs:&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;I think it would be harder for a good programmer to change editors than to change languages.&lt;br /&gt;%&lt;br /&gt;Parentheses? What parentheses? I haven't noticed any parentheses&lt;br /&gt;since my first month of Lisp programming. I like to ask people who&lt;br /&gt;complain about parentheses in Lisp if they are bothered by all the&lt;br /&gt;spaces between words in a newspaper...&lt;br /&gt;%&lt;br /&gt;Lisp gives you a kazillion ways to solve a problem.&lt;br /&gt;(1- kazillion) of them are wrong.&lt;br /&gt;%&lt;br /&gt;My dream of a Cells consulting business is fading as user after user&lt;br /&gt;turns out to be hindered not at all by my deliberate withholding&lt;br /&gt;of documentation.&lt;br /&gt;%&lt;br /&gt;Lisp nearing the age of fifty is the most modern language out there. GC, dynamic, reflective, the best OO model extant including GFs, procedural macros, and the only thing old-fashioned about it is that it is compiled and fast.&lt;br /&gt;%&lt;br /&gt;Eight years to do TeX? How smart can [Knuth] be? He should have used Lisp.&lt;br /&gt;%&lt;br /&gt;&lt;span style="font-style: italic;"&gt;[This one apparently stopped the quoter from trying Lisp. The quoter suspected irony but finally decided I was serious.]&lt;/span&gt;&lt;br /&gt;Yeah, I'm a gifted guru. Since you called me that, I guess I'll talk to you a little bit.&lt;br /&gt;%&lt;br /&gt;There are no average Lisp programmers. We are the Priesthood. Offerings of incense or cash will do.&lt;br /&gt;%&lt;br /&gt;I suppose if what you said had any merit it would occasion hostility.&lt;br /&gt;%&lt;br /&gt;Yeah, what the hell can anyone accomplish with beauty and power? &lt;span style="font-style: italic;"&gt;(in response to a linked blog entry saying Lisp was beautiful and powerful but unuseable)&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;No, you are an asshole doing his best to despoil c.l.l, and I am an&lt;br /&gt;asshole doing his best to hose out your crap.&lt;br /&gt;%&lt;br /&gt;Liars need good memories, trolls need NG readers with bad ones.&lt;br /&gt;%&lt;br /&gt;We all need early warning systems for "they might have heard this a million times before". I once destroyed any nano-chance I had with a stunning, taller woman by asking her how tall she was.&lt;br /&gt;"Six foot two," she replied. "How short are you?"&lt;br /&gt;%&lt;br /&gt;Programmers who lock onto a design decision and cling to it in the face of contradictory new information -- well, that's almost everyone in my experience, so I better not say what I think of them or people will start saying bad things about me on c.l.l.&lt;br /&gt;%&lt;br /&gt;This reminds me of the NYC cabby who accepted a fare to Chicago. When they got there and could not find the friend who was supposed to pay the fare the cabby  just laughed and said he should have known.&lt;br /&gt;%&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; Actually, I believe that Aikido, Jazz and Lisp are different appearances of the same thing.&lt;/span&gt;&lt;br /&gt;Yes, the Tao. /Everything/ is a different appearance of the tao.&lt;br /&gt;---&lt;br /&gt;"Ken, I went to the library and read up on Buddhism, and believe me, you are no Buddhist."&lt;br /&gt;-- Kenny's Mom&lt;br /&gt;%&lt;br /&gt;That absolutely terrifies the herd-following, lockstep-marching, mainstream-saluting cowards who obediently dash out to scoop up books on The Latest Thing. They learn and use atrocities like Java, C++, XML, and even Python for the security it gives them and then sit there slaving away miserably, tediously, joylessly paying off mortgages and supporting ungrateful teenagers who despise them, only to look out the double-sealed thermo-pane windows of their central-heated, sound-proofed, dead-bolted, suffocating little nests into the howling gale thinking "what do they know that I do not know?" when they see us under a lean-to hunched over our laptops to shield them from the rain laughing our asses off as we write great code between bong hits.... what was the question?&lt;br /&gt;%&lt;br /&gt;Shut up! (That last phrase has four or more syllables  if pronounced as intended.)&lt;br /&gt;%&lt;br /&gt;Nonsense. You'll be using it for the GUI, not protein-folding.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(in response to a comment that LTk was slow)&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;Continuations certainly are clever, but if we learned anything from the rejection of the cover art for "Smell the Glove", it is that "there is a fine line between stupid... and clever".&lt;br /&gt;%&lt;br /&gt;Ah, there's no place like academia for dispassionate, intellectually honest discussion of new ideas on their merits. Thank god for tenure giving your bold antagonist the protection they needed to shout down your iconoclastic..... hang on...&lt;br /&gt;%&lt;br /&gt;Whoever objected must be in my killfile, ...&lt;br /&gt;%&lt;br /&gt;From memory (but I think I have it right): "But Jesus said, Suffer captured variables, and forbid them not to come unto thine macro bodies, for of such are DSLs made." Can I get an Amen?&lt;br /&gt;%&lt;br /&gt;Awareness of defect is the first step to recovery.&lt;br /&gt;%&lt;br /&gt;You made a bad analogy (there are no good ones, but you found a new low) ...&lt;br /&gt;%&lt;br /&gt;Yes, it is true that Kent Pitman was raised by a closet full of Lisp Machines, but the exception only proves the rule. &lt;span style="font-style: italic;"&gt;(in a postscript after positing that computer languages are not learned in infancy)&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;I suggest you try bartender's school to support yourself, start programming for fun again.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(responding to a comment that 98% of anything to do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;with computers was not interesting code)&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;I could add four lanes to my carpal tunnel and still not write all the code I am dying to write.&lt;br /&gt;%&lt;br /&gt;Neutrality? I want to bury other languages, not have a gateway to them.&lt;br /&gt;%&lt;br /&gt;Ken: "Cute puppy. Did you get it for companionship or to pick up chicks?"&lt;br /&gt;Simon: "Hunh? My puppy /always/ gives me companionship."&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(on how he was understood by a native English speaker)&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; Yeah. In case you guys didn't quite get it, this particular site&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; targets (among other things) the Turkish lisp effort. Yours truly and&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; others have also been accused of being destructive to Turkish youth&lt;br /&gt;&lt;/span&gt;They want you to copy them first?&lt;br /&gt;%&lt;br /&gt;You can lead a horse away from water, but if it wants to drink you&lt;br /&gt;better have a big frickin stun gun. No, I have no idea what I just said.&lt;br /&gt;%&lt;br /&gt;PWUIAHAHAHAHA. This is Lisp. We never use anyone else's code. Hell, most of us won't even use Lisp, insist on creating our own with C.&lt;br /&gt;%&lt;br /&gt;OK, who is going to head over to c.l.python and suggest parentheses instead of whitespace? It could be a pretty funny post. "Hey, guys! I was looking at Lisp, had this great idea...keep an open mind!"&lt;br /&gt;%&lt;br /&gt;Educational software itself is now an acknowledged joke precisely because of people who try to foist on others "Oh, look, we used a computer, it must be in-frickin-credible".&lt;br /&gt;%&lt;br /&gt;Horse. Cart. Please note order.&lt;br /&gt;%&lt;br /&gt;Start this thread again. Change the subject to "Lisp Sucks! Molasses is faster!!" and post the code and some timings and the whole community will be working for you for free.&lt;br /&gt;%&lt;br /&gt;We live here. Every week we see noobs stumble in the door, trip over the upturned rug, bang their heads on the too-low hanging lamp, and then ease into Lisp pretty easily after being pointed to Lisp-aware editors, Slime, PCL, etc etc directed by living Lisp Gods, dynamic and interactive, not some two-dimensional billboard of an FAQ that just raises more questions.&lt;br /&gt;%&lt;br /&gt;Are you looking for that "friends" stuff from C++ (if I have that right, unless it was Java &lt;g&gt;). This is Lisp, we just shoot from the hip.&lt;br /&gt;%&lt;br /&gt;You people do not listen to me on AllegroCL, you do not listen to me on Cells, why am I not surprised you do not listen to me on the tao?&lt;br /&gt;%&lt;br /&gt;Two prehensile toes up!&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- reporting on behalf of his development team their review of Peter Seibel's "Practical Common Lisp"&lt;/span&gt;&lt;br /&gt;%&lt;br /&gt;Pearls. Swine. Please note order.&lt;br /&gt;%&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; I think it's a fairly large assumption that this problem is soluble...&lt;/span&gt;&lt;br /&gt;If not work on it should be suspended.&lt;br /&gt;%&lt;br /&gt;This will be a commercial "Hello World" app that displays "Hello", asks you to login or buy, then displays "world". More soon.&lt;br /&gt;%&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt; Callbacks are a form of continuation.&lt;/span&gt;&lt;br /&gt;Yes, in the same sense that a shoe is a form of aircraft carrier.&lt;br /&gt;%&lt;br /&gt;Lisp is no longer the crazy aunt in the attic, she is now out in the front parlor where her admirers come to pay homage and learn at her feet.&lt;br /&gt;%&lt;br /&gt;&gt; fred gilham wrote:&lt;br /&gt;&gt;&gt; kenny tilton wrote:&lt;br /&gt;&gt;&gt;&gt; fred gilham wrote:&lt;br /&gt;&gt;&gt;&gt;  Become a celebrity like Kenny Tilton.&lt;br /&gt;&gt;&gt; I am a simple Lisp programmer.&lt;br /&gt;&gt;&gt; --&lt;br /&gt;&gt;&gt; "I am a simple Buddhist monk.  "&lt;br /&gt;&gt;&gt;             --  Tenzin Gyatso, the Fourteenth Dalai Lama&lt;br /&gt;&gt; On top of everything else,  humble too!  :-)&lt;br /&gt;%&lt;/g&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-9104505413724552951?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/9104505413724552951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=9104505413724552951' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/9104505413724552951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/9104505413724552951'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/what-hell-is-fortune-cookie-file-anyway.html' title='What the Hell is a Fortune Cookie File Anyway?'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-705534537697359539</id><published>2008-02-11T03:18:00.001-05:00</published><updated>2008-02-14T04:40:58.410-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Road to Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Kenny Tilton'/><title type='text'>My Road to Lisp</title><content type='html'>&lt;div id="Content"&gt;&lt;span id="ContentHeader"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div id="ContentBody"&gt;&lt;br /&gt;I, &lt;span style="font-size:100%;"&gt;Kenny Tilton&lt;/span&gt;, do solemnly offer these my responses to &lt;a href="http://wiki.alu.org/The_Road_to_Lisp_Questions"&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="internal"&gt;The Road to Lisp Survey&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt; &lt;p&gt;&lt;b&gt; When did you first try Lisp seriously?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;1995. My initial interest in programming when I went shopping for my first computer in 1977 was artificial intelligence so of course I heard about Lisp,and when I ran across a Lisp 1.5 Manual in some geek shop I snagged it. But I could not make any sense out of it. &lt;/p&gt;&lt;p&gt;Fast forward five years and now I am a VAX/VMS consultant doing business apps in tall buildings, and while reading some geek rag I am stunned to see Lisp listed as a 4GL based on the 4GL definition of being an order of magnitude more productive than a 3GL. This was strange because 4GLs generally created the illusion of greater productivity with screen builders and a super high level hence inflexible language with database stuff done for you and I knew Lisp was not like that. I filed this datapoint away and went on with my life. &lt;/p&gt;&lt;p&gt;Five years later I decide to write a program which could check intermediate steps of arbitrary first-year high school algebra problems as part of a math tutorial. I see Microsoft (!) offers a Logo, and I remember the 4GL datapoint and decide what the hell let's learn a new language at the same time. &lt;/p&gt;&lt;p&gt;I loved it and went amazingly far with Logo on the tutorial before realizing it would have to be ported to C (a most unpleasant exercise) and it was another ten years before I found my way out of the desert and back to Lisp.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt; Which Lisp did you try?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;Common Lisp. Digitool's MCL, to be specific.  &lt;/p&gt;&lt;p&gt;&lt;b&gt; What led you to try Lisp?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;I was looking for A Better Way than C for version two of my algebra tutorial. I knew I wanted OO because I could see in my C code that I was using structs in an OO kinda way. I also knew I wanted a dynamic, interactive development environment and it had to run on the Mac where I made most of my sales. &lt;/p&gt;&lt;p&gt;The first thing I tried was Stoney Ballard's Component Workshop, a brave attempt at a dynamic C++ which never even got to "Hello world" before Stoney gave up. Then I got Symantec C++ (I had used it when it was Michael Kahl's Think C) and freaked out when I saw incremental linking was gone and every edit-run cycle now included a twenty second link from scratch. And I was just appalled by C++ the language. &lt;/p&gt;&lt;p&gt;Next up was SmalltalkAgents from Quasar Knowledge Systems. QKS kept saying how great they were and how great they were going to be. Perhaps, but not by crashing my Mac every five minutes. &lt;/p&gt;&lt;p&gt;I then announced on Compuserve's MACDEV forum that I was giving up and was going to use C++,when a kind soul from Cambridge, Mass suggested I look at MCL. He said it was compiled, fast, mature, object-oriented and a few other things. &lt;/p&gt;&lt;p&gt;Well the amazing thing is that I had been skipping MCL ads in the Apple Developer association catalog for months because of my earlier experience with Logo. I had no idea of the progress in Lisp compilers. &lt;/p&gt;&lt;p&gt;I also had come incredibly close when I got the pre-alpha Dylan CD from Apple Computer and played with that. Dylan was being developed for Apple by Digitool and it ran atop (wait for it) Macintosh Common Lisp! Who knew? &lt;/p&gt;&lt;p&gt;But having read the message from Cambridge I promptly ordered a copy of MCL. It came a few days later and just while assembling the manual pages into a binder I concluded I had found The One. I gave the install CD to my two developers, told them to dump QKS, then ordered two more copies to stay honest. &lt;/p&gt;&lt;p&gt;The next few weeks involved everyone taking turns running to each others desk to show them neat new features we had just discovered and I have never looked back.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt; If you were trying Lisp out of unhappiness with another language, what was it and what did you not like about it, or what about Lisp were you hoping to find different?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;I wanted a dynamic development modality, no linker especially. And an end to pointers and dereferencing and manual memory management. ie, I was looking for a better way than C and when I looked at C++ I did not find it. &lt;/p&gt;&lt;p&gt;&lt;b&gt; How far have you gotten in your study of Lisp?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;Well, it's been thirteen years, so as an application developer I am fluent.  &lt;/p&gt;&lt;p&gt;&lt;b&gt; What do you think of Lisp so far?&lt;/b&gt;  &lt;/p&gt;&lt;p&gt;Perfect. Whatever it does not do, macros let me coax from CL. Being able to restart from a backtrace after hours of debugging or while trying twenty things a minute apart to get something working is an enormous win. CLOS is unspeakably powerful. A simple thing like special variables is magnificent when you really need them. Of course garbage collection is a stupendous win. The speed is crucial. Multiple inheritance and multi-methods are vital. &lt;/p&gt;&lt;p&gt;One thing a lot of newbies experience as did I is that when I go to find out how some function works it always turns out to work just the way I happen at that time to expect or want or need it to work. Clearly Common Lisp is the product of a long history of refinement by good engineers with a strong ethic of doing things well. &lt;/p&gt;&lt;p&gt;And if you have to know, Lawdy, I never want to edit without parentheses again. When reworking code the code tree is perfect for moving chunks of semantics around. And the autoindentation is a significant time saver. I refactor a lot so a lot of time in other languages goes into tediously realigning code. &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-705534537697359539?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/705534537697359539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=705534537697359539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/705534537697359539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/705534537697359539'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/my-road-to-lisp.html' title='My Road to Lisp'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-7920986157284478240</id><published>2008-02-11T02:02:00.002-05:00</published><updated>2010-12-22T18:17:36.189-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silver bullet'/><category scheme='http://www.blogger.com/atom/ns#' term='Dataflow'/><category scheme='http://www.blogger.com/atom/ns#' term='Functional reactive programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Common Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Flapjax'/><category scheme='http://www.blogger.com/atom/ns#' term='Trellis'/><category scheme='http://www.blogger.com/atom/ns#' term='Cells'/><title type='text'>The Cells Manifesto</title><content type='html'>&lt;i&gt;[We may as well get this out of the way, an explanation of my pet project Cells, the kind of thing I'll be sitting in a rocking chair twenty years from now mumbling how the CIA stole it from me but they don't have the latest version I have that in a floppy disk here in my shirt pocket.]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;In the text that follows, [xxx] signifies a footnote named "xxx" and&lt;br /&gt;listed alphabetically at the end.&lt;br /&gt;                   &lt;br /&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;Cells is a mature, stable extension to CLOS[impl] allowing one to create classes whose instances can have slot values determined by instance-specific formulas. It is useful for any application involving an interesting amount of long-lived state and a stream of unpredictable inputs. Two examples are any GUI-based application and a RoboCup client (trying to simulate a soccer player given a stream of sensory data fed it by the game server).&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Example&lt;/u&gt;&lt;br /&gt;For example, in a text editor application we might have (condensed, and with the symbol ".w." macroexpanding to code that returns the relevant window)):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; (make-instance 'menu-item&lt;br /&gt;:label "Cut"&lt;br /&gt;:enabled (c? (bwhen (f (focus .w.))&lt;br /&gt;                       (and (typep f 'text-widget)&lt;br /&gt;     (selection-range f)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Translated, the enabled state of the Cut menu item follows whether or not the user is focused on a text-edit widget and whether they have in fact selected a range of text, the trick being that nil is treated as false by (decent) Lisp dialects.&lt;br /&gt;&lt;br /&gt;Meanwhile, the selection-range rule might be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(let (start)&lt;br /&gt; (c? (if (mouse-down? .w.)&lt;br /&gt;         (bwhen (c (mouse-pos-to-char self (mouse-pos .w.)))&lt;br /&gt;           (if start&lt;br /&gt;               (list start c)&lt;br /&gt;             (setf start c)))&lt;br /&gt;       (setf start nil))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now the only imperative code needed is some glue reading the OS event loop onverting raw mouse down and mouse move events into window attributes such as mouse-down? and mouse-pos. The desired functionality is achieved by declarative rules which (like selection-range above) are entirely responsible for deciding the selection range.&lt;br /&gt;&lt;br /&gt;A final trick comes from slot observers. Suppose we are thinly wrapping a C GUI and need to do something in the C library to actually make menu items available or not.  It might look something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defobserver enabled ((self menu-item) new-value old-value old-value-bound?)&lt;br /&gt;    (menu-item-set (c-ptr self) (if new-value 1 0)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ie, Some model attributes must be propagated outside the model as they change, and observers are callbacks we can provide to handle change.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Motivation&lt;/u&gt;&lt;br /&gt;As a child I watched my father toil at home for hours over paper spreadsheets with pencil and slide rule. After he changed one value, he had to propagate that change to other cells by first remembering which other ones included the changed cell in their computation. Then he had to do the calculations for those, erase, enter...and then repeat that process to propagate those changes in a cascade across the paper.&lt;br /&gt;&lt;br /&gt;VisiCalc let my father take the formula he had in mind and put it into (declare it to) the electronic spreadsheet. Then VisiCalc could do the tedious work: recalculating, knowing what to recalculate, and knowing in what order to recalculate.&lt;br /&gt;&lt;br /&gt;Cells do for programmers what electronic spreadsheets did for my father. Without Cells, CLOS slots are like cells of a paper spreadsheet. A single key-down event can cause a cascade of change throughout an application. The programmer has to arrange for it all to happen, all in the right order: delete any selected text, insert the new character, re-wrap the text, update the undo mechanism, revisit the menu statuses ("Cut" is no longer enabled), update the scroll bars, possibly scroll the window, flag the file as unsaved...&lt;br /&gt;&lt;br /&gt;Here is a real-world case study:&lt;br /&gt;&lt;br /&gt;"The last company I worked with made a product that was a control unit for some mechanical devices, presenting both sensor readings coming in from those devices and an interface to program the devices. Consider it like a very sophisticated microwave oven, perhaps with a temperature probe.&lt;br /&gt;&lt;br /&gt;"The UI code was a frighteningly complex rat's nest. Input data arriving from the sensors changed certain state values, which caused the display to update, but the system state also changed, and rules had to be evaluated, the outcome of which might be tuning to the running job or warning messages presented to the user, and in the meantime the user may be adjusting the running job. I'm sure there are even more interactions I'm leaving out.&lt;br /&gt;&lt;br /&gt;"There was no "large idea" in this code to organize these dependencies or orchestrate the data flow. The individual facilities were well-formed enough: "message" input and output, GUI widgets and forms, real-world entities modeled as entities in the code. However, the connections between these things were ad-hoc and not formalized. Every change to the system would provoke defects, and the failure usually involved not propagating some event, propagating it at the wrong time, or propagating it to the wrong recipients."&lt;br /&gt;--- Steven Harris, on comp.lang.lisp&lt;br /&gt;&lt;br /&gt;What Mr. Harris describes is what Fred Brooks [bullet] said was an essential property of software development, meaning by essential that there was no way around it, and thus his prediction that a software silver bullet was in principle impossible.&lt;br /&gt;&lt;br /&gt;Which brings us to Cells. See also [axiom] Phillip Eby's developing axiomatic definition he is developing in support of Ryan Forseth's SoC project.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;DEFMODEL and Slot types&lt;/u&gt;&lt;br /&gt;Classes, some of whose slots may be mediated by Cells, are defined by DEFMODEL, which is exactly like DEFCLASS but adds support for two slot definition options, :cell and :unchanged-if. Classes defined by DEFMODEL can inherit from normal CLOS classes.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;New slot definition options&lt;/u&gt;&lt;br /&gt;:cell {nil | t | :ephemeral}&lt;br /&gt;&lt;br /&gt;:cell is optional. The default is ":cell t", meaning the Cells engine will manage the slot to give it the spreadsheet-like characteristics. Specifying NIL signifies that this slot is entirely outside any handling by the Cells engine; it is just a plain CLOS slot.&lt;br /&gt;&lt;br /&gt;This next bit will not make sense until we have explained propagation of state change, but specifying :ephemeral causes the Cells engine to reset the apparent slot  value to NIL immediately and only after fully propagating any value assumed by the slot, either by assignment to an input Cell (the vastly more common case) or by a rule calculation.&lt;br /&gt;&lt;br /&gt;Ephemeral cells are necessary to correctly model events in the otherwise steady-state spreadsheet paradigm.&lt;br /&gt;&lt;br /&gt;:unchanged-if &lt;function-name&gt;&lt;br /&gt;&lt;br /&gt;Specifying :unchanged-if is optional. [Come to think of it, it should be an error to specify both :cell nil and :unchanged-if.] If specified, the named function is a predicate of two arguments, the new and old value in that order. The predicate determines if a subsequent slot value (either computed or assigned to an input) is unchanged in the sense that no propagation is necessary, either to dependent ruled cells or (getting ahead of ourselves again) "on change" observers.&lt;br /&gt;The default unchanged test is EQL.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Cell types&lt;/u&gt;&lt;br /&gt;The Cells library allows the programmer to specify at make-instance time that a Cell slot of an instance be mediated for the life of that instance by one of:&lt;br /&gt;&lt;br /&gt;-- a so-called "input" Cell;&lt;br /&gt;-- a "ruled" Cell; or&lt;br /&gt;-- no Cell at all.&lt;br /&gt;&lt;br /&gt;Note that different instances of the same class may do different things Cells-wise with the same slot. One label widget may have a fixed width of 42 and text "Hi, Mom!", where another might have an input Cell mediating the text (so edit logic can assign new values as the user types) and a rule mediating the width so the widget can have a minimum width of 42(so it does not disappear altogether) yet grow based on text length and relevant font metrics to always leave room for one more character (if the GUI design calls for that).&lt;br /&gt;&lt;br /&gt;To summarize, the class specification supplied with DEFMODEL specifies whether a slot can /ever/ be managed by the Cells engine. For those that can, at and only at instance initialization time different instances can have different Cell types and rules specified to mediate the same slot.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Input Cells&lt;/u&gt;&lt;br /&gt;A slot mediated by an input Cell may be assigned new values at runtime. These are how Cell-based models get data from the world outside the model -- it cannot be rules all the way down. Typically, these input assignements are made by code polling OS events via some GetNextEvent API call, or by callbacks registered with an event system such as win32 WindowProc functions. Other code may poll sockets or  serial inputs from an external device.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ruled Cells&lt;/u&gt;&lt;br /&gt;Ruled Cells come with an instance-specific  rule in the form of an anonymous function of two variables, the instance owning the slot and the prior value (if any) computed by the rule. These rules consist of arbitrarily complex Common Lisp code, and are invoked immediately after instance initialization (but see the next bit on lazy cells).&lt;br /&gt;&lt;br /&gt;When a rule runs, any dynamic read (either expressly in the rule source or during the execution of  some function invoked by the rule) of a slot of any instance mediated by a Cell of any type establishes a runtime dependency of the ruled cell on the slot of the instance that was read. Note then that thanks to code branching, dependencies can vary after every rule invocation.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Lazy Ruled Cells&lt;/u&gt;&lt;br /&gt;Laziness is cell-specific, applies only to ruled cells, and comes in four varieties:&lt;br /&gt;&lt;br /&gt;:once-asked -- this will get evaluated and "observed" on initialization, but then not get reevaluated immediately if dependencies change, rather only when read by application code.&lt;br /&gt;&lt;br /&gt;:until-asked  -- this does not get evaluated/observed until read by application code, but then it becomes un-lazy, eagerly reevaluated as soon as any dependency changes (not waiting until asked).&lt;br /&gt;&lt;br /&gt;:always -- not evaluated/observed until read, and not reevaluated until read after a dependency changes.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Dataflow&lt;/u&gt;&lt;br /&gt;When application code assigns a new value to an input Cell (a quick way of saying an instance slot mediated by an input Cell) -- typically by code polling OS events or a socket or an input device -- a cascade of recalculation ensues to bring direct and indirect ruled dependents current with the new value assigned to the input Cell.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;No Cell at All&lt;/u&gt;&lt;br /&gt;Because of all that, it is an error to assign a new value to a slot of an instance not mediated by any Cell. The Cells engine can do a handy optimization by treating such slots as constants and not creating dependencies when ruled Cells read these. But then we cannot let these Cells vary and still guarantee data integrity, because we no longer know who else to update in light of such variation. The optimization, by the way, extends to eliminating ruled Cells which, after any computation, end up not depending on any other cell.&lt;br /&gt;&lt;br /&gt;Again, note that this is different from specifying ":cell nil" for some slot. Here, the Cells engine has been told to manage some slot, but for some instance the slot has been authored to bear some value for the lifetime of that instance.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Observers&lt;/u&gt;&lt;br /&gt;To allow the emergent animated data model to operate usefully on the world outside the model--if only to update the screen--programmers may specify so-called observer callbacks dispatched according to: slot name, instance, new value, old value, and whether the old value actually existed (false only on the first go). Observers are inherited according to the rules of CLOS class inheritance. If multiple primary observer methods apply because of inheritance, they all get run, most specific last.&lt;br /&gt;&lt;br /&gt;ie, observers are a GF with PROGN method combination.&lt;br /&gt;&lt;br /&gt;Observers get called in two circumstances: as part of Model object initialization, in a processing step just after CLOS instance initialization, and when a slot changes value. Any observer of a Cell slot is guaranteed to be called at least once during intialization even if a cell slot is bound to a constant or if it is an input or ruled Cell that never changes value.&lt;br /&gt;&lt;br /&gt;It is legal for observer code to assign to input Cells, but (a) special syntax is required to defer execution until the observed state change has fully propagated; and (b) doing so compromises the declarative quality of an application -- one can no longer look to one rule to see how a slot (in this case the input slot being assigned by the observer) gets its value. A reasonable usage might be one with a cycle, where changing slot A requires a change to slot B, and changing slot B requires a change to slot A, such as the scroll thumb position and the amount a document has been scrolled.&lt;br /&gt;&lt;br /&gt;Finally, to make it possible for such a declarative model to talk intelligibly to imperative systems such as Tcl/Tk which sometimes requires a precise sequence of commands for something to work at all, a mechanism exists by which client code can (a) queue tasks for execution after a data change has fully propagated and (b) process those tasks with a client-supplied handler. Tasks are queued with arbitrary keying data which can be used by the handler to sort or compress the queued tasks.&lt;br /&gt;&lt;br /&gt;                             &lt;br /&gt;&lt;u&gt;Data Integrity&lt;/u&gt;&lt;br /&gt;When application code assigns to some input cell X, the Cells engine guarantees:&lt;br /&gt;&lt;br /&gt;- recomputation exactly once of all and only state affected by the change to X, directly or indirectly through  some intermediate datapoint. note that if A depends on B, and B depends on X, when B gets recalculated it may come up with the same value as before. In this case A is not considered to have been affected  by the change to X and will not be recomputed.&lt;br /&gt;&lt;br /&gt;- recomputations, when they read other datapoints, must see only values current with the new value of X.  Example: if A depends on B and X, and B depends on X, when X changes and A reads B and X to compute a new value, B must return a value recomputed from the new value of X.&lt;br /&gt;&lt;br /&gt;- similarly, client observer callbacks must see only values current with the new value of X; and&lt;br /&gt;&lt;br /&gt;- a corollary: should a client observer SETF a datapoint Y, all the above must&lt;br /&gt;happen with values current with not just X, but also with the value of Y /prior/&lt;br /&gt;to the change to Y.&lt;br /&gt;&lt;br /&gt;- Deferred "client" code must see only values current with X and not any values current with some subsequent change to Y queued by an observer&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Benefits&lt;/u&gt;&lt;br /&gt;Program state guaranteed to be self-consistent, without programmer effort. Dependencies are identified&lt;br /&gt;by the engine, and change propagation happens automatically.&lt;br /&gt;&lt;br /&gt;Greater object re-use. Slots of instances can be authored with rules, not just literal values. In a sense, we get greater reuse by allowing instances to override slot derivations instance by instance. But not slot expressions, which are still class-oriented. By this I mean the observers expressing changes in value are dispatched by the class of the instance and so are not instance-specific. (Such a thing has been suggested, however.) Another strong bit of class-orientation comes from the fact that code reading slot X of some instance Y obviously does so without knowing how the returned value was derived. It knows only that the slot is named X, and will do things with that value assuming only that it has the X attribute of the instance Y. So again: the derivation of a slot value is potentially instance-oriented under Cells, but its expression or manifestation is still class-oriented.&lt;br /&gt;&lt;br /&gt;Natural decomposition of overall application complexity into so many simple rules and slot observers. Let's return for a moment to VisiCalc and its descendants. In even the most complex financial spreadsheet model, no one cell rule accesses more than a relatively few other spreadsheet cells (counting a row or column range as one reference). Yet the complex model emerges. All the work of tracking dependencies is handled by the spreadsheet software, which requires no special declaration by the modeller. They simply write the Cell rule. In writing the rule, they are concerned only with the derivation of one datapoint from a population of other datapoints. No effort goes into arranging for the rule to get run at the right time, and certainly no energy is spent worrying about what other cells might be using the authored cell. That cell has certain semantics -- "account balance", perhaps -- and the modeller need only worry about writing a correct, static computation of those semantics.&lt;br /&gt;&lt;br /&gt;Same with Cells. :) The only difference is that VisiCalc has one "observer" requirement for all cells: update the screen. In Cells applications, a significant amount of application functionality -- indeed, all its outputs -- end up in cell observers. But as discussed above, this additional burden falls only on the class designer when they decide to add a slot to a class. As instances are created and different rules specified for different slots to achieve custom behavior, the effort is the same as for the VisiCalc user.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Model Building&lt;/u&gt;&lt;br /&gt;Everything above could describe one instance of one class defined by DEFMODEL. A real application has multiple instances of multiple classes. So...&lt;br /&gt;&lt;br /&gt;-- cells can depend on other cells from any other instance. Since a rule gets passed only "self", Cell users need something like the Family class included with the Cells package effectively to turn a collection of instances into a network searchable by name or type.&lt;br /&gt;&lt;br /&gt;-- The overall model population must be maintainable by Cell slots such as the "kids" slot of the Family class. The burden here is on the Cells engine to allow one cell of one child to ask for the value of a cell of another child and vice versa (with different Cells), when both children are the product of the same rule, or different rules when "cousins" are exchanging information. So we must gracefully traverse the parent/kids tree dispatching kids rules just in time to produce the other instance sought.&lt;br /&gt;&lt;br /&gt;-- kid-slotting: used almost exclusively so far for orderly GUI layout, a parent must be able to specify rules for specific slots of kids. Example: a "stack" class wants to provide rules for child geometry specifying left, right, or centered alignment and vertical stacking (with optional spacing) one below the other. The idea is that we want to author classes of what might be GUI subcomponents without worrying about how they will be arranged in some container.&lt;br /&gt;&lt;br /&gt;-- finalization: when an instance appears in the "old kids" but not in the "new kids", a Cells engine may need to arrange for all Cells to "unsubscribe" from their dependents. Cells takes care of that if one calls "not-to-be" on an instance.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Suggested Applications&lt;/u&gt;&lt;br /&gt;Any application that must maintain an interesting, long-lived data model incorporating a stream of unpredictable data. Two examples: any GUI application and a RoboCup soccer client.&lt;br /&gt;&lt;br /&gt;An application needing to shadow data between two systems. Examples: a Lisp GUI imlemented by thinly wrapping a C GUI library, where Lisp-land activity must be propagated to the C GUI, and C GUI events must propagate to Lisp-land. See the Cells-Gtk or Celtk projects. Also, a persistent CLOS implementation that must echo CLOS instance data into, say, SQL tables.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Prior Art (in increasing order of priorness (age))&lt;/u&gt;&lt;br /&gt;Functional reactive programming:&lt;br /&gt;This looks to be the most active, current, and vibrant subset of folks working on this sort of stuff.&lt;br /&gt;Links:&lt;br /&gt;FlapJax (FRP-powered web apps) http://www.flapjax-lang.org/&lt;br /&gt;http://lambda-the-ultimate.org/node/1771&lt;br /&gt;http://www.haskell.org/frp/&lt;br /&gt;FrTime (scheme FRP implementation, no great links) http://pre.plt-scheme.org/plt/collects/frtime/doc.txt&lt;br /&gt;&lt;br /&gt;Adobe Adam, originally developed only to manage complex GUIs. [Adam]&lt;br /&gt;&lt;br /&gt;COSI, a class-based Cells-alike used at STSCI in software used to&lt;br /&gt;schedule Hubble telescope viewing time. [COSI]&lt;br /&gt;&lt;br /&gt;Garnet's KR: http://www.cs.cmu.edu/~garnet/&lt;br /&gt;Also written in Lisp. Cells looks  much like KR, though Cells was&lt;br /&gt;developed in ignorance of KR (or any other prior art). KR has&lt;br /&gt;an astonishing number of backdoors to its constraint&lt;br /&gt;engine, none of which have turned out to be necessary for Cells.&lt;br /&gt;&lt;br /&gt;The entire constraint programming field, beginning I guess with Guy Steele's&lt;br /&gt;PhD Thesis in which he develops a constraint programming language or two:&lt;br /&gt;http://portal.acm.org/citation.cfm?id=889490&amp;amp;dl=ACM&amp;amp;coll=ACM&lt;br /&gt;http://www.cs.utk.edu/~bvz/quickplan.html&lt;br /&gt;&lt;br /&gt;Sutherland, I. Sketchpad: A Man Machine Graphical Communication System. PhD thesis, MIT, 1963.&lt;br /&gt;Steele himself cites Sketchpad as inexplicably unappreciated prior&lt;br /&gt;art to his Constraints system:&lt;br /&gt;&lt;br /&gt;See also:&lt;br /&gt;The spreadsheet paradigm: http://www.cs.utk.edu/~bvz/active-value-spreadsheet.html&lt;br /&gt;The dataflow paradigm: http://en.wikipedia.org/wiki/Dataflow&lt;br /&gt;Frame-based programming&lt;br /&gt;Definitive-programming&lt;br /&gt;&lt;br /&gt;Commentary&lt;br /&gt;----------&lt;br /&gt;-- Jack Unrue, comp.lang.lisp&lt;br /&gt;"Cells provides the plumbing for data dependency management which every&lt;br /&gt;non-trivial program must have; a developer using Cells can focus on&lt;br /&gt;computing program state and reacting to state changes, leaving Cells to worry about&lt;br /&gt;how that state is propagated. Cells does this by enabling a declarative&lt;br /&gt;mechanism built via an extension to CLOS, and hence achieves its goal in a way&lt;br /&gt;that meshes well with with typical Common Lisp programming style."&lt;br /&gt;&lt;br /&gt;-- Bill Clementson, http://bc.tech.coop/blog/030911.html&lt;br /&gt;"Kenny Tilton has been talking about his Cells implementation on comp.lang.lisp&lt;br /&gt;for some time but I've only just had a look at it over the past few evenings.&lt;br /&gt;It's actually pretty neat. Kenny describes Cells as, conceptually, analogous to&lt;br /&gt;a spreadsheet cell (e.g. -- something in which you can put a value or a formula&lt;br /&gt;and have it updated automatically based on changes in other "cell" values).&lt;br /&gt;Another way of saying this might be that Cells allows you to define classes&lt;br /&gt;whose slots can be dynamically (and automatically) updated and for which&lt;br /&gt;standard observers can be defined that react to changes in those slots."&lt;br /&gt;&lt;br /&gt;-- "What is Cells?", Cells-GTk FAQ, http://common-lisp.net/project/cells-gtk/faq.html#q2&lt;br /&gt;"If you are at all familiar with developing  moderately complex software that&lt;br /&gt;is operated through a GUI, then you have probably&lt;br /&gt;learned this lesson: Keeping what is presented through the GUI in-sync with what&lt;br /&gt;the user is allowed to do, and in-sync with the computational state of the&lt;br /&gt;program is often tedious, complicated work. .... Cells-GTK helps&lt;br /&gt;with these tasks by providing an abstraction over the details; each of the tasks&lt;br /&gt;just listed can be controlled by (a) formula that specify the value of&lt;br /&gt;attributes of graphic features in the part-subpart declaration (that declaration&lt;br /&gt;is called 'defpart' in cells-gtk); and, (b) formula that specify the value of CLOS slots."&lt;br /&gt;&lt;br /&gt;-- Phillip Eby, PyCells and peak.events,&lt;br /&gt;http://www.eby-sarna.com/pipermail/peak/2006-May/002545.html&lt;br /&gt;"What I discovered is quite cool.  The Cells system *automatically&lt;br /&gt;discovers* dynamic dependencies, without having to explicitly specify that&lt;br /&gt;X depends on Y, as long as X and Y are both implemented using cell&lt;br /&gt;objects.  The system knows when you are computing a value for X, and&lt;br /&gt;registers the fact that Y was read during this computation, thus allowing&lt;br /&gt;it to automatically invalidate the X calculation if Y changes....&lt;br /&gt;Aside from the automatic dependency detection, the cells system has&lt;br /&gt;another trick that is able to significantly reduce the complexity of&lt;br /&gt;event cascades, similar to what I was trying (but failing) to do using&lt;br /&gt;the "scheduled thread" concept in peak.events.&lt;br /&gt;Specifically, the cells system understands how to make event-based updates&lt;br /&gt;orderly and deterministic, in a way that peak.events cannot.  It&lt;br /&gt;effectively divides time into "propagation" and "non-propagation"&lt;br /&gt;states.  Instead of simply making callbacks whenever a computed value&lt;br /&gt;changes, the system makes orderly updates by queueing invalidated cells for&lt;br /&gt;updating.  Also, if you write code that sets a new value imperatively (as&lt;br /&gt;opposed to it being pulled declaratively), the actual set operation is&lt;br /&gt;deferred until all computed cells are up-to-date with the current state of&lt;br /&gt;the universe."&lt;br /&gt;&lt;br /&gt;_____________&lt;br /&gt;Uncommentary&lt;br /&gt;&lt;br /&gt;&lt;/function-name&gt;&lt;div&gt;&lt;function-name&gt;-- Josh Marchan, internal company email:&lt;/function-name&gt;&lt;/div&gt;&lt;div&gt;&lt;function-name&gt;"some obscure technology that only theoretically benefits us.... I'm not even sure what the advantage here would be."&lt;/function-name&gt;&lt;/div&gt;&lt;div&gt;&lt;function-name&gt;&lt;br /&gt;-- Peter Seibel, comp.lang.lisp:&lt;br /&gt;"I couldn't find anything that explained what [Cells] was and why I should care."&lt;br /&gt;&lt;br /&gt;-- Alan Crowe, comp.lang.lisp:&lt;br /&gt;"Further confession: I'm bluffing. I've grasped that Cells is&lt;br /&gt;interesting, but I haven't downloaded it yet, and I haven't&lt;br /&gt;checked out how it works or what /exactly/ it does."&lt;br /&gt;&lt;br /&gt;_________               &lt;br /&gt;Footnotes&lt;br /&gt;&lt;br /&gt;[Adam] "Adam is a modeling engine and declarative language for describing constraints and&lt;br /&gt;relationships on a collection of values, typically the parameters to an&lt;br /&gt;application command. When bound to a human interface (HI) Adam provides&lt;br /&gt;the logic that controls the HI behavior. Adam is similar in concept to a spreadsheet&lt;br /&gt;or a forms manager. Values are set and dependent values are recalculated.&lt;br /&gt;Adam provides facilities to resolve interrelated dependencies and to track&lt;br /&gt;those dependencies, beyond what a spreadsheet provides."&lt;br /&gt;http://opensource.adobe.com/group__asl__overview.html#asl_overview_intro_to_adam_and_eve&lt;br /&gt;________&lt;br /&gt;[bullet] This resolves a problem Fred Brooks identified in 1987: ""The essence of a software&lt;br /&gt;entity is a construct of  interlocking concepts: data sets, relationships among data items, algorithms,&lt;br /&gt;and invocations of functions... Software systems have orders-of-magnitude more states than&lt;br /&gt;computers do...a scaling-up of a software  entity is not merely a repetition of the same elements&lt;br /&gt;in larger sizes; it is necessarily an increase in the number of different elements. In most cases,&lt;br /&gt;the elements interact with each other in some nonlinear fashion, and the complexity of the whole&lt;br /&gt;increases much more than linearly."&lt;br /&gt;-- http://www.virtualschool.edu/mon/SoftwareEngineering/BrooksNoSilverBullet.html&lt;br /&gt;______&lt;br /&gt;[COSI] "The Constraint Sequencing Infrastructure (COSI) is an extension to&lt;br /&gt;the Common Lisp Object System (*(CLOS)) which supports a constraint&lt;br /&gt;based object-oriented programming model. .....&lt;br /&gt;&lt;br /&gt;"A constraint is a specialized method which will be automatically&lt;br /&gt;re-run by the COSI infrastructure whenever any of its input values&lt;br /&gt;change. Input values are any of the object attributes that are&lt;br /&gt;accessed by the constraint, and which are therefore assumed to&lt;br /&gt;alter the processing within the constraint.&lt;br /&gt;&lt;br /&gt;"Whenever a state change occurs those constraints which depend upon&lt;br /&gt;that state are added to a propagation queue. When the system is&lt;br /&gt;queried a propagation cycle runs ensuring that the state of the&lt;br /&gt;system is consistent with all constraints prior to returning a value."&lt;br /&gt;-- http://www.cliki.net/ACL2/COSI?source&lt;br /&gt;______&lt;br /&gt;[impl] The Cells library as it stands is all about doing interesting things&lt;br /&gt;with slots of CLOS instances, but Cells is not only about CLOS or even Lisp.&lt;br /&gt;One Cells user is known to have mediated a global variable with a Cell, some work&lt;br /&gt;was done on having slots of DEFSTRUCTs mediated by Cells, and ports to C++, Java, and&lt;br /&gt;Python have been explored.&lt;br /&gt;&lt;br /&gt;_______&lt;br /&gt;[axiom] Phillip Eby's axiomatic specification of Cells:&lt;br /&gt;&lt;br /&gt;Data Pulse Axioms&lt;br /&gt;=================&lt;br /&gt;&lt;br /&gt;Overview: updates must be synchronous (all changed cells are updated at&lt;br /&gt;once), consistent (no cell rule sees out of date values), and minimal (only&lt;br /&gt;necessary rules run).&lt;br /&gt;&lt;br /&gt;1. Global Update Counter:&lt;br /&gt;There is a global update counter. (Guarantees that there is a&lt;br /&gt;globally-consistent notion of the "time" at which updates occur.)&lt;br /&gt;&lt;br /&gt;2. Per-Cell "As Of" Value:&lt;br /&gt;Every cell has a "current-as-of" update count, that is initialized with&lt;br /&gt;a value that is less than the global update count will ever be.&lt;br /&gt;&lt;br /&gt;3. Out-of-dateness:&lt;br /&gt;A cell is out of date if its update count is lower than the update&lt;br /&gt;count of any of the cells it depends on.&lt;br /&gt;&lt;br /&gt;4. Out-of-date Before:&lt;br /&gt;When a rule-driven cell's value is queried, its rule is only run if the&lt;br /&gt;cell is out of date; otherwise a cached previous value is&lt;br /&gt;returned.  (Guarantees that a rule is not run unless its dependencies have&lt;br /&gt;changed since the last time the rule was run.)&lt;br /&gt;&lt;br /&gt;5. Up-to-date After:&lt;br /&gt;Once a cell's rule is run (or its value is changed, if it is an input&lt;br /&gt;cell), its update count must be equal to the global update&lt;br /&gt;count.  (Guarantees that a rule cannot run more than once per update.)&lt;br /&gt;&lt;br /&gt;6. Inputs Move The System Forward&lt;br /&gt;When an input cell changes, it increments the global update count and&lt;br /&gt;stores the new value in its own update count.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dependency Discovery Axioms&lt;br /&gt;===========================&lt;br /&gt;&lt;br /&gt;Overview: cells automatically notice when other cells depend on them, then&lt;br /&gt;notify them at most once if there is a change.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1. Thread-local "current rule cell":&lt;br /&gt;There is a thread-local variable that always contains the cell whose&lt;br /&gt;rule is currently being evaluated in the corresponding thread.  This&lt;br /&gt;variable can be empty (e.g. None).&lt;br /&gt;&lt;br /&gt;2. "Currentness" Maintenance:&lt;br /&gt;While a cell rule's is being run, the variable described in #1 must be&lt;br /&gt;set to point to the cell whose rule is being run.  When the rule is&lt;br /&gt;finished, the variable must be restored to whatever value it had before the&lt;br /&gt;rule began.  (Guarantees that cells will be able to tell who is asking for&lt;br /&gt;their values.)&lt;br /&gt;&lt;br /&gt;3. Dependency Creation:&lt;br /&gt;When a cell is read, it adds the "currently-being evaluated" cell as a&lt;br /&gt;listener that it will notify of changes.&lt;br /&gt;&lt;br /&gt;4. Dependency Creation Order:&lt;br /&gt;New listeners are added only *after* the cell being read has brought&lt;br /&gt;itself up-to-date, and notified any *previous* listeners of the&lt;br /&gt;change.  (Ensures that the listening cell does not receive redundant&lt;br /&gt;notification if the listened-to cell has to be brought up-to-date first.)&lt;br /&gt;&lt;br /&gt;5. Dependency Minimalism:&lt;br /&gt;A listener should only be added if it does not already present in the&lt;br /&gt;cell's listener collection.  (This isn't strictly mandatory, the system&lt;br /&gt;behavior will be correct but inefficient if this requirement isn't met.)&lt;br /&gt;&lt;br /&gt;6. Dependency Removal:&lt;br /&gt;Just before a cell's rule is run, it must cease to be a listener for&lt;br /&gt;any other cells.  (Guarantees that a dependency from a previous update&lt;br /&gt;cannot trigger an unnecessary repeated calculation.)&lt;br /&gt;&lt;br /&gt;7. Dependency Notification&lt;br /&gt;Whenever a cell's value changes (due to a rule change or input change),&lt;br /&gt;it must notify all of its listeners that it has changed, in such a way that&lt;br /&gt;*none* of the listeners are asked to recalculate their value until *all* of&lt;br /&gt;the listeners have first been notified of the change.  (This guarantees&lt;br /&gt;that inconsistent views cannot occur.)&lt;br /&gt;&lt;br /&gt;7a. Deferred Recalculation&lt;br /&gt;The recalculation of listeners (not the notification of the listeners'&lt;br /&gt;out-of-dateness) must be deferred if a cell's value is currently being&lt;br /&gt;calculated.  As soon as there are no cells being calculated, the deferred&lt;br /&gt;recalculations must occur.  (This guarantees that in the absence of&lt;br /&gt;circular dependencies, no cell can ask for a value that's in the process of&lt;br /&gt;being calculated.)&lt;br /&gt;&lt;br /&gt;8. One-Time Notification Only&lt;br /&gt;A cell's listeners are removed from its listener collection as soon as&lt;br /&gt;they have been notified.  In particular, the cell's collection of listeners&lt;br /&gt;must be cleared *before* *any* of the listeners are asked to recalculate&lt;br /&gt;themselves.  (This guarantees that listeners reinstated as a side effect of&lt;br /&gt;recalculation will not get a duplicate notification in the current update,&lt;br /&gt;or miss a notification in a future update.)&lt;br /&gt;&lt;br /&gt;9. Conversion to Constant&lt;br /&gt;If a cell's rule is run and no dependencies were created, the cell must&lt;br /&gt;become a "constant" cell, and do no further listener additions or&lt;br /&gt;notification, once any necessary notifications to existing listeners are&lt;br /&gt;completed.  (That is, if the rule's run changed the cell's value, it must&lt;br /&gt;notify its existing listeners, but then the listener collection must be&lt;br /&gt;cleared -- *again*, in addition to the clearing described in #8.)&lt;br /&gt;&lt;br /&gt;10. No Changes During Notification:&lt;br /&gt;It is an error to change an input cell's value while change&lt;br /&gt;notifications are taking place.&lt;br /&gt;&lt;br /&gt;11. Weak Notification&lt;br /&gt;Automatically created inter-cell links must not inhibit garbage&lt;br /&gt;collection of either cell.  (Technically optional, but very easy to do.)&lt;/function-name&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-7920986157284478240?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/7920986157284478240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=7920986157284478240' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7920986157284478240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/7920986157284478240'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html' title='The Cells Manifesto'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6508797467947601724.post-432224683968201822</id><published>2008-02-09T20:45:00.001-05:00</published><updated>2008-02-12T16:46:57.336-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='alan turing'/><category scheme='http://www.blogger.com/atom/ns#' term='paul graham'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>All Your Parenthesis Are Belong to Us</title><content type='html'>&lt;span style="font-size:100%;"&gt;About the name. Just google it. You will find two kinds of mention. In one kind the author has never tried Lisp and is afraid of it and is trying to make Lisp advocates feel bad. In the other kind the author has tried Lisp and says no wonder Lispers are so smug.&lt;br /&gt;&lt;br /&gt;OK, but why is it the name of this blog? Think of Queer Nation embracing the epithet. I'll have more to say another time about &lt;a href="http://en.wikipedia.org/wiki/Alan_Turing"&gt;Turing&lt;/a&gt; who invented the computer just to prove a theorem, but long before &lt;a href="http://en.wikipedia.org/wiki/Stonewall_riots"&gt;Stonewall&lt;/a&gt; he refused to deny his affection for men at a time &lt;span style="font-style: italic;"&gt;in my lifetime&lt;/span&gt; when England jailed people for whom they liked and got prosecuted for his courage even though he had single-handedly turned back the Nazis by parachuting onto an Enigma factory to steal one of the machines. I think I have that right. So much for courage -- they made him take hormones that gave him titties to stay out of jail and two years later he killed himself -- but I digress.&lt;br /&gt;&lt;br /&gt;smuglispweeny you call me? Lessee...&lt;br /&gt;&lt;br /&gt;Smug? "&lt;/span&gt;&lt;span style="font-size:100%;"&gt;marked by excessive complacency or self-satisfaction".  Well, excessive does not work because I am if anything insufficiently complacent and self-satisfied about Lisp but that's a quibble and I hate quibbles so sure, color me smug.&lt;br /&gt;&lt;br /&gt;Lisp? Duh.&lt;br /&gt;&lt;br /&gt;Weeny? Sinking to the level of schoolyard name calling, are we? Super, that level is as far as I got. But you won't get an insult back, I am just standing here with this smug grin. What gives?&lt;br /&gt;&lt;br /&gt;Easy. Lisp is that good. Call me anything you like as long as lisp is in there somewhere. No Lisper has any doubt that Lisp is far and away superior to everything else out there so if you call us names we are just gonna get it printed up on T-shirts. Before you argue read &lt;a href="http://wiki.alu.org/RtL_Highlight_Film"&gt;The Road to Lisp&lt;/a&gt; to hear what other weenies have to say. Quiz Friday. OK, now you can argue. Or download &lt;a href="http://www.franz.com/downloads/allegrodownload.lhtml"&gt;one&lt;/a&gt; free trial Lisp or &lt;a href="http://www.lispworks.com/downloads/index.html"&gt;another&lt;/a&gt; and maybe learn something. Or...&lt;br /&gt;&lt;br /&gt;If you love the bleeding edge and want to join a brand new Lisp community consisting mostly of brand new Lispers, try &lt;a href="http://www.arclanguage.org/"&gt;Arc&lt;/a&gt;. Arc is the brandest newest Lisp and brought to us by &lt;a href="http://www.paulgraham.com/"&gt;Paul Graham&lt;/a&gt;, a better advocate for Lisp than I. I would link to Paul's specific page on Lisp if Firefox was worth a damn and I could see the navigation icons. Arc is Scheme with two fixes from Common Lisp -- unhygienic macros and NIL as false -- and &lt;gasp&gt; small doses of syntax in return for denser code and fewer parentheses (but not so few as to lose the tremendous advantage (yep) they offer when thrashing code).&lt;br /&gt;&lt;br /&gt;After Arc makes you fall in love with Lisp, take up Common Lisp. Not Scheme, a failed experiment in minimalism and purity and all sorts of qualities useless to Real Programmers, an experiment brought to you by academia -- nuff said?&lt;br /&gt;&lt;br /&gt;Common Lisp resources: Paul Graham also wrote not &lt;a href="http://www.paulgraham.com/acl.html"&gt;one&lt;/a&gt; but two fine books &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt;. The good news about On Lisp is that it is a free download, the bad news is that it is pretty advanced, save that till week two. Peter Seibel wrote the newest Lisp tome, &lt;a href="http://www.gigamonkeys.com/book/"&gt;Practical Common Lisp&lt;/a&gt;, comprehensive yet built around real-world projects hence the title. Available in print from &lt;a href="http://www.apress.com/book/view/1590592395"&gt;Apress&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Your final great resource is Usenet, comp.lang.lisp to be specific. Read it daily once you have switched to Lisp for a continuing education in Common Lisp.&lt;br /&gt;&lt;br /&gt;As for this blog, it will be about Lisp, application programming in general, dispatches from the trenches of my &lt;a href="http://www.theoryyalgebra.com/"&gt;current application&lt;/a&gt; in particular, my Cells project (in a domain the grownups call &lt;a href="http://en.wikipedia.org/wiki/Functional_reactive_programming"&gt;functional reactive programming&lt;/a&gt;), &lt;a href="http://www.w3.org/TR/rdf-concepts/"&gt;RDF&lt;/a&gt; (my latest crush), and more Lisp because software matters and the world would be a better place with better software and that means Lisp.&lt;br /&gt;&lt;br /&gt;Let us pray.&lt;br /&gt;&lt;br /&gt;&lt;/gasp&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6508797467947601724-432224683968201822?l=smuglispweeny.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smuglispweeny.blogspot.com/feeds/432224683968201822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6508797467947601724&amp;postID=432224683968201822' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/432224683968201822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6508797467947601724/posts/default/432224683968201822'/><link rel='alternate' type='text/html' href='http://smuglispweeny.blogspot.com/2008/02/all-your-parentheses-are-belong-to-us.html' title='All Your Parenthesis Are Belong to Us'/><author><name>Kenny Tilton</name><uri>http://www.blogger.com/profile/17430816457662806163</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp1.blogger.com/_QGhCxCRWf78/R7N8x_KlpOI/AAAAAAAAAA4/G2GYZcmX6LM/S220/ktbigsmile.jpg'/></author><thr:total>17</thr:total></entry></feed>
