<?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/'><id>tag:blogger.com,1999:blog-6687315</id><updated>2006-12-03T21:41:13.805-08:00</updated><title type='text'>Sambangu</title><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/index.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default'></link><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.quetzal.com/sambangu/atom.xml'></link><author><name>Chris Bogart</name></author><generator version='7.00' uri='http://beta.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>21</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6687315.post-67011484981499964</id><published>2006-12-03T21:35:00.000-08:00</published><updated>2006-12-03T21:37:42.893-08:00</updated><title type='text'>Moving to new URL</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;I'm moving to &lt;a href="http://sambangu.blogspot.com"&gt;http://sambangu.blogspot.com&lt;/a&gt;.  Please update your feed!  I was doing an FTP upload from blogger.com to my ISP, but the comments never worked, and it just doesn't seem worth the trouble to do it that way.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/12/moving-to-new-url'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/67011484981499964'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/67011484981499964'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-4784589849197709838</id><published>2006-12-03T19:50:00.000-08:00</published><updated>2006-12-03T21:16:23.560-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell polynomials'></category><title type='text'>Polynomials as numbers</title><content type='html'>So, I was trying to learn category theory, having gathered it was a good thing to know for people interested in programming language theory.  I kind of got bogged down though -- it's castles built on castles built on castles in the air, and I was losing track of reality in all the abstractions.  My book would talk about a category of Groups, for example, so I'd go looking up Groups in my faithful Wikipedia.  I'd get the concept, it's not that tricky in itself, but obviously understanding the definition of a group does not make one a group theorist.&lt;br /&gt;&lt;br /&gt;So, I finally declared "mission accomplished" brought the troops home to a ticker-tape parade, and started in on a group theory textbook instead (Knapp's Basic Algebra).  I'm enjoying it a lot more -- it starts up where I left off with math classes, so I don't feel like I'm a freshman in a senior-level class.&lt;br /&gt;&lt;br /&gt;Anyway, &lt;span style="font-style: italic;"&gt;this&lt;/span&gt; book starts with a kind of review of polynomials, simultaneous equations, matrices, vector spaces, etc. that is stuff I've seen before, but with a more theoretical spin, that either was missing from my high school algebra or I've simply forgotten it.  The book points out that factoring integers into products of smaller integers, is very much like factoring polynomials into products of polynomials of smaller degree, and a prime number is like a polynomial you can't factor any further (like say x&lt;sup&gt;2&lt;/sup&gt;+9 = 0, when you're dealing with Reals).   Of course you can also add, subtract, multiply, and divide polynomials, and the result is always still a polynomial.  If a topologist can't tell a coffee cup from a doughnut, then a group theorist can't tell a polynomial from an integer.&lt;br /&gt;&lt;br /&gt;Well, maybe she can; obviously integers and polynomials have some different properties.  But I'm tickled enough with the idea that a polynomial is a kind of number, that I created a polynomial instance of Num in Literate Haskell as an exercise, reproduced below for your edification.&lt;br /&gt;&lt;br /&gt;Since I'm also still learning Haskell, I welcome any critiques you might have of my code.  I like the fact that the data structure I used (just a list of coefficients) turned out to make for short code; but it doesn't come out very readable.  The fact that prepending a 0 to a list multiplies the polynomial by X seems as cryptic as it is convenient.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; module Main where&lt;br /&gt;&gt; main = print testP&lt;br /&gt;&lt;br /&gt;I represent a polynomial as a list of its coefficients,&lt;br /&gt;with the constant first, then the X, the X^2, etc.  So&lt;br /&gt;3x^2 - 4 would be Poly [-4,0,3].&lt;br /&gt;&lt;br /&gt;&gt; data Floating a =&gt; Poly a = Poly [a] deriving (Eq)&lt;br /&gt;&lt;br /&gt;Now we evaluate by filling in the unknown.  Note that&lt;br /&gt;ax2 + bx + c evaluated at x is the same as&lt;br /&gt;(ax + b)x + c, so you can evaluate it by taking the constant&lt;br /&gt;term, popping it off the list, then multiplying x by the&lt;br /&gt;polynomial interpretation of the rest of the list.&lt;br /&gt;&lt;br /&gt;&gt; evalPoly :: (Floating a) =&gt; (Poly a) -&gt; a -&gt; a&lt;br /&gt;&gt; evalPoly (Poly []) x = 0&lt;br /&gt;&gt; evalPoly (Poly (c:cs)) x = c + x*(evalPoly (Poly cs) x)&lt;br /&gt;&lt;br /&gt;To add two polynomials, add corresponding coefficients.  If&lt;br /&gt;one is shorter than the other, you want to use zeroes.  I don't&lt;br /&gt;know how to do this beautifully with standard functions, because&lt;br /&gt;zip cuts off when the shortest list runs out.  So I defined&lt;br /&gt;a helper function zipLong, that keeps going till the longest&lt;br /&gt;list is done, filling in a default value.&lt;br /&gt;&lt;br /&gt;10 Points to whoever emails me with a shorter, cleaner,&lt;br /&gt;idiomatic way to do this.&lt;br /&gt;&lt;br /&gt;&gt; addPoly :: (Floating a) =&gt; (Poly a) -&gt; (Poly a) -&gt; (Poly a)&lt;br /&gt;&gt; addPoly (Poly r) (Poly s) = Poly $ map (\v -&gt; (fst v + snd v)) (zipLong r s 0)&lt;br /&gt;&lt;br /&gt;&gt; zipLong [] [] d = []&lt;br /&gt;&gt; zipLong (x:xs) [] d = (x,d):(zipLong xs [] d)&lt;br /&gt;&gt; zipLong [] (y:ys) d = (d,y):(zipLong [] ys d)&lt;br /&gt;&gt; zipLong (x:xs) (y:ys) d = (x,y):(zipLong xs ys d)&lt;br /&gt;&lt;br /&gt;Multiply a polynomial by a scalar.  I have a feeling this&lt;br /&gt;could be defined somehow under an instance of Num so that&lt;br /&gt;the * operator is automatically overloaded.  Not sure how.&lt;br /&gt;&lt;br /&gt;&gt; scalarPolyMult :: (Floating a) =&gt; a -&gt; Poly a -&gt; Poly a&lt;br /&gt;&gt; scalarPolyMult c (Poly rs) = Poly $ map (*c) rs&lt;br /&gt;&lt;br /&gt;Since (ax^2 + bx + c)x = ax^3 + bx^2 + cx,&lt;br /&gt;then Poly [c b a] * x = Poly [0 c b a]&lt;br /&gt;&lt;br /&gt;&gt; multByUnknown (Poly rs) = Poly (0:rs)&lt;br /&gt;&lt;br /&gt;To multiply two polynomials, P1 * P2, where P2 = (dx^2 + ex + f),&lt;br /&gt;rewrite as  f*P1 + P1*x*(dx + e); the first term is a scalar multiplication&lt;br /&gt;and the second has one less degree, so we can recurse on it.  The&lt;br /&gt;(Poly bs) term below is (dx + e) in this example.&lt;br /&gt;&lt;br /&gt;&gt; multPoly :: (Floating a) =&gt; (Poly a) -&gt; (Poly a) -&gt; (Poly a)&lt;br /&gt;&gt; multPoly (Poly []) cs = Poly []&lt;br /&gt;&gt; multPoly (Poly (b:bs)) cs =&lt;br /&gt;&gt;     addPoly&lt;br /&gt;&gt;         (scalarPolyMult b cs)&lt;br /&gt;&gt;         (multPoly (Poly bs) (multByUnknown cs))&lt;br /&gt;&lt;br /&gt;Define a polynomial as a number.  I'm cheating a little by&lt;br /&gt;picking a dumb definition of signum; really a polynomial&lt;br /&gt;with an unknown isn't positive or negative before a number&lt;br /&gt;is plugged into it, so I'm just defining it as the sign of&lt;br /&gt;the constant term.&lt;br /&gt;&lt;br /&gt;&gt; instance (Floating a) =&gt; Num (Poly a) where&lt;br /&gt;&gt;     s + t  = addPoly s t&lt;br /&gt;&gt;     negate (Poly cs) = Poly $ map (\q -&gt; -q) cs&lt;br /&gt;&gt;     s * t = multPoly s t&lt;br /&gt;&gt;     abs s&lt;br /&gt;&gt;        | signum s == -1   = negate s&lt;br /&gt;&gt;        | signum s /= -1   = s&lt;br /&gt;&gt;     signum (Poly [])  = Poly []&lt;br /&gt;&gt;     signum (Poly (c:cs)) = Poly [signum c]&lt;br /&gt;&gt;     fromInteger i = Poly [fromInteger i]&lt;br /&gt;&lt;br /&gt;And define a cheesy way to print out a polynomial&lt;br /&gt;&lt;br /&gt;&gt; instance Floating a =&gt; Show (Poly a) where&lt;br /&gt;&gt;     show (Poly [])     = "null"&lt;br /&gt;&gt;     show (Poly cs)     = concatMap&lt;br /&gt;&gt;          (\c -&gt; " + " ++ (show (fst c)) ++ "X^" ++ (show (snd c)))&lt;br /&gt;&gt;          (reverse (zip  cs  [0..length(cs)-1] ))&lt;br /&gt; &lt;br /&gt;Define some examples and some tests. &lt;br /&gt;&lt;br /&gt;&gt; p = Poly [2,0,1,2] -- 2x^3 + x + 2&lt;br /&gt;&gt; q = Poly [0,0,0,3,4]   -- 4x^4 + 3x^3&lt;br /&gt;&lt;br /&gt;&gt; testP = (p * q == Poly [0,0,0,6,8,3,10,8]) &amp;&amp;amp;&lt;br /&gt;&gt;         (p + q == Poly [2,0,1,5,4]) &amp;&amp;amp;&lt;br /&gt;&gt;         (evalPoly p 3 == 65.0 ) &amp;&amp;amp;&lt;br /&gt;&gt;         (3 * p == Poly [6,0,3,6]) &amp;&amp;amp;&lt;br /&gt;&gt;         (show p == " + 2.0X^3 + 1.0X^2 + 0.0X^1 + 2.0X^0")&lt;br /&gt;&lt;/pre&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/12/polynomials-as-numbers'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/4784589849197709838'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/4784589849197709838'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-6982253509869146113</id><published>2006-11-17T14:19:00.000-08:00</published><updated>2006-11-17T14:24:32.027-08:00</updated><title type='text'>SOAP: follow-up</title><content type='html'>Here's a &lt;a href="http://wanderingbarque.com/nonintersecting/2006/11/15/the-s-stands-for-simple/"&gt;fantastic dialog&lt;/a&gt; that exactly captures my experiences with SOAP.  (via &lt;a href="http://anarchaia.org/"&gt;Anarchaia&lt;/a&gt;)</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/11/soap-follow-up'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/6982253509869146113'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/6982253509869146113'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-116183851293766794</id><published>2006-10-25T21:52:00.000-07:00</published><updated>2006-10-25T21:55:12.950-07:00</updated><title type='text'>Follow up on kanji coding method: Wuji</title><content type='html'>Turns out there is a &lt;a href="http://en.wikipedia.org/wiki/Five_Stroke_method"&gt;character input method&lt;/a&gt; like the one I described in my &lt;a href="http://www.quetzal.com/sambangu/2006/08/keystroke-coding-system-for-kanji.html"&gt;previous post&lt;/a&gt;.&lt;br /&gt;  Sounds like it turns out to be kind of awkward to use.  Ah well...</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/10/follow-up-on-kanji-coding-method-wuji.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116183851293766794'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116183851293766794'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-116093328140756650</id><published>2006-10-15T09:45:00.000-07:00</published><updated>2006-10-15T10:35:34.400-07:00</updated><title type='text'>Ban the dangling else!</title><content type='html'>I was just reading through Niklaus Wirth's paper, &lt;a href="http://www.cs.inf.ethz.ch/%7Ewirth/Articles/GoodIdeas_origFig.pdf"&gt;"Good Ideas, Through the Looking Glass"&lt;/a&gt; (found through &lt;a href="http://lambda-the-ultimate.org/node/1773"&gt;Lambda the Ultimate&lt;/a&gt;, of course!) where he talks about the &lt;a href="http://en.wikipedia.org/wiki/Dangling_else"&gt;Dangling Else&lt;/a&gt; problem.&lt;br /&gt;&lt;br /&gt;Some programming languages have statements of the form:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;blockquote&gt;&lt;code&gt;if X then Y&lt;/code&gt;&lt;br /&gt;&lt;/blockquote&gt;and&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;blockquote&gt;&lt;code&gt;if X then Y else Z&lt;/code&gt;&lt;br /&gt;&lt;/blockquote&gt;with no &lt;code&gt;end&lt;/code&gt; keyword or bracket, leading to the problem of how to interpret:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;blockquote&gt;&lt;code style="font-weight: bold;"&gt;if&lt;/code&gt; it's Saturday &lt;code style="font-weight: bold;"&gt;then if&lt;/code&gt; it's sunny &lt;code style="font-weight: bold;"&gt;then&lt;/code&gt; have a picnic &lt;code style="font-weight: bold;"&gt;else&lt;/code&gt; see a movie&lt;br /&gt;&lt;/blockquote&gt;Do we see a movie if it's not Saturday, or if it is Saturday, but it's cloudy?&lt;br /&gt;&lt;br /&gt;Natural languages have exactly the same sort of problem (example from the &lt;i&gt;AP Press Guide to News Writing&lt;/i&gt;, quoted in &lt;a href="http://itre.cis.upenn.edu/%7Emyl/languagelog/archives/001174.html"&gt;Language Log&lt;/a&gt;):&lt;br /&gt;&lt;blockquote&gt;We spent most of our time sitting on the back porch watching the   cows playing Scrabble and reading.&lt;br /&gt;&lt;/blockquote&gt;It reads funny in English, but we resolve it easily because we know the context.   Obviously context is not as helpful for a compiler.&lt;br /&gt;&lt;br /&gt;How does Language Log suggest fixing that problem in English?  They give two suggestions:&lt;br /&gt;&lt;blockquote&gt;We spent most of our time sitting on the back porch watching the   cows, playing Scrabble and reading.  &lt;/blockquote&gt;or&lt;br /&gt;&lt;blockquote&gt;Playing Scrabble and reading, we spent most of our time sitting on   the back porch watching the cows.  &lt;/blockquote&gt;The first suggestion corresponds approximately to Wirth's preference for an &lt;code&gt;end&lt;/code&gt; keyword; the comma signals a break of some kind, and the obvious interpretation is that the cows and the scrabble shouldn't be too closely associated.  It's not nearly so rigorous as &lt;code&gt;end&lt;/code&gt;, of course.&lt;br /&gt;&lt;br /&gt;The other suggestion is a bit more interesting; they rework the entire ordering of the sentence.  Although the two examples aren't really parallel, it does suggest another way to rework our if-then-if-then-else, if we intend the final else to correspond to the &lt;span style="font-style: italic;"&gt;first&lt;/span&gt; if-then:&lt;br /&gt;&lt;br /&gt;&lt;code style="font-weight: bold;"&gt;if&lt;/code&gt; it's not Saturday &lt;code style="font-weight: bold;"&gt;then&lt;/code&gt; see a movie &lt;code style="font-weight: bold;"&gt;else if&lt;/code&gt; it's sunny &lt;code style="font-weight: bold;"&gt;then&lt;/code&gt; have a picnic.&lt;br /&gt;&lt;br /&gt;In other words, we're punting -- not solving the original ambiguity but wording around to avoid the issue.&lt;br /&gt;&lt;br /&gt;I think that's actually a better strategy from a human reader's standpoint.  We do not have much in the way of "closing braces" in natural language: they tend to lead to &lt;a href="http://en.wikipedia.org/wiki/Center_embedding"&gt;center embedding&lt;/a&gt; issues which our brains just aren't equipped to deal with.  So maybe a good policy would be for a compiler to simply disallow the "if-then-if-then-else" construction with either interpretation, and force the user to rework their logic a little.  Such a restriction looks like an ugly hack to a computer scientist, but I think its necessary if we take seriously the idea that programs should be human languages as well as computer languages.&lt;br /&gt;&lt;br /&gt;Tags: &lt;a href="http://en.wikipedia.org/wiki/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Programming+Languages" rel="tag"&gt;Programming Languages&lt;/a&gt;, &lt;a href="http://www.technorati.com/tags/HCI" rel="tag"&gt;HCI&lt;/a&gt;, &lt;a href="http://technorati.com/tag/dangling+modifiers" rel="tag"&gt;dangling modifiers&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/10/ban-dangling-else.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116093328140756650'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116093328140756650'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-116036535688416736</id><published>2006-10-08T20:37:00.000-07:00</published><updated>2006-10-08T20:48:56.720-07:00</updated><title type='text'>Metalanguage for Software Development</title><content type='html'>Every software developer uses a variety of languages to develop a program.  It may seem like you're developing something purely in Perl or Java or VB or whatever, in fact you're using a lot of mini-languages to manage the development process:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;   Shell: if you're using a command line, you have to know shell commands for managing files and directories, invoking the compiler, etc.&lt;/li&gt;&lt;li&gt;   IDE: On the other hand if you're using an IDE, you could kind of consider it language-like; you invoke series of drop down menus and click options on and off&lt;/li&gt;&lt;li&gt;   source control: whether it's IDE-based or command-line based, you're describing and querying a specialized model encompassing time, files, directories, versions, and maybe different user identities&lt;/li&gt;&lt;li&gt;   deployment: you use FTP commands, or something equivalent, to put files on a server, configure the server to run your programs at the appropriate time, etc.&lt;/li&gt;&lt;li&gt;   building and linking: Like makefiles or visual studio "projects"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;   profiling: turning a profiler on or off, configuring it, and interpreting its output, is a language-like interaction&lt;/li&gt;&lt;li&gt;   debugging: another model of the program, where you communicate with the debugger about variable values and code structures&lt;/li&gt;&lt;li&gt;   SQL: typically any interaction with a database within your program, is done from within a walled-off sublanguage; maybe SQL built into strings, or maybe a specialized, but usually somewhat awkward, object or function call model.&lt;/li&gt;&lt;li&gt;   Database configuration: setting up tables and so forth is often done with a combination of SQL or database management configuration IDE manipulation&lt;/li&gt;&lt;/ul&gt;   When programmers think about the development process, we have an integrated mental model of all these aspects of the process, and from that figure out how to use them all together to do what needs to be done.  It would be interesting to have a single, consistent meta-language for software development that encompassed all these tasks.&lt;br /&gt;&lt;br /&gt;The closest thing we have to that, I think, is the command-line shell.  The simpler "languages", such as the compiler settings language, are encapuslated as command-line arguments, so technically from the same prompt you are doing diverse tasks like compiling your program or renaming files.  But useful as it is, it's kind of a gimmick.  You can't easily pull together information from, say, the profiler, the debugger, and some unit test results, and ask questions that cut across these different domains.&lt;br /&gt;&lt;br /&gt;For example, suppose you made a change to a procedure last week, and now you think it may be running too slow on a particular dataset.  A test of that is easy to express in English: run the current version of the procedure X against dataset Y and note how long it takes; also run X against Y using the version of X that was current last Thursday.  Implementing it would take a little work; we'd have to check out two versions, compile them in separate directories, run them both under a profiler, and know how to interpret the profiler results.  Speaking for myself, I'd probably make a mistake the first time through -- I'd check out the wrong version of the code, or run the compiler with different optimization flags or something.&lt;br /&gt;&lt;br /&gt;There oughtta be a language that has standard terminology for all these sorts of tools, and some easy way to build little modules onto the front end of a tool, that translates this language into the tool's configuration settings, and translates its results or error messages back into the language.&lt;br /&gt;&lt;br /&gt;The trick is you'd have to have a pretty smart front end that could pull apart commands or queries that involved multiple tools and figure out what commands to pass along to the individual tools; then integrate the results it gets back.  This would not be a trivial problem, but it would be a good start just to make this kind of task *expressible*, and require a lot of user guidance at first.&lt;br /&gt;&lt;br /&gt;Tag: &lt;a href="http://www.technorati.com/tags/programminglanguages" rel="tag"&gt;ProgrammingLanguages&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/10/metalanguage-for-software-development.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116036535688416736'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/116036535688416736'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115767378335242531</id><published>2006-09-07T16:43:00.000-07:00</published><updated>2006-09-07T17:03:03.366-07:00</updated><title type='text'>Buddhism and Category Theory</title><content type='html'>In my previous post today I mused about using standard ontologies in programs as a way of grounding the web of connections between your objects in a framework of common terminology. &lt;br /&gt;&lt;br /&gt;There is a concept in Buddhist metaphysics called &lt;a href="http://en.wikipedia.org/wiki/Dependent_origination" rel="tag"&gt;Dependent Origination&lt;/a&gt;, which states that nothing exists on its own, but only manifests itself through its connections with everything else in its environment.  One illustration of the concept is &lt;a href="http://en.wikipedia.org/wiki/Indra%27s_Net"&gt;Indra's Net&lt;/a&gt;, an infinite spider web with little silver balls at all the junctions, each reflecting all the others in a way that would gum up any &lt;a href="http://en.wikipedia.org/wiki/Ray_tracer"&gt;ray tracer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A program that doesn't refer to much of anything external to itself is like that -- you can define data structures and pointers and files that all point to each other, but it's all meaningless without the interpretation that a programmer or user gives to it in the data they feed to it and their interpretation of its output.&lt;br /&gt;&lt;br /&gt;I'd say that &lt;a href="http://en.wikipedia.org/wiki/Category_theory" rel="tag"&gt;Category Theory&lt;/a&gt; is a mathematical restatement of Dependent Origination.&lt;br /&gt;&lt;br /&gt;Tags: &lt;a href="http://www.technorati.com/tags/categorytheory" rel="tag"&gt;CategoryTheory&lt;/a&gt;, &lt;a href="http://www.technorati.com/tags/dependentorigination" rel="tag"&gt;DependentOrigination&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/09/buddhism-and-category-theory.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115767378335242531'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115767378335242531'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115767200353979504</id><published>2006-09-07T15:13:00.000-07:00</published><updated>2006-09-07T16:42:30.403-07:00</updated><title type='text'>Organizing programs by their invariants</title><content type='html'>It seems to me that natural langauge program specifications tend to consist of a lot of statements which are all independently true, and only dependent on context for &lt;a href="http://en.wikipedia.org/wiki/Deixis"&gt;deictic&lt;/a&gt; references (i.e. pronouns and pronoun-like references to concepts in surrounding sentences).  In other words, I'd claim, you could make sense of a good proportion of a scrambled specification if:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sentences remained intact&lt;/li&gt;&lt;li&gt;Deictic references were replaced by full references to global names of entities or processes&lt;/li&gt;&lt;/ul&gt;Now obviously, not everything in such a document will behave that way; for example an ordered list of steps will have their ordering and context lost.   But I think my claim is more true of an English-language spec, then, say, a large FORTRAN program.  If you have a spec you're working with closely, you might have sticky notes on different pages, and individual sentences highlighted, which you can turn to and refer to instantly without necessarily reading for context.    An old-skool not-very-modular FORTRAN program, on the other hand, is meant to be executed in one fell swoop.  A programmer might turn to a particular page of a printout and look for some information, but will require a lot more scanning around and reasoning to come up with an answer to their question about what's going on in the program.&lt;br /&gt;&lt;br /&gt;A Java program might fall somewhere in between English and Fortran in that regard -- Java tends to be written with lots of smallish functions, each of which might be comprehended on its own. &lt;br /&gt;&lt;br /&gt;Another reason a natural-language spec is easier to read in a random order, is that the words in an English sentence are more likely to be standard vocabulary not defined in the spec; and the ones that are defined in the spec are likely to be motivated* narrowings or metaphors of standard terminology.  In all the programming languages I'm familiar with, almost all the entities defined in a particular system can be freely named: a there may be conventions telling a programmer what sort of thing a WidgetWindowHandlerFactory is, but the compiler doesn't care; it could be a synonym for Integer.&lt;br /&gt;&lt;br /&gt;So this habit of natural language helps make randomly-chosen sentences more comprehensible on their own.  That in turn makes it easier for us short-attention-span programmers to digest the piles of paper our managers and user groups churn out.&lt;br /&gt;&lt;br /&gt;This suggests a couple interesting features for programming languages:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Structurally organize programs around a series of declared &lt;a href="http://en.wikipedia.org/wiki/Invariant_%28computer_science%29"&gt;invariants&lt;/a&gt;, with the compiler (when possible) or the programmer (the rest of the time) filling in associated code to ensure the invariant remains true.  This could be done in a lot of different ways depending on the need -- type systems, aspects, agents.&lt;/li&gt;&lt;li&gt;Create a large and varied, but standard and fixed, &lt;a href="http://en.wikipedia.org/wiki/Ontology_%28computer_science%29"&gt;ontology&lt;/a&gt; of types that the user should almost always derive from.  Give them all short names and require user-defined types and variables to end with those type names.  This would have to be done carefully to avoid javaStyleWordiness(), and it would also be a larger learning curve/burden on the programmer.  I'm picturing something vaguer and more flexible than a standard library; rather than providing a bunch of standard implementations, the ontology would provide standard invariants.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;* "motivated" -- I got this term from &lt;a href="http://en.wikipedia.org/wiki/George_Lakoff"&gt;George Lakoff&lt;/a&gt;'s book "&lt;a href="http://www.amazon.com/Women-Dangerous-Things-George-Lakoff/dp/0226468046"&gt;Women, Fire, and Dangerous Things"&lt;/a&gt; where he talks about how new uses for old words are &lt;span style="font-style: italic;"&gt;motivated&lt;/span&gt; by metaphorical relations with older meanings, but not &lt;span style="font-style: italic;"&gt;predictable&lt;/span&gt; from those meanings.&lt;br /&gt;&lt;br /&gt;Tags: &lt;a href="http://en.wikipedia.org/wiki/ontology" rel="tag"&gt;ontology&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Programming+Languages" rel="tag"&gt;Programming Languages&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/09/organizing-programs-by-their.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115767200353979504'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115767200353979504'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115605060164058643</id><published>2006-08-19T21:14:00.000-07:00</published><updated>2006-08-19T22:10:01.676-07:00</updated><title type='text'>Saponomancy</title><content type='html'>This week I was asked to write some code to mimic a &lt;a href="http://en.wikipedia.org/wiki/SOAP"&gt;SOAP&lt;/a&gt; service.  How hard could that be?  It was a very simple service, just a couple remote procedure calls, one of which could return a large binary file.&lt;br /&gt;&lt;br /&gt;Of course, the original one was implemented in Delphi, to run under &lt;a href="http://en.wikipedia.org/wiki/IIS"&gt;IIS&lt;/a&gt;, and the new one needed to run on a UNIX-like system, but SOAP is intended on making all this easy, right?  How much did I need to know?&lt;br /&gt;&lt;br /&gt;Well, a lot, it turns out.   I played with a couple different toolkits for creating SOAP services, and they kept coming up with slight variations, none of which seemed to interoperate out of the box.  Little things would be different in the XML message, like whether namespaces were mentioned in the tags, or how the attachment was referenced and sent.  It was easy to see and understand the problem by looking at the dumps of the XML and MIME stuff going over the wire, but much harder to plow through the documentation of the various API's to see what flags needed to be set in their object model, or what objects needed to be created, or who was responsible for allocating and freeing memory, etc.&lt;br /&gt;&lt;br /&gt;In the end, I realized that since this was an internal service, and I controlled both endpoints, I could easily make a case to management for just &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;using the raw HTTP protocol&lt;/a&gt;, and in fact as I played with that solution, it turned out to be cleaner, lighter, more maintainable, and easier to document.  I'm changing my party affiliation to REST, even though it's too late to vote in the primaries.&lt;br /&gt;&lt;br /&gt;Well, that's fine; I'm sure there must be cases where SOAP is a better solution, but it got me to thinking about why it is that the raw XML is so much easier to debug than the supposedly labor-saving frameworks built on top of it.  I guess it's just that what goes across a line is easier to capture and pin down -- I can run two services, capture their input and output, and just compare the logs of them.  But I can't compare the operations of their object models, because they're different.&lt;br /&gt;&lt;br /&gt;What would be very cool, is if there were a formal way to specify a relationship between all the possible operations of an object model, and the grammar of its input and output streams.  Then I could point to a rule in the grammar that I wanted to come out a certain way, and ask "what sequences of user-accessible object operations can cause this".  The closest thing I've seen to this is the &lt;a href="http://www.cs.cmu.edu/%7Emarmalade/whyline.html"&gt;Whyline&lt;/a&gt; from project Marmelade at CMU.  The Whyline is a thingy that looks like it's geared towards helping a programmer find bugs in their code, by tracing out why a particular condition was arrived at in code execution.  Seems like it could be just as useful for prying apart the mysteries of someone else's prepackaged API, especially if it was closed-source, if somehow the Whyline could still operate without showing you precious vendor secrets.&lt;br /&gt;&lt;br /&gt;Unfortunately the Whyline is still a research project built into a research language called Alice, not a handy button on my Visual Studio menubar.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/08/saponomancy.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115605060164058643'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115605060164058643'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115561612815325536</id><published>2006-08-14T21:17:00.000-07:00</published><updated>2006-08-14T21:28:48.173-07:00</updated><title type='text'>Abstracting Bubblesort</title><content type='html'>In my &lt;a href="/sambangu/2006/08/how-we-talk-about-algorithms_04.html"&gt;August 4th entry&lt;/a&gt; I conjectured that monads might be a good way to abstract away the question of whether a bubblesort was done over time or laid out across memory as a sequence of permutations.&lt;br /&gt;&lt;br /&gt;I thought that was a good exercise for me to brush up on Haskell monads, so here's the program I wrote.  It's "literate haskell", so you can take this whole posting, save it as an whatever.lhs, and it should compile.&lt;br /&gt;&lt;br /&gt;I especially relied on a &lt;a href="http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html"&gt;monad tutorial&lt;/a&gt; at &lt;a href="http://sigfpe.blogspot.com/"&gt;A Neighborhood of Infinity&lt;/a&gt;, that Sigfpe happened to post just as I was in need of it.  Thanks, Sigfpe!&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;I'll be using the State, List, and IO monads.  Eek, trial by fire.&lt;br /&gt;To start with, State has to be imported:&lt;br /&gt;&lt;br /&gt;&gt;import Control.Monad.State&lt;br /&gt;&lt;br /&gt;So here's my generic bubblesort to start out with.  It sets everything&lt;br /&gt;up without actually having the list available yet; all it needs is the&lt;br /&gt;length for now.&lt;br /&gt;&lt;br /&gt;The cf and swap parameters are functions that compare and swap elements,&lt;br /&gt;respectively.  Actually, they just take the indexes of the element(s)&lt;br /&gt;and return a function which will be responsible for testing and permuting&lt;br /&gt;anything the caller wants, however they want.  cf x y should compare elements&lt;br /&gt;x and y (whatever that may mean), and swap x should swap the xth and (x+1)th&lt;br /&gt;elements.&lt;br /&gt;&lt;br /&gt;So this function cycles through pairs of adjacent indices in bubblesorty&lt;br /&gt;fashion, and builds a list of functions, each of which is responsible&lt;br /&gt;for testing, and maybe swapping, a pair of elements, with those &lt;br /&gt;user-supplied comparison and swapping functions.&lt;br /&gt;&lt;br /&gt;&gt;bubblesort cf swap theLen = do&lt;br /&gt;&gt;                       i &lt;- reverse [0..theLen]&lt;br /&gt;&gt;                       j &lt;- [0..(i-2)]&lt;br /&gt;&gt;                       [do&lt;br /&gt;&gt;                            i &lt;- cf j (j+1)&lt;br /&gt;&gt;                            if i&lt;br /&gt;&gt;                                 then swap j &lt;br /&gt;&gt;                                 else return ()]&lt;br /&gt;&lt;br /&gt;Now here's a simple comparison function: it assumes that the &lt;br /&gt;list will be just an ordinary list, with elements instances of&lt;br /&gt;Ord (so that &gt; works).  What it returns is (State [a] Bool),&lt;br /&gt;which is actually another function, taking one list [a]&lt;br /&gt;and returning the same unchanged list [a] and a Boolean.&lt;br /&gt;&lt;br /&gt;&gt;cf1 :: Ord a =&gt; Int -&gt; Int -&gt; (State [a] Bool)&lt;br /&gt;&gt;cf1 i j = do&lt;br /&gt;&gt;            ls &lt;- get&lt;br /&gt;&gt;            return $ (ls!!i) &gt; (ls!!j)&lt;br /&gt;&lt;br /&gt;And here's the corresponding swap function.  It returns a&lt;br /&gt;function which takes a list, and returns a list with the&lt;br /&gt;jth and (j+1)th elements swapped.&lt;br /&gt;&lt;br /&gt;&gt;swap1 :: Int -&gt; (State [a] ())&lt;br /&gt;&gt;swap1 j = do&lt;br /&gt;&gt;            theList &lt;- get&lt;br /&gt;&gt;            put $ (take j theList) ++ &lt;br /&gt;&gt;                 [theList!!(j+1)] ++ [theList!!j] ++ drop (j+2) theList&lt;br /&gt;&lt;br /&gt;Let's look at another pair of swapping/comparison functions,&lt;br /&gt;before putting everything together:&lt;br /&gt;&lt;br /&gt;This set has a more complicated state -- it's an ordered pair,&lt;br /&gt;of the current permutation [a], and a list of strings [[Char]]&lt;br /&gt;representing the &lt;a href="/sambangu/plinko.txt"&gt;Plinko&lt;/a&gt; toy that &lt;br /&gt;would produce the sort so far.&lt;br /&gt;&lt;br /&gt;&gt;cf2 :: Ord a =&gt; Int -&gt; Int -&gt; (State ([a],[[Char]]) Bool)&lt;br /&gt;&gt;cf2 i j = do&lt;br /&gt;&gt;            (theList, history) &lt;- get&lt;br /&gt;&gt;            return $ (theList!!i) &gt; (theList!!j)&lt;br /&gt;&lt;br /&gt;And here's the corresponding swap function:&lt;br /&gt;&lt;br /&gt;&gt;swap2 j = do&lt;br /&gt;&gt;            (theList, history) &lt;- get&lt;br /&gt;&gt;            let newList = (take j theList) &lt;br /&gt;&gt;                          ++ [theList!!(j+1)] &lt;br /&gt;&gt;                          ++ [theList!!j] &lt;br /&gt;&gt;                          ++ drop (j+2) theList in&lt;br /&gt;&gt;                let newHistory = (( (replicate j '|') &lt;br /&gt;&gt;                              ++ "&gt;&lt;" &lt;br /&gt;&gt;                              ++ (replicate ((length theList)-j-1) '|')) &lt;br /&gt;&gt;                                  : history) in&lt;br /&gt;&gt;                    put (newList, newHistory)&lt;br /&gt;&lt;br /&gt;In this second example, the state is more than just the&lt;br /&gt;list, so we need a function to create the original ([a], [[Char]])&lt;br /&gt;structure:&lt;br /&gt;&lt;br /&gt;&gt;buildstate2 :: [a] -&gt; ([a], [[a]])&lt;br /&gt;&gt;buildstate2 a = (a, [[]])&lt;br /&gt;&lt;br /&gt;And one to get our plinko toy out after we're done sorting:&lt;br /&gt;&lt;br /&gt;&gt;getresult2 :: (Show a) =&gt; ([a], [[a]]) -&gt; [Char]&lt;br /&gt;&gt;getresult2 (_, b) = foldl (++) "" $ map (\b -&gt; "\n" ++ show(b) ) b&lt;br /&gt;&lt;br /&gt;I skipped the equivalent functions before for the straightforward&lt;br /&gt;sorting example because they are straightforward:&lt;br /&gt;&lt;br /&gt;&gt;buildstate1 :: [a] -&gt; [a]&lt;br /&gt;&gt;buildstate1 a = a&lt;br /&gt; &lt;br /&gt;&gt;getresult1 :: (Show a) =&gt; [a] -&gt; [Char]&lt;br /&gt;&gt;getresult1 a = show a&lt;br /&gt;&lt;br /&gt;So now we're ready to call this contraption.  dosort takes&lt;br /&gt;the four functions that relate to our state: buildstate, getresult,&lt;br /&gt;swap, and cf; along with the string to be sorted (I call it string,&lt;br /&gt;but it could have been a list of anything in Ord, really).&lt;br /&gt;&lt;br /&gt;The "sequence" function links up that list of functions that&lt;br /&gt;bubblesort created, and execState is what runs them, when supplied&lt;br /&gt;with the output of buildstate.&lt;br /&gt;&lt;br /&gt;&gt;dosort buildstate cf swap getresult string = &lt;br /&gt;&gt;           let sorter = bubblesort cf swap $ length string in&lt;br /&gt;&gt;               getresult $ execState (sequence sorter) (buildstate string)&lt;br /&gt;&lt;br /&gt;Here are some test functions which call both suites on the same string:&lt;br /&gt;&lt;br /&gt;&gt;test1 = dosort buildstate1 cf1 swap1 getresult1 "sambangu!"&lt;br /&gt;&gt;test2 = dosort buildstate2 cf2 swap2 getresult2 "sambangu!"&lt;br /&gt;&gt;&lt;br /&gt;&gt;main = do&lt;br /&gt;&gt;        putStrLn test1&lt;br /&gt;&gt;        putStrLn test2&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'm certain I'm not doing this in a very elegant way.  It appears that those four characteristic functions belong together in a class declaration, and somehow different execution types would be instances of that class, but I was unable to get it to compile that way.  Could be my syntax was wrong, or more likely, fuzzy thinking, which Haskell seems to be pretty (justifiably) intolerant of.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/08/abstracting-bubblesort.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115561612815325536'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115561612815325536'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115560686231159102</id><published>2006-08-14T18:39:00.000-07:00</published><updated>2006-08-14T18:54:22.330-07:00</updated><title type='text'>Keystroke coding system for Kanji</title><content type='html'>I was thinking about ways of entering Chinese characters, and wishing there were a more intuitive way to do it.  So here's a scheme I came up with.  Obviously a lot of people have been thinking about how to type kanji for a long time, so it's probably been thought of and (implemented | dismissed) before, but anyway, it seems to me like it could work:&lt;br /&gt;&lt;br /&gt;In this system each character is represented by a sequence of the letters b, n, m, and k.  Each letter represents a stroke or part of a stroke:&lt;br /&gt;&lt;br /&gt;   b = diagonal downwards to left&lt;br /&gt;   n = downwards&lt;br /&gt;   m = diagonal downwards to right&lt;br /&gt;   k = horizontal&lt;br /&gt;&lt;br /&gt;So for every stroke you type a letter, and if the stroke changes directions, you type the new letter, making no distinction between strokes and parts of strokes.  I wonder how many ambiguities there would be?  Are there any kanji with disputed stroke orders, or is it totally standardized?&lt;br /&gt;&lt;br /&gt;Here are the numbers 1 - 10:&lt;br /&gt;&lt;br /&gt;一  k&lt;br /&gt;二  kk&lt;br /&gt;三  kkk&lt;br /&gt;四  nknknbnk    &lt;br /&gt;五  knknk&lt;br /&gt;六  nkbm&lt;br /&gt;七  knk&lt;br /&gt;八  bkm&lt;br /&gt;九  bknk&lt;br /&gt;十  kn&lt;br /&gt;&lt;br /&gt;There would have to be some standard rules about how to represent the little hooks (like the last strokes of 四 and 九) and the ones that kind of curve from one heading to another (like the first stroke of 九).&lt;br /&gt;&lt;br /&gt;It seems like a person adept at writing kanji might be able to kind of mentally translate their mechanical skill of writing into these keystrokes.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/08/keystroke-coding-system-for-kanji.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115560686231159102'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115560686231159102'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-115473371785511985</id><published>2006-08-04T16:17:00.000-07:00</published><updated>2006-08-04T16:21:57.880-07:00</updated><title type='text'>How we talk about algorithms</title><content type='html'>It's often the case that a programmer can quickly state the algorithm they want to use to solve a problem, but it takes significantly more time to cobble together the implementation.  There are lots of good reasons why it has to be that way -- explaining something in English presumes an intelligent listener, but the computer you're programming to is not intelligent.  But still, I'm wonder if part of the mental transformation that takes place is a conceptual restrucuring, that wouldn't be necessary if a computer language were structured differently.&lt;br /&gt;&lt;br /&gt;A good way to look at this might be to examine some programs along with descriptions of their algorithms, and see if we can discern any structural differences, and propose new computer language structures that are closer to the human abstraction mechanisms.&lt;br /&gt;&lt;br /&gt;So I want to take as a particular example the "BLACK" problem from this year's &lt;a href="http://www.icfpcontest.org/index.shtml"&gt;ICFP 2006 programming contest&lt;/a&gt;.  After the end of the contest, participants discussed their solutions to some of the problems, and in some cases posted their code, in a &lt;a href="http://lists.andrew.cmu.edu/pipermail/icfpcontest-discuss/Week-of-Mon-20060724/thread.html"&gt;public discussion list&lt;/a&gt;.  As this was a problem I spent some time with (and didn't solve) I decided to look at the algorithms that other teams used.&lt;br /&gt;&lt;h4&gt;Spoiler alert&lt;/h4&gt;The contest puzzle was an amazing construction that I'd highly recommend working on, even though the contest is over.  I'll be giving away the problem description here (which is a good piece of work just to get to), and some solution algorithms.&lt;br /&gt;&lt;h4&gt;The Problem&lt;/h4&gt;&lt;a href="http://www.quetzal.com/sambangu/plinko.txt"&gt;The problem is described here&lt;/a&gt;; basically you're doing a permutation of an ordered list, in steps, where each step can exchange pairs of adjacent items.  When a step shifts any item to the right, there is a "plink" sound.  There's no sound when shifting to the left.  The task is to recreate the steps needed, given an ending permutation and the number of plinks each item would experience in tracing through the steps.  So the first problem they provide looks like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;* x -&amp;gt; (y,z)&lt;br /&gt;* Means that if you drop a marble into pipe x, it comes out pipe y,&lt;br /&gt;* and you hear z plinks&lt;br /&gt;0 -&amp;gt; (3,4)&lt;br /&gt;1 -&amp;gt; (2,3)&lt;br /&gt;2 -&amp;gt; (0,1)&lt;br /&gt;3 -&amp;gt; (1,1)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And one solution is this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;gt;&amp;lt;||&lt;br /&gt;|&amp;gt;&amp;lt;|&lt;br /&gt;&amp;gt;&amp;lt;&amp;gt;&amp;lt;&lt;br /&gt;|&amp;gt;&amp;lt;|&lt;br /&gt;&amp;gt;&amp;lt;&amp;gt;&amp;lt;&lt;br /&gt;&amp;gt;&amp;lt;&amp;gt;&amp;lt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Where the &amp;gt;&amp;lt;'s represent swaps, and the |'s represent items that don't change in that step.  The problem set started with this puzzle of width 4, and also included problems of width 10, 20, 30, 40, 50, 100, 200, 300, 400, and 500.  Your score was based on submitting solutions; the code was not considered -- solving by hand was perfectly legal, if impractical for the larger problems.&lt;br /&gt;&lt;h4&gt;Notation&lt;/h4&gt;I'll use this notation in the discussion below:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In{st}[x]: the xth hole going into step {st} of the machine (numbering starting with 0)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Out{st}[x]: the xth hole coming out of step {st}.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Target{st}[x]: the desired destination of a marble placed at In{st}[x]&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Plinks{st}[x]: the plink count of a marble found at In{st}[x]&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Plinktarget{st}[x]: the desired plink count of a marble found at In{st}[x]&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Step{st}: The string of |'s, &amp;lt;'s, and &amp;gt;'s representing step #st of the machine&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Solution Strategies&lt;/h4&gt;I studied the descriptions of solutions on the mailing list, and on the web pages of participants if they were linked from the &lt;a href="http://lists.andrew.cmu.edu/pipermail/icfpcontest-discuss/Week-of-Mon-20060724/thread.html"&gt;list archive&lt;/a&gt;.&lt;br /&gt;&lt;h4&gt;Divide and Conquer&lt;/h4&gt;The first insight that most solvers shared was a division into two sequential phases.  As stated by Alain Frisch:&lt;br /&gt;&lt;br /&gt;&lt;quote&gt;&lt;/quote&gt;&lt;blockquote&gt;&lt;quote&gt;All the puzzles in the contest had a lot of plinks, [...] and it was indeed possible to first bubble sort the wires and then start from the identical permutation. That's what our team's solver does. &lt;/quote&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Jed Davis wrote: &lt;quote&gt;&lt;/quote&gt;&lt;blockquote&gt;&lt;quote&gt;Mine likewise -- it first does the usual selection sort, then figures&lt;br /&gt;out what combination of maneuvers like that pictured above (moving a&lt;br /&gt;ball N places to one side and then back) need to be placed after the&lt;br /&gt;sort to reduce the remaining needed plinks to a form that can be handled&lt;br /&gt;by appending only double-swaps.&lt;/quote&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Marcin Mucha wrote: &lt;blockquote&gt;&lt;quote&gt; I guess you know that, be some puzzles do have solutions, but you can't decompose any solution as a sequence of a bubblesort and a solution starting from an identical permutation.&lt;/quote&gt;&lt;/blockquote&gt;&lt;quote&gt;&lt;/quote&gt;It's interesting that they all emphasize the sequentiality; the two phases can' t be done in parallel.  Frisch says "to first xxxxxx and then yyyy"; Davis wrote "first xxxxxxx, then yyyyyy".  Mucha uses the word "sequence".   In your typical imperative language, simply listing two steps in order is sufficient to say "do one, then do the other"; this explicit statement of ordering suggests that sequentiality is not necessarily the default in English.&lt;br /&gt;&lt;h4&gt;The Bubblesort&lt;/h4&gt;In two of the three quotes above, the posters mention &lt;a href="http://en.wikipedia.org/wiki/Bubble_sort"&gt;bubblesort&lt;/a&gt; with the implied presumption that its application is obvious.  Bubble sort is an apt description of an algorithm realizable by this type of machine, since every swap is done between adjacent elements.  Here is the code Wikipedia gives for bubblesort:&lt;br /&gt;&lt;pre&gt;function bubblesort (A : list[1..n]) {&lt;br /&gt; var int i, j;&lt;br /&gt; for i from n downto 1 {&lt;br /&gt;     for j from 1 to i-1 {&lt;br /&gt;         if (A[j] &amp;gt; A[j+1])&lt;br /&gt;             swap(A[j], A[j+1])&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;A reasonably adept programmer should be able to read the description of the problem, and the vague advice to "apply a bubblesort", and implement it with some thought, but without any further clarification.  They are making a conceptual mapping like this:&lt;br /&gt;&lt;br /&gt;&lt;dl style=compact&gt;&lt;br /&gt;&lt;dt&gt;List parameter A&lt;br /&gt;&lt;dd&gt;Mapping from exit hole# of current step to exit hole# of final step&lt;br /&gt;&lt;dt&gt;n&lt;br /&gt;&lt;dd&gt;The number of pipes in the machine&lt;br /&gt;&lt;dt&gt;A[j] &gt; A[j+1]&lt;br /&gt;&lt;dd&gt;Pipe at j at this step is destined to a place further to the right of pipe at j+1&lt;br /&gt;&lt;dt&gt;swap(A[j], A[j+1])&lt;br /&gt;&lt;dd&gt;A pipe crossing is added&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;...so substituting the notation above, we have something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function bubblesort (Dest{st}) {&lt;br /&gt; var int i, j;&lt;br /&gt; st = 0&lt;br /&gt; for i from n downto 1 {&lt;br /&gt;     for j from 1 to i-1 {&lt;br /&gt;         if (Target{st}[j] &gt; Target{st}[j+1]) {&lt;br /&gt;             Target{st+1}[j] := Target{st}[j+1]&lt;br /&gt;             Target{st+1}[j+1] := Target{st}[j]&lt;br /&gt;             st ++&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is an interesting mapping because the paradigmatic bubblesort involves mutable storage, but this version builds a list of successively refined permutations.  Wikipedia of course doesn't define bubblesort this way. Programmers can make this leap with some thought.  Can the concept of "bubblesort" be defined such that something so fundamental is abstracted away?  I'm still wrapping my brain around monads, but I think this is what they are good for.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/08/how-we-talk-about-algorithms_04.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115473371785511985'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/115473371785511985'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-113800107820646531</id><published>2006-01-22T22:12:00.000-08:00</published><updated>2006-01-22T23:25:08.513-08:00</updated><title type='text'>A Different Implementation of Relation-Chaining

O...</title><content type='html'>A Different Implementation of Relation-Chaining&lt;br /&gt;&lt;br /&gt;OK, I wasn't really happy with the implemenation the relation-chaining thing I did last week, so I rewrote it.  This won't make a lot of sense if you haven't read last week's installment, so go read it if you haven't yet...&lt;br /&gt;&lt;br /&gt;This time I have the forward-linking operator sort of equivalent to the python "." operator.  If &lt;span style="font-weight: bold;"&gt;romulus.father == mars&lt;/span&gt;, then &lt;span style="font-weight: bold;"&gt;romulus &gt;&gt; father == rset([mars])&lt;/span&gt;; in other words, the set containing &lt;span style="font-weight: bold;"&gt;mars&lt;/span&gt;.  &lt;span style="font-weight: bold;"&gt;rset&lt;/span&gt; is a class derived from set.  It's convenient to work with sets, because in the case of the reverse-linking operator, there could be more than one result, and I wanted some symmetry between the two cases.&lt;br /&gt;&lt;br /&gt;To do the reverse linking, I use gc.get_objects(), which is python's garbage collector's master list of all the objects in the system.  I guess that's not very efficient for a large program.  In a large program I'd recommend creating a "universe" dictionary, put the objects you really care about it in it, then search that instead of get_objects().&lt;br /&gt;&lt;br /&gt;A nice result of using sets is shown in the brother() function; the set operator "-" means to remove items from a set, so &lt;span style="font-weight: bold;"&gt;(x &gt;&gt; "father" &lt;&lt; "father") - x&lt;/span&gt; means: find the &lt;span style="font-weight: bold;"&gt;father&lt;/span&gt; of &lt;span style="font-weight: bold;"&gt;x&lt;/span&gt;, then find the people &lt;span style="font-weight: bold;"&gt;x&lt;/span&gt; is a &lt;span style="font-weight: bold;"&gt;father&lt;/span&gt; to, then subtract &lt;span style="font-weight: bold;"&gt;x&lt;/span&gt; from that set, leaving only the siblings.&lt;br /&gt;&lt;br /&gt;The only reason I create my own set class, or my own &lt;span style="font-weight: bold;"&gt;relational_object&lt;/span&gt; class, is to get the syntax of &lt;span style="font-weight: bold;"&gt;&lt;&lt;&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;&gt;&gt;&lt;/span&gt; to work.  Really, this is a demonstration of a feature I think could be central to a language, and in that hypothetical language you'd build this feature in so it could be used on any objects.&lt;br /&gt;&lt;br /&gt;Well, here's the code.  I promise I'll move on to something different next week!  I just had to get this out of my system.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/local/bin/python2.4&lt;br /&gt;from gc import get_objects&lt;br /&gt;&lt;br /&gt;class relational_object(object):&lt;br /&gt;  def __repr__(self):&lt;br /&gt;      return "&lt;relational_object:&gt;"&lt;br /&gt;&lt;br /&gt;  def get_conv_gen(self, att):&lt;br /&gt;      for other in get_objects():&lt;br /&gt;          try:&lt;br /&gt;              if other.__dict__[att] == self:&lt;br /&gt;                  yield other&lt;br /&gt;          except Exception, e: pass&lt;br /&gt;&lt;br /&gt;  def get_conv_any(self, att): return self.get_conv_gen(att).next()&lt;br /&gt;  def get_conv_all(self, att): return rset([ x for x in self.get_conv_gen(att)])&lt;br /&gt;&lt;br /&gt;  def __rshift__(self, att):  return rset([self.__dict__[att]])&lt;br /&gt;  def __lshift__(self, att):  return rset(self.get_conv_all(att))&lt;br /&gt;&lt;br /&gt;class rset(set):&lt;br /&gt;  def __rshift__(self, att):&lt;br /&gt;      result = rset()&lt;br /&gt;      for x in self:&lt;br /&gt;          result = result | rset([x.__dict__[att]])&lt;br /&gt;      return result&lt;br /&gt;  def __lshift__(self, att):&lt;br /&gt;      result = rset()&lt;br /&gt;      for x in self:&lt;br /&gt;          result = result | x.get_conv_all(att)&lt;br /&gt;      return result&lt;br /&gt;&lt;br /&gt;class person(relational_object):&lt;br /&gt;  def __init__(self, theName):&lt;br /&gt;      self.name = theName&lt;br /&gt;  def __repr__(self): return "&lt;&gt;"&lt;br /&gt;&lt;br /&gt;mars = person("mars")&lt;br /&gt;romulus = person("romulus")&lt;br /&gt;remus = person("remus")&lt;br /&gt;assert mars == mars&lt;br /&gt;assert mars != remus&lt;br /&gt;&lt;br /&gt;romulus.father = mars&lt;br /&gt;remus.father = mars&lt;br /&gt;&lt;br /&gt;assert mars &lt;&lt; "father" == rset([romulus, remus])   &lt;span style="font-family:Georgia,serif;"&gt;&lt;/span&gt;&lt;/relational_object:&gt;&lt;/pre&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/01/different-implementation-of-relation.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/113800107820646531'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/113800107820646531'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-113728033862876484</id><published>2006-01-14T15:11:00.000-08:00</published><updated>2006-01-14T15:35:53.566-08:00</updated><title type='text'>Relation-chaining gimmick in Python

This is just ...</title><content type='html'>Relation-chaining gimmick in Python&lt;br /&gt;&lt;br /&gt;This is just a piece of a whole idea, but I thought you might find it amusing.&lt;br /&gt;&lt;br /&gt;There is an &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; notation called &lt;a href="http://www.w3.org/DesignIssues/Notation3.html"&gt;N3&lt;/a&gt; that has an interesting syntax for quickly describing a chain of relations linking one node to another.&lt;br /&gt;&lt;br /&gt;Here are some examples from the N3 paper:&lt;br /&gt;&lt;pre&gt;:joe!fam:mother!loc:office!loc:zip   Joe's mother's office's zipcode&lt;br /&gt;:joe!fam:mother^fam:mother           Anyone whose mother is Joe's mother.&lt;br /&gt;&lt;/pre&gt;:joe ("Colon Joe" -- sounds like a brand of medicinal coffee, doesn't it?) is an RDF node.  The other strings with colons in them, fam:mother, loc:office, and loc:zip, represent binary relations.  I think the part before the colon tells you the namespace it's from, but ignore that for now.&lt;br /&gt;&lt;br /&gt;The ! is like the "." operator in most object-oriented languages.  :joe!fam:mother means "Joe's Mother", and you might say this as joe.mother in some language like Python or C.&lt;br /&gt;&lt;br /&gt;The ^ is the converse of !; so if joe!mother == sue, then sue^mother == joe.  You can think of !mother as meaning "mother" and ^mother as meaning "child".  ^employer means employee, ^owner means possession.  "hello, world"!length == 12, so 12^length == "hello, world" (among many other strings).&lt;br /&gt;&lt;br /&gt;My mind was brought back to this when I was working on a project with a bunch of related objects in Python, and I was looking for a clean way of expressing complicated queries among them.  In my day job I do a lot of ad-hoc SQL querying, and while I don't love SQL, it is nice to be able to fluently, readably, ask some complex questions of a bunch of relations.  I'd read that list comprehensions were more or less isomorphic to SQL, but I found when playing with them that my queries were inefficient and not very readable; they were no better than just writing explicit code to traverse the object tree and collect the information I wanted.&lt;br /&gt;&lt;br /&gt;I'm not sure if these N3-style paths will be useful in practice, yet, but it was worth playing around with them.  The biggest hurdle with them, as I see it, is that there's no easy way when presented with 12^length to know what string is wanted, so you have to have a well-defined universe of objects to work with, and be willing to accept multiple results from every query.&lt;br /&gt;&lt;br /&gt;So anyway, here's some code to give you an idea what I've come up with so far:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import pprint&lt;br /&gt;&lt;br /&gt;class relation:&lt;br /&gt; def __init__(self):&lt;br /&gt;     self.forward = dict()&lt;br /&gt;     self.backward = dict()&lt;br /&gt;&lt;br /&gt; def add(self, arg1, arg2):&lt;br /&gt;     if not self.forward.has_key(arg1):&lt;br /&gt;         self.forward[arg1] = dict()&lt;br /&gt;     if not (arg2 in self.forward[arg1]):&lt;br /&gt;         self.forward[arg1][arg2] = True&lt;br /&gt;     if not self.backward.has_key(arg2):&lt;br /&gt;         self.backward[arg2] = dict()&lt;br /&gt;     if not (arg1 in self.backward[arg2]):&lt;br /&gt;         self.backward[arg2][arg1] = True&lt;br /&gt;&lt;br /&gt; def __call__(self, arg1, arg2):&lt;br /&gt;     try:&lt;br /&gt;         return self.forward[arg1][arg2]&lt;br /&gt;     except Exception, e:&lt;br /&gt;         return false&lt;br /&gt;&lt;br /&gt; def get_all_keys(self, hash, key):&lt;br /&gt;     try:&lt;br /&gt;         return hash[key].keys()&lt;br /&gt;     except Exception, e:&lt;br /&gt;         return []&lt;br /&gt;&lt;br /&gt; def __rlshift__(self, other):&lt;br /&gt;     result = []&lt;br /&gt;     for item in other:&lt;br /&gt;        result = result + self.get_all_keys(self.forward, item)&lt;br /&gt;     return result&lt;br /&gt;&lt;br /&gt; def __rrshift__(self, other):&lt;br /&gt;     result = []&lt;br /&gt;     for item in other:&lt;br /&gt;        result = result + self.get_all_keys(self.backward, item)&lt;br /&gt;     return result&lt;br /&gt;&lt;br /&gt;father = relation()&lt;br /&gt;phone = relation()&lt;br /&gt;&lt;br /&gt;class frank: pass&lt;br /&gt;class jeff: pass&lt;br /&gt;class chris: pass&lt;br /&gt;class andy: pass&lt;br /&gt;&lt;br /&gt;father.add(frank, jeff)&lt;br /&gt;father.add(jeff, chris)&lt;br /&gt;father.add(jeff, andy)&lt;br /&gt;phone.add(andy, "101-555-1249")&lt;br /&gt;assert [chris] &gt;&gt; father == [jeff]&lt;br /&gt;assert [jeff] &lt;&lt; father == [chris, andy]&lt;br /&gt;assert [chris] &gt;&gt; father == [jeff]&lt;br /&gt;assert [jeff] &lt;&lt; father == [chris, andy]&lt;br /&gt;assert [andy] &lt;&lt; phone == ["101-555-1249"]&lt;br /&gt;assert [chris] &lt;&lt; phone == []&lt;br /&gt;assert [andy, chris] &lt;&lt; phone == ["101-555-1249"]&lt;br /&gt;assert (([chris] &gt;&gt; father) &lt;&lt; father) &lt;&lt; phone == ["101-555-1249"]&lt;br /&gt;assert [chris] &gt;&gt; father &lt;&lt; father &lt;&lt; phone == ["101-555-1249"]&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Some things to note about this implementation:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I used classes like "jeff" and "chris" for nodes.  You could use any Python objects; the "class X: pass" syntax is just a cheesy quick way to create a dummy object to play around with.  In Python a class is a kind of object.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I used &gt;&gt; and &lt;&lt;&gt;&lt;li&gt;nstead of the RDF "node", I use a list with one or more python objects in it, in this case strings.  I'm using a list as kind of a half-assed &lt;a href="http://en.wikipedia.org/wiki/Monads_in_functional_programming"&gt;monad&lt;/a&gt;.  Since a &gt;&gt; or &lt;&lt;&gt;&lt;li&gt;I define a relation object which holds all its pairs of related things in hashes.  It's probably not very efficient.  I originally thought I'd just use the members of objects as the relations, so that the natural joe.mother would be the basis for the relation joe &gt;&gt; mother.   But that didn't fit in very well with the list thing.  If Heather has two mommies, you can have:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mother("Ann", "Heather")&lt;br /&gt;mother("Patricia", "Heather")&lt;br /&gt;assert ["Heather"] &gt;&gt; mother == ["Ann", "Patricia"]&lt;br /&gt;&lt;/pre&gt;as opposed to&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;heather.mother = ann&lt;br /&gt;heather.mother = patricia&lt;br /&gt;&lt;/pre&gt;where Patricia just overwrites Ann.  This makes Ann sad.&lt;br /&gt;&lt;p&gt;Maybe there's a better way around this.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;I'm not sure I've got the precedence the same as N3 has it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It should be sets, not lists.  ["Ann", "Patricia"] should be considered the same result as ["Patricia", "Ann"].&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Next time I'll try to apply this to a more interesting problem to see if it holds up.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2006/01/relation-chaining-gimmick-in-python.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/113728033862876484'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/113728033862876484'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108695952053701085</id><published>2004-06-11T06:07:00.000-07:00</published><updated>2004-06-11T06:12:00.536-07:00</updated><title type='text'>Paul Graham also has some pie-in-the-sky thoughts ...</title><content type='html'>&lt;a href="http://www.paulgraham.com"&gt;Paul Graham&lt;/a&gt; also has some pie-in-the-sky thoughts about computer languages; see his articles, &lt;a href="http://www.paulgraham.com/hundred.html"&gt;Hundred-year language&lt;/a&gt; and his work on a new dialect of Lisp, &lt;a href="http://www.paulgraham.com/arc.html"&gt;Arc&lt;/a&gt;.  Arc is a little more down-to-earth than the Tunes HLL, and he appears to have done some work on it.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/06/paul-graham-also-has-some-pie-in-sky.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108695952053701085'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108695952053701085'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108695911156617075</id><published>2004-06-11T06:02:00.000-07:00</published><updated>2004-06-11T06:07:19.683-07:00</updated><title type='text'>The Tunes project has some requirements for an unn...</title><content type='html'>The &lt;a href="http://tunes.org/"&gt;Tunes&lt;/a&gt; project has some requirements for an unnamed "&lt;a href="http://tunes.org/HLL/"&gt;High Level Language&lt;/a&gt;" for their project, which has a lot of good ideas init.  As far as I can tell looking at the web page, it's kind of vaporware at this point.  And maybe doomed to remain vaporware, since the requirements seem so abstract and idealistic.  But anyway, some of their ideas have crossed my mind too, and they might at least server as a thoughtful critique of how current programming langauges feel inadequate to people.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/06/tunes-project-has-some-requirements.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108695911156617075'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108695911156617075'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108511564889093015</id><published>2004-05-20T21:37:00.000-07:00</published><updated>2004-05-20T22:00:48.890-07:00</updated><title type='text'>Two good articles by Cory Doctorow (Metacrap) and ...</title><content type='html'>Two good articles by Cory Doctorow (&lt;a href="http://www.well.com/~doctorow/metacrap.htm"&gt;Metacrap&lt;/a&gt;) and Clay Shirky (&lt;a href="http://www.shirky.com/writings/semantic_syllogism.html"&gt;The Semantic Web, Syllogism, and Worldview&lt;/a&gt;), expressing skepticism about the &lt;a href="http://www.w3.org/2001/sw/"&gt;Semantic Web&lt;/a&gt;.  &lt;br /&gt;&lt;p&gt;&lt;br /&gt;Shirky says most human thought isn't deduction from syllogisms, it's much more fuzzy and heuristic than that.  Doctorow points out lots of good reasons why metadata will be crap in practice.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;These ideas relate to better programming languages too.  There's an impedance mismatch between human concepts and the way computer software systems tend to classify things.  We just don't think as rigidly about things as computers do.  We get frustrated with how software will go mindlessly clanking down the wrong path (for example happily cranking out copies of a virus and emailing them to all your friends), but when we try to build smarts into it, we're frustrated by just how &lt;i&gt;dumb&lt;/i&gt; those smarts turn out to be.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Human computer interfaces, from GUIs to languages to development and testing environments, need to help our squishy minds navigate the bizarre tinkertoy syllogismatrons we're forced to build.  While we frantically look for ways to teach software to think more like we do.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/05/two-good-articles-by-cory-doctorow.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108511564889093015'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108511564889093015'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108294009809321262</id><published>2004-04-25T17:39:00.000-07:00</published><updated>2004-04-25T17:49:29.466-07:00</updated><title type='text'>I just stumbled on a weblog about programming lang...</title><content type='html'>I just stumbled on a weblog about programming languages and their design, called &lt;a href="http://lambda.weblogs.com"&gt;Lambda the Ultimate&lt;/a&gt;.  Similar to what I want to do here, although I want to focus more specifically on languages that bridge the gap in some interesting way between natural human languages and traditional computer languages.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/04/i-just-stumbled-on-weblog-about.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108294009809321262'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108294009809321262'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108267546988996680</id><published>2004-04-22T15:51:00.000-07:00</published><updated>2004-04-22T16:15:17.890-07:00</updated><title type='text'>Apocalypse 12 is out.

In case you live in a cav...</title><content type='html'>&lt;a href="http://www.perl.com/pub/a/2004/04/16/a12.html"&gt;Apocalypse 12&lt;/a&gt; is out.&lt;br /&gt;&lt;br /&gt;In case you live in a cave, the Apocalypses are Larry Wall's occasional manifestos (manifesti?) about how some aspect of Perl 6 will work.  I read them with great interest because I like how Wall thinks, and I'm an avid user of Perl, and Perl 6 has some great ideas in it.  I like hyperoperators and the new regular expression syntax.  That being said, I'm getting kind of worried that Perl 6 is going to be too crufty.  Look at what you can do with subroutine signatures.  It seems unnecessarily complex and cryptic.&lt;br /&gt;&lt;br /&gt;Of course I thought that back when I was learning Old Perl, but now I know it well and can use pretty efficiently, so I'll withhold judgment on Perl 6 until I get a chance to use it.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/04/apocalypse-12-is-out.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108267546988996680'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108267546988996680'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108239797072032295</id><published>2004-04-19T10:53:00.000-07:00</published><updated>2004-04-19T11:10:14.373-07:00</updated><title type='text'>What this blog is about

The last post was mostl...</title><content type='html'>What this blog is about&lt;br /&gt;&lt;br /&gt;The last post was mostly a test.  What I want to do here is review computer languages that bridge the gap between computer language and human language in some interesting way.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.lojban.org"&gt;Lojban&lt;/a&gt; is an attempt to make a human language somewhat more approachable by computers -- it has a yacc-parseable grammar that is syntactically unambiguous.  In practice so far it has been used for communication between humans, not to specify or constrain a computer's behavior in any way.  But it's a good example of an effort to think about some of  the differences between the two kinds of language and find halfway points.&lt;br /&gt;&lt;br /&gt;I do think that someday computers will be able to cope with human language.  For programming I think we'll always need something a little more precise (like the language used in human legal contracts, maybe) to avoid some ambiguity.&lt;br /&gt;But that day could be a ways off; why not meet the machine halfway for now?  High-level languages have come a long way from raw machine code in doing this; I'm interested in seeing in what other ways computer languages can be more human without requiring outright artificial intelligence in the computer that uses them.</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/04/what-this-blog-is-about-last-post-was.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108239797072032295'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108239797072032295'></link><author><name>Chris Bogart</name></author></entry><entry><id>tag:blogger.com,1999:blog-6687315.post-108051759420368407</id><published>2004-03-28T15:28:00.000-08:00</published><updated>2004-03-28T15:50:38.686-08:00</updated><title type='text'>Kevo was an object-oriented language where classes...</title><content type='html'>Kevo was an object-oriented language where classes were derived from objects rather than the other way around: a "family" of objects are ones that have the same signature.  Families change dynamically as object properties are changed at runtime.&lt;br /&gt;&lt;br /&gt;I haven't been able to find much detail about Kevo; it looks like it emerged around 1993 and its author is &lt;a href="http://www.cs.tut.fi/~taivalsa/"&gt;Antero Taivalsaari&lt;/a&gt; who has since done a lot of work since then on Mobile Java (J2ME).  Here's an interesting paper that mentions Kevo: &lt;br /&gt;&lt;a href="http://www.helsinki.fi/~jppesone/papers/kandi.html"&gt;Psychological criticism of the Prototype-Based OO-Languages&lt;/a&gt;</content><link rel='alternate' type='text/html' href='http://www.quetzal.com/sambangu/2004/03/kevo-was-object-oriented-language.html'></link><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108051759420368407'></link><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6687315/posts/default/108051759420368407'></link><author><name>Chris Bogart</name></author></entry></feed>