<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;AkQAQXw4fip7ImA9WhVXFUk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972</id><updated>2012-04-15T20:52:20.236-07:00</updated><category term="xpday" /><category term="java" /><category term="welder" /><title>fnargs</title><subtitle type="html">a java dude explores arc</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.fnargs.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/fnargs" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="fnargs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C0cEQHY-eSp7ImA9WxBUGE4.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-1075725258520534</id><published>2010-03-01T14:42:00.000-08:00</published><updated>2010-03-05T15:16:41.851-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-05T15:16:41.851-08:00</app:edited><title>W.A.Mozart KV331: Rondo a la Turca, played by Arc</title><content type="html">&lt;p&gt;&lt;br /&gt;This midi file was written by arc:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo.midi" width="400" height="24"&gt;&lt;br /&gt;  &lt;param name="autoplay" value="false"/&gt;&lt;br /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;b&gt;"too many notes, Mozart!"&lt;/b&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Emperor Joseph II, on hearing Marriage of Figaro&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Musical notation is outrageously repetitive; it seems a ripe candidate for refactoring into a more concise language. Bach had twenty children, and they all had to earn their keep, so he had no shortage of labour for copying out manuscripts, despite which he nonetheless went blind before his death in 1750. So I want to help you make some great music in arc without having to write out zillions of notes all over the place, risking your eyesight in the process. I'm sure you'd like to&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;play:with-feeling&lt;/span&gt; &lt;span class="sym nil"&gt;moonlight-sonata&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;play:vigorously&lt;/span&gt; &lt;span class="sym nil"&gt;mozart-rondo&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;play:quite-seriously&lt;/span&gt; &lt;span class="sym nil"&gt;art-of-fugue&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;as much as I would. Traditional notation is the assembly language of music, it has been waiting centuries for arc! Step aside, Beethoven; out of my way, Chopin ... s-exps FTW!!1!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Here's what I have so far:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;A mini-language for expressing music. ("Language" is a bit of a grandiose term for a ragtag collection of functions and macros)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A converter to convert expressions in this language into midi events.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A writer to write midi events to a midi-format file.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A midi player (rainbow-dependent) that calls a java api to play music.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Only the player depends on rainbow; the rest is vanilla arc.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;em&gt;Rondo a la Turca&lt;/em&gt; is low-hanging fruit for this kind of exercise; it's a short piano piece, there is a lot of duplication, which would make for easy compression were it not for the slight variations in each repetition. For example, the second passage consists of &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/01-rondo-passage-2-opening.png"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo-sample-3.midi" width="200" height="24"&gt;&lt;param name="autoplay" value="false"/&gt;&lt;/object&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/02-rondo-passage-2-alt.png"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo-sample-4.midi" width="200" height="24"&gt;&lt;param name="autoplay" value="false"/&gt;&lt;/object&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;- these are identical except for the hanging half-note at the end of the first version. More insidiously, here are the two variations on the third motif: &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/rondo-passage-3.png" width="500"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo-sample-1.midi" width="200" height="24"&gt;&lt;param name="autoplay" value="false"/&gt;&lt;/object&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/rondo-passage-6.png" width="500"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo-sample-2.midi" width="200" height="24"&gt;&lt;param name="autoplay" value="false"/&gt;&lt;/object&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;It's the same tune, but the first variation specifies a series of notes to be played as octave chords; the second variation specifies the same series of notes, played alternately with their octaves. But I can't express this as a simple transformation; the differences between the passages are not completely consistent.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I'm going to describe how it all works; I'm assuming Dear Reader knows as much about midi as I did when I started, which was approximately nothing, so forgive me if I am mistaken and/or you spot boring bits.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;Simple representation&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Write arc-music by creating lists of notes. This is what a note looks like:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note&lt;/span&gt; &lt;span class="sym nil"&gt;volume&lt;/span&gt; &lt;span class="sym nil"&gt;duration&lt;/span&gt; &lt;span class="sym nil"&gt;.&lt;/span&gt; &lt;span class="sym nil"&gt;options&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="string nil"&gt;; options specify grace notes, staccato, and other decorations&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;A chord is a list of notes to be played simultaneously:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note1&lt;/span&gt; &lt;span class="sym nil"&gt;volume&lt;/span&gt; &lt;span class="sym nil"&gt;duration&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note2&lt;/span&gt; &lt;span class="sym nil"&gt;volume&lt;/span&gt; &lt;span class="sym nil"&gt;duration&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Music is a sequence of chords.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note1&lt;/span&gt; &lt;span class="sym nil"&gt;volume1&lt;/span&gt; &lt;span class="sym nil"&gt;duration1&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note2&lt;/span&gt; &lt;span class="sym nil"&gt;volume2&lt;/span&gt; &lt;span class="sym nil"&gt;duration2&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note3&lt;/span&gt; &lt;span class="sym nil"&gt;vol3&lt;/span&gt; &lt;span class="sym nil"&gt;dur3&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;note4&lt;/span&gt; &lt;span class="sym nil"&gt;vol4&lt;/span&gt; &lt;span class="sym nil"&gt;dur4&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym nil"&gt;etc...&lt;/span&gt; &lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Single notes are expressed as a chord of one note. Hence, the C Major scale&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;assign&lt;/span&gt; &lt;span class="sym nil"&gt;c-major-scale&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;mono&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;d4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;e4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;f4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;          &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;g4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;a4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;b4&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c5&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;or alternatively,&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;assign&lt;/span&gt; &lt;span class="sym nil"&gt;c-major-scale&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;apply&lt;/span&gt; &lt;span class="sym fn"&gt;mono&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;map&lt;/span&gt; &lt;span class="syntax"&gt;[&lt;/span&gt;&lt;span class="sym nil"&gt;_&lt;/span&gt; &lt;span class="sym int"&gt;mp&lt;/span&gt; &lt;span class="sym int"&gt;crotchet&lt;/span&gt;&lt;span class="syntax"&gt;]&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;list&lt;/span&gt; &lt;span class="sym fn"&gt;c4&lt;/span&gt; &lt;span class="sym fn"&gt;d4&lt;/span&gt; &lt;span class="sym fn"&gt;e4&lt;/span&gt; &lt;span class="sym fn"&gt;f4&lt;/span&gt; &lt;span class="sym fn"&gt;g4&lt;/span&gt; &lt;span class="sym fn"&gt;a4&lt;/span&gt; &lt;span class="sym fn"&gt;b4&lt;/span&gt; &lt;span class="sym fn"&gt;c5&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;code&gt;mono&lt;/code&gt; converts a sequence of single notes into a sequence of single-note chords, returning this for &lt;code&gt;c-major-scale&lt;/code&gt;:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;60&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;62&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;64&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;65&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;67&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;69&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;71&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;72&lt;/span&gt; &lt;span class="int nil"&gt;55&lt;/span&gt; &lt;span class="int nil"&gt;16&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;Midi representation&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;With the above simple representation, the start-time for each note is the sum of all preceding note-durations. Midi doesn't work like this though; it requires &lt;code&gt;note-on&lt;/code&gt; and &lt;code&gt;note-off&lt;/code&gt; events, each with an explicit time offset, measured in "ticks". To convert from arc-notation to something more closely resembling midi, use &lt;code&gt;make-music&lt;/code&gt;:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;assign&lt;/span&gt; &lt;span class="sym nil"&gt;music&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;make-music&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;c-major-scale&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Most music makes ample use of simultaneous notes belonging to different voices; it would be a pain to attempt to express these as chords. Separate voices out this way:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;assign&lt;/span&gt; &lt;span class="sym nil"&gt;moonlight&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;make-music&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;moonlight-sonata-right-hand&lt;/span&gt;&lt;br /&gt;                                &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;moonlight-sonata-left-hand&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The &lt;code&gt;0&lt;/code&gt; specifies the midi channel to use, and &lt;code&gt;make-music&lt;/code&gt; generates something like&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;60&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;4&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;60&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;4&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;62&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;8&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;62&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;8&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;12&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;12&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;65&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;16&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;65&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;16&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;67&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;20&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;67&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;20&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;69&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;24&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;69&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;24&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;71&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;28&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;71&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;28&lt;/span&gt; &lt;span class="sym nil"&gt;note-on&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;72&lt;/span&gt; &lt;span class="int nil"&gt;64&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="int nil"&gt;32&lt;/span&gt; &lt;span class="sym nil"&gt;note-off&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="int nil"&gt;72&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;This list is very close to the structure of an actual midi file, except here I use absolute tick offsets, whereas midi stores delta tick offsets from each event to the next. Items in this list have the following structure:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tick-offset&lt;/span&gt; &lt;span class="sym nil"&gt;event-type&lt;/span&gt; &lt;span class="sym nil"&gt;channel&lt;/span&gt; &lt;span class="sym nil"&gt;key&lt;/span&gt; &lt;span class="sym nil"&gt;velocity&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;code&gt;tick&lt;/code&gt; is the offset in ticks from the start of the music when this event should occur; you control the tempo of your music by varying ticks-per-second. Event-type is note-on or note-off (for now; more types coming later); channel specifies the midi channel, so you can play several instruments simultaneously; key corresponds to pitch for most instruments, and velocity to volume (the loudness of a piano keystroke depends on the velocity with which it is struck).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;Facing the music&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;If you're using &lt;a href="http://github.com/conanite/rainbow"&gt;rainbow&lt;/a&gt;, you can pass this list of note-events to &lt;code&gt;play-sequence&lt;/code&gt; and actually hear something come out of your speakers.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;play-sequence&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;make-music&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;c-major-scale&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;You could play more interesting stuff by combining voices:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;play-sequence&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;make-music&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;violins-1-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="sym nil"&gt;violins-2-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;1&lt;/span&gt; &lt;span class="sym nil"&gt;viola-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="sym nil"&gt;cello-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;3&lt;/span&gt; &lt;span class="sym nil"&gt;trombone-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;4&lt;/span&gt; &lt;span class="sym nil"&gt;trumpet-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;5&lt;/span&gt; &lt;span class="sym nil"&gt;oboe-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;6&lt;/span&gt; &lt;span class="sym nil"&gt;flute-1-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;6&lt;/span&gt; &lt;span class="sym nil"&gt;flute-2-part&lt;/span&gt;&lt;br /&gt;                             &lt;span class="int nil"&gt;7&lt;/span&gt; &lt;span class="sym nil"&gt;percussion-part&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I haven't tried anything this complex yet. The &lt;code&gt;play-sequence&lt;/code&gt; function supports tempo control - I haven't worked that into the midi writer yet.&lt;br /&gt;&lt;br /&gt;Depending on your OS and version of java, you may hear music, or something resembling a flatulent wasp. The wasp finally quit my machine after the java update for MacOS in December last year.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;The music notation "language"&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Having transcribed only two small pieces of keyboard music, I haven't made much language - so far there are only a few simple elements.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Pitch definitions&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;c1 d1 e1 f1 ... all the way up to f8 g8 a8 b8. Each of these symbols defines a function that creates the corresponding arc-music note.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c4&lt;/span&gt; &lt;span class="sym int"&gt;quarter&lt;/span&gt; &lt;span class="sym fn"&gt;quiet&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;returns &lt;code&gt;(60 4 48)&lt;/code&gt;. Sometimes you need to transform a given starting note, so&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c4&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym fn"&gt;transform&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;returns a function that is identical to &lt;code&gt;d4&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The "four-note sequence"&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;It quickly becomes tedious to write out individual notes, even if they have lovely names. It is the nature of music that small sequences are repeated, perhaps transposed, inverted, or extended. In this example,&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://home.conandalton.net/arc-midi/08-four-note-sequences.png"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;four of the six groups of notes are painfully close to being the same thing. Wouldn't it be nice to use a function to create that shape,&lt;br /&gt;taking a pitch and duration parameter? So instead of repeating &lt;code&gt;(mono (c4 mf quaver) (d4 mf quaver) (e4 mf quaver) (f4 mf quaver))&lt;/code&gt;, you can write &lt;code&gt;(s2/4/5 c4 mf mf quaver)&lt;/code&gt;. The 2/4/5 represent the semitone interval count between the first note of the sequence and each subsequent note.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Here are a couple of examples:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/09-b-a-g-a-sequence.png"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;code&gt;(s-2/-3/-2 b5 f)&lt;/code&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/10-es-fs-gs-fs-sequence.png"/&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;code&gt;(s1/3/0 f5 f)&lt;/code&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The &lt;code&gt;sX/Y/Z&lt;code&gt; functions are generated from a simple macro invocation. This&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;four-note-sequence&lt;/span&gt;&lt;br /&gt;    &lt;span class="int nil"&gt;2&lt;/span&gt;  &lt;span class="int nil"&gt;3&lt;/span&gt;  &lt;span class="int nil"&gt;5&lt;/span&gt;&lt;br /&gt;    &lt;span class="int nil"&gt;2&lt;/span&gt;  &lt;span class="int nil"&gt;4&lt;/span&gt; &lt;span class="int nil"&gt;-3&lt;/span&gt;&lt;br /&gt;    &lt;span class="int nil"&gt;2&lt;/span&gt;  &lt;span class="int nil"&gt;4&lt;/span&gt;  &lt;span class="int nil"&gt;0&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;generates the functions &lt;code&gt;s/2/3/5&lt;/code&gt;,  &lt;code&gt;s/2/4/-3&lt;/code&gt;,  &lt;code&gt;s/2/4/0&lt;/code&gt;. So it is trivial to extend the vocabulary of this language for other sequences. There is no &lt;code&gt;three-note-sequence&lt;/code&gt; macro yet, but &lt;em&gt;Rondo&lt;/em&gt; didn't need it. (BWV 147 will, so it's coming)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;&lt;br /&gt;Volume control&lt;br /&gt;&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;code&gt;amp&lt;/code&gt; transforms the loudness of notes in a sequence. For example &lt;code&gt;((amp 20) c-major-scale)&lt;/code&gt; makes our C Major scale 20 midi-velocity-units louder. &lt;code&gt;loud&lt;/code&gt; and &lt;code&gt;quiet&lt;/code&gt; are shortcuts for &lt;code&gt;(amp 16)&lt;/code&gt; and &lt;code&gt;(amp -16)&lt;/code&gt;, respectively.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;code&gt;((crescendo 20 8) c-major-scale)&lt;/code&gt; transforms the scale by applying a smooth crescendo over the sequence of 8 notes.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;An example&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The result is pretty ugly. I'm not sure how to improve it; music is at least two-dimensional, code is mostly unidimensional. Compare the musical notation for the opening motif&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;img src="http://home.conandalton.net/arc-midi/07-rondo-passage-1-opening.png"/&gt;&lt;/td&gt;&lt;td&gt;&lt;object data="http://home.conandalton.net/arc-midi/rondo-sample-5.midi" width="200" height="24"&gt;&lt;param name="autoplay" value="false"/&gt;&lt;/object&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;with the arc version:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym fn"&gt;rondo-theme&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;cresc&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;+&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;s-2/-3/-2&lt;/span&gt; &lt;span class="sym fn"&gt;b4&lt;/span&gt; &lt;span class="int nil"&gt;80&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;mono&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c5&lt;/span&gt; &lt;span class="int nil"&gt;100&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;staccato&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;pause&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;s-2/-3/-2&lt;/span&gt; &lt;span class="sym fn"&gt;d5&lt;/span&gt; &lt;span class="int nil"&gt;80&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;mono&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;e5&lt;/span&gt; &lt;span class="int nil"&gt;100&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;staccato&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;pause&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;s-2/-3/-2&lt;/span&gt; &lt;span class="sym fn"&gt;f5&lt;/span&gt; &lt;span class="int nil"&gt;80&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;if&lt;/span&gt; &lt;span class="sym nil"&gt;cresc&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;crescendo&lt;/span&gt; &lt;span class="int nil"&gt;20&lt;/span&gt; &lt;span class="int nil"&gt;8&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym fn"&gt;idfn&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;repeat-list&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;s-2/-3/-2&lt;/span&gt; &lt;span class="sym fn"&gt;b5&lt;/span&gt; &lt;span class="int nil"&gt;80&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;mono&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;c6&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;if&lt;/span&gt; &lt;span class="sym nil"&gt;cresc&lt;/span&gt; &lt;span class="int nil"&gt;120&lt;/span&gt; &lt;span class="int nil"&gt;100&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="int nil"&gt;4&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;Success?&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;In terms of compression, here are the stats:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;rondo.arc: 2586 tokens, 346 lines&lt;br /&gt;&lt;/li&gt;&lt;li&gt;rondo-left-hand: 848 items&lt;br /&gt;&lt;/li&gt;&lt;li&gt;rondo-right-hand: 1129 items&lt;br /&gt;&lt;/li&gt;&lt;li&gt;total: 1977 items, where an item corresponds roughly to a note in a traditional printed score.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;rondo-music: 5699 midi events (half of them being 'note-on events, the other half note-off)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;resulting midi file, not using any size optimisations: 22864 bytes.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;So there are somewhat fewer arc tokens than there are note-on events. It doesn't feel like victory yet though, because &lt;code&gt;s/2/4/5&lt;/code&gt; isn't jumping off the page and ringing bells for me. It's not exactly &lt;a href="http://en.wikipedia.org/wiki/Emily_Howell"&gt;Emily Howell&lt;/a&gt; yet (having a day job and a family is likely to delay progress on that goal). You have ideas for making this better; I'm all ears.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Get the code&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I don't know why you'd want to do this: the api is still unstable, and its use is error-prone and frustrating.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;  &lt;td&gt;&lt;a href="http://github.com/conanite/rainbow/raw/master/src/arc/lib/midi/midi.arc"&gt;arc/lib/midi/midi.arc&lt;/a&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;Collection of functions and macros for declaring music&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;  &lt;td&gt;&lt;a href="http://github.com/conanite/rainbow/raw/master/src/arc/lib/midi/rondo.arc"&gt;arc/lib/midi/rondo.arc&lt;/a&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;Defines &lt;code&gt;rondo-music&lt;/code&gt;, which can subsequently be passed to a midi writer or player&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;  &lt;td&gt;&lt;a href="http://github.com/conanite/rainbow/raw/master/src/arc/lib/midi/midi-writer.arc"&gt;arc/lib/midi/midi-writer.arc&lt;/a&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;Defines &lt;code&gt;write-midi-file&lt;/code&gt; which outputs your music in midi format (format type 0, the simplest). Supports the bare minimum&lt;br /&gt;      for playing music - note-on and note-off events. No support for any other event type yet.&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;  &lt;td&gt;&lt;a href="http://github.com/conanite/rainbow/raw/master/src/arc/rainbow/midi/midi.arc"&gt;arc/rainbow/midi/midi.arc&lt;/a&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;(rainbow-dependent) Defines &lt;code&gt;play-sequence&lt;/code&gt;, which uses a java api to play midi music, and &lt;br /&gt;      &lt;code&gt;rondo&lt;/code&gt;, a convenience function to load dependent libraries and invoke &lt;code&gt;(play-sequence rondo-music)&lt;/code&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The fastest way to get this running on your machine is to clone &lt;a href="http://github.com/conanite/rainbow"&gt;rainbow from github&lt;/a&gt;, and run either rainbow or scheme from your working copy.&lt;br /&gt;&lt;br /&gt;Playing &lt;i&gt;Rondo&lt;/i&gt; from rainbow is as easy as&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;rondo&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Write it to a midi file like this&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;write-midi-to&lt;/span&gt; &lt;span class="syntax"&gt;"&lt;/span&gt;&lt;span class="string nil"&gt;rondo.midi&lt;/span&gt;&lt;span class="syntax"&gt;"&lt;/span&gt; &lt;span class="sym cons"&gt;rondo-music&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;br /&gt;Acknowledgements&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.skytopia.com/project/articles/midi.html"&gt;Skytopia: Crash course on the standard MIDI specification&lt;/a&gt; and&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sonicspot.com/guide/midifiles.html"&gt;MIDI File Format - The Sonic Spot&lt;/a&gt; helped me make sense of the midi format.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.mutopiaproject.org/cgibin/piece-info.cgi?id=108"&gt;The Mutopia project&lt;/a&gt; hosts free/open-source PDFs of sheet music, and&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://lilypond.org/"&gt;LilyPond ... music notation for everyone&lt;/a&gt; is the awesome sheet music layout engine that produced the mozart excerpts I've used in this article.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-1075725258520534?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/1075725258520534/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=1075725258520534" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/1075725258520534?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/1075725258520534?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2010/03/wamozart-kv331-rondo-la-turca-played-by.html" title="W.A.Mozart KV331: Rondo a la Turca, played by Arc" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;DEEMSHo5eCp7ImA9WxJUFk0.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-5932178343474987738</id><published>2009-07-14T13:41:00.000-07:00</published><updated>2009-07-14T14:24:49.420-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-14T14:24:49.420-07:00</app:edited><title>Flowers and Spirals and iterated complex functions</title><content type="html">&lt;p&gt;Take a look at &lt;a href="http://spiral.fnargs.com/spiral-intro.html"&gt;spiral.fnargs.com&lt;/a&gt; - it's a plotter for the function that generates the Mandelbrot fractal:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  z &amp;lt;- z&lt;sup&gt;&lt;small&gt;2&lt;/small&gt;&lt;/sup&gt; + c&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;These are some of the images it generates:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7sjE3SRdZhk/Slz2jCNhQlI/AAAAAAAAAKQ/E1lhGybH3tY/s1600-h/8-arm-exploded.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_7sjE3SRdZhk/Slz2jCNhQlI/AAAAAAAAAKQ/E1lhGybH3tY/s400/8-arm-exploded.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5358428738413478482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br class="forReal"/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7sjE3SRdZhk/Slz2i8dMGfI/AAAAAAAAAKI/M7J9ptno0ck/s1600-h/7-petal-flower.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_7sjE3SRdZhk/Slz2i8dMGfI/AAAAAAAAAKI/M7J9ptno0ck/s400/7-petal-flower.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5358428736868588018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br class="forReal"/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_7sjE3SRdZhk/Slz2imbmeQI/AAAAAAAAAKA/txvnXZVzfyc/s1600-h/4-arm-tight.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_7sjE3SRdZhk/Slz2imbmeQI/AAAAAAAAAKA/txvnXZVzfyc/s400/4-arm-tight.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5358428730956347650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It's written in arc, using rainbow (in order to access java's image libraries; it could also be done using shell calls to ImageMagick from arc3).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Enjoy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-5932178343474987738?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/5932178343474987738/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=5932178343474987738" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5932178343474987738?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5932178343474987738?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2009/07/flowers-and-spirals-and-iterated.html" title="Flowers and Spirals and iterated complex functions" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_7sjE3SRdZhk/Slz2jCNhQlI/AAAAAAAAAKQ/E1lhGybH3tY/s72-c/8-arm-exploded.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;DUQDQ3g-eSp7ImA9WxJQE0s.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-5385608539774971435</id><published>2009-05-26T12:43:00.000-07:00</published><updated>2009-05-26T12:49:32.651-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-26T12:49:32.651-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xpday" /><title>Arc at XP Day France</title><content type="html">&lt;p&gt;Today's arc presentation at &lt;a href="http://xpday.fr/"&gt;XP Day France&lt;/a&gt; -&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;iframe src='http://docs.google.com/EmbedSlideshow?id=dg93d8cv_68c2xw9jd5' frameborder='0' width='410' height='342'&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-5385608539774971435?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/5385608539774971435/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=5385608539774971435" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5385608539774971435?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5385608539774971435?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2009/05/arc-at-xp-day-france.html" title="Arc at XP Day France" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;C0AMR3o7fip7ImA9WxJRGEg.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-1061486435447319444</id><published>2009-05-20T12:15:00.000-07:00</published><updated>2009-05-20T13:36:26.406-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T13:36:26.406-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="welder" /><title>Introducing Welder</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7sjE3SRdZhk/ShRlRhhNxqI/AAAAAAAAAJg/fT5poEZDDYY/s1600-h/Picture+159.png"&gt;&lt;img style="cursor:pointer; float: left;" src="http://2.bp.blogspot.com/_7sjE3SRdZhk/ShRlRhhNxqI/AAAAAAAAAJg/fT5poEZDDYY/s400/Picture+159.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5338002810070746786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;When I read Gödel, Escher, Bach, I decided to drop my literature degree and take a computing one instead to learn Lisp. That didn't happen ... I got as far as expertly and elegantly configuring a key binding or two in my ~/.emacs file while struggling with java-mode. Many years later, arc came out, and Paul Graham being who he is, I just had to take a look. Maybe I could build an online ecommerce solution with this stuff, get rich, and turn into an Angel.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Anyway, the first thing I noticed was that I didn't have an editor for arc. Intellij wasn't going to cut the mustard, I wasn't falling in love with Textmate despite those gorgeous RoR screencasts, and I didn't feel like learning DrScheme. And none of these options would give me arc-aware highlighting and evaluation in any case.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So I decided to try what anyone learning a new language should try: write an editor for it. In it. On top of that, I needed something to drive rainbow that would demonstrate easy java integration without polluting the elegance of the arc spirit. And lo, Welder was born. Welder is an arc editor, written in arc. You'll have to forgive, or at least tolerate, the pun. The name "arc" invites it, what else could I do?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Don't get excited - Welder isn't quite ready for prime-time. It's too slow to parse a file (around 5 seconds for arc.arc - 2.5k lines, 13k tokens). The slowness is in the tokeniser, so I'm concentrating my speed-up efforts there. For smaller files (~3k tokens), its performance is tolerable.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;These were the minimal required features I started with:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Syntax colouring: strings, numbers, characters, should have their own colours, and symbols should be coloured differently depending on their current bound value, if any. This way it's easy to see if a local variable is shadowing a globally bound symbol, and what kind of a thing it's shadowing.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Paren-matching - highlight matching parentheses, brackets, string delimiters, and any other kind of delimiter that might arise in the future. Also, highlight unbalanced delimiters.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easy selection of forms: I'm addicted to intellij's "widen selection" - I want to be able to select the entire form enclosing the current expression, in such a way that repeated application selects an increasingly wider scope. This makes copy/paste operations a lot simpler.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Eval: I want to eval the currently selected expression, or the whole file, with a single keystroke&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Htmlify: there's no point in writing arc if you're not going to blog about it. But what a pain to reproduce all that syntax highlighting! and besides, if arc gets its herokugarden, this might be a useful part of it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Configurable keystrokes for all actions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Pretty-printing (doesn't work terribly well)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As well as all the usual editor facilities: undo/redo, cut/copy/paste. Fortunately, java/swing comes with this kind of thing pre-packaged.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Added later:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Font-size control - essential to demo welder on a projector&lt;/li&gt;&lt;br /&gt;&lt;li&gt;"pop-form" - replace &lt;code&gt;(foo (bar))&lt;/code&gt; with &lt;code&gt;(bar)&lt;/code&gt; if the cursor is on &lt;code&gt;bar&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;"push-form" - replace &lt;code&gt;x&lt;/code&gt; with &lt;code&gt;( x)&lt;/code&gt; - these two together are really useful for inserting/removing a little &lt;code&gt;do&lt;/code&gt;, &lt;code&gt;atomic&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt;, &lt;code&gt;debug&lt;/code&gt; or whatever you need for quick refactorings&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Note the paren-matching:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor: pointer; width: 320px; height: 73px;" src="http://1.bp.blogspot.com/_7sjE3SRdZhk/ShRd44sP-xI/AAAAAAAAAI4/7-RxJ7Kh-ds/s320/Picture+160.png" alt="" id="BLOGGER_PHOTO_ID_5337994690212920082" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And easy form-selection:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor: pointer; width: 320px; height: 70px;" src="http://1.bp.blogspot.com/_7sjE3SRdZhk/ShRd5PU6vaI/AAAAAAAAAJA/zBwlB0t-bHc/s320/Picture+161.png" alt="" id="BLOGGER_PHOTO_ID_5337994696289074594" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Context help for symbol under caret (help text, if present, and the help system, are entirely thanks to the tireless efforts of anarki contributors)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor: pointer; width: 320px; height: 122px;" src="http://2.bp.blogspot.com/_7sjE3SRdZhk/ShRd5ZaqBJI/AAAAAAAAAJI/J-AtyoQhzh4/s320/Picture+162.png" alt="" id="BLOGGER_PHOTO_ID_5337994698997499026" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And the complete list of current keybindings:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_7sjE3SRdZhk/ShRd5aSoN-I/AAAAAAAAAJQ/4zkgRB6nHas/s320/Picture+163.png" alt="" id="BLOGGER_PHOTO_ID_5337994699232262114" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Welder is still outrageously incomplete. Here are the kinds of thing I would like to add:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Visual macro expander&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Common refactorings that are annoying to do by hand - toggle between &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;with&lt;/code&gt; for example&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Navigate to source of symbol declarations&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Appropriate highlighting for lexically-bound symbols (I don't know how to do this when the scope is created by a macro, other than macexing everything and working backwards)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Runtime analysis&lt;/li&gt;&lt;br /&gt;&lt;li&gt;and everything else ... &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Please suggest and vote for your favourite features!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Welder requires anarki, and is distributed with rainbow on github at &lt;a href="http://github.com/conanite/rainbow/tree/master"&gt;http://github.com/conanite/rainbow/tree/master&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-1061486435447319444?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/1061486435447319444/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=1061486435447319444" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/1061486435447319444?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/1061486435447319444?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2009/05/introducing-welder.html" title="Introducing Welder" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_7sjE3SRdZhk/ShRlRhhNxqI/AAAAAAAAAJg/fT5poEZDDYY/s72-c/Picture+159.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUMBR386cCp7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-5374900942889935744</id><published>2009-01-23T01:43:00.000-08:00</published><updated>2009-05-20T12:24:16.118-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:24:16.118-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><title>calling java from arc</title><content type="html">&lt;p&gt;Rainbow adds six builtin functions for calling java code from arc. Theoretically this is all you need to interact with any java library from arc code.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-new (classname . args)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Create and return a new instance of &lt;code&gt;classname&lt;/code&gt;, passing &lt;code&gt;args&lt;/code&gt; to the constructor&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-class (classname)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Return a &lt;code&gt;java-object&lt;/code&gt; wrapping the class identified by &lt;code&gt;classname&lt;/code&gt;&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-invoke (obj method . args)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Invoke &lt;code&gt;method&lt;/code&gt; on &lt;code&gt;obj&lt;/code&gt; with &lt;code&gt;args&lt;/code&gt;. &lt;code&gt;'defcall&lt;/code&gt; binds this function to &lt;code&gt;java-object&lt;/code&gt; so that you should only rarely need to call this explicitly. Return the value of the method if there&lt;br /&gt;is any, wrapping into arc types where possible.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-static-invoke (classname method . args)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Invoke static &lt;code&gt;method&lt;/code&gt; on &lt;code&gt;classname&lt;/code&gt; with &lt;code&gt;args&lt;/code&gt;.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-static-field (classname fieldname)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Return the value of the specified static field&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;&lt;code&gt;java-implement (interfacename strictly methods)&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;Returns a &lt;code&gt;java-object&lt;/code&gt; which implements the java interface identified by &lt;code&gt;interfacename&lt;/code&gt;, the implementation being provided by the arc code given in &lt;code&gt;methods&lt;/code&gt;, where &lt;code&gt;methods&lt;/code&gt; is a hash mapping method-name to corresponding implementation. The &lt;code&gt;strictly&lt;/code&gt; parameter determines whether an error should be raised if &lt;code&gt;methods&lt;/code&gt; does not include all of the methods defined on the interface. &lt;code&gt;java-implement&lt;/code&gt; is necessary for implementing, for example, mouse and keyboards handlers for a desktop application, or servlets and filters for a web application.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Following in the arc tradition of using arc-code wrappers for builtin functions (eg &lt;code&gt;'w/stdout&lt;/code&gt; for &lt;code&gt;'call-w/stdout&lt;/code&gt;, &lt;code&gt;'atomic&lt;/code&gt; for &lt;code&gt;'atomic-invoke&lt;/code&gt;, &lt;code&gt;'thread&lt;/code&gt; for &lt;code&gt;'new-thread&lt;/code&gt;), rainbow provides some wrappers to make java interaction a little less ugly and possibly a little more arcish. The &lt;code&gt;'implement&lt;/code&gt; macro removes some boilerplate around &lt;code&gt;'java-implement&lt;/code&gt;, so you can create an implementation of, for example, an iterator (where &lt;code&gt;xs&lt;/code&gt; is a list) thus:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym nil"&gt;to-iterator&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;xs&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;implement&lt;/span&gt; &lt;span class="string nil"&gt;&amp;#34;java.util.Iterator&amp;#34;&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;hasNext&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym nil"&gt;xs&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;next&lt;/span&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;pop&lt;/span&gt; &lt;span class="sym nil"&gt;xs&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The &lt;code&gt;'bean&lt;/code&gt; function instantiates and configures a java object via its setter methods. Here is an example of creating a &lt;code&gt;JFrame&lt;/code&gt; object, specifying its bounds and title:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym fn"&gt;frame&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;left&lt;/span&gt; &lt;span class="sym nil"&gt;top&lt;/span&gt; &lt;span class="sym nil"&gt;width&lt;/span&gt; &lt;span class="sym nil"&gt;height&lt;/span&gt; &lt;span class="sym nil"&gt;title&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;bean&lt;/span&gt; &lt;span class="string nil"&gt;&amp;#34;javax.swing.JFrame&amp;#34;&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;bounds&lt;/span&gt;       &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;list&lt;/span&gt; &lt;span class="sym nil"&gt;left&lt;/span&gt; &lt;span class="sym nil"&gt;top&lt;/span&gt; &lt;span class="sym nil"&gt;width&lt;/span&gt; &lt;span class="sym nil"&gt;height&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;title&lt;/span&gt;        &lt;span class="sym nil"&gt;title&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;contentPane&lt;/span&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;box&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;vertical&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Behind the scenes, &lt;code&gt;bean&lt;/code&gt; is going to call &lt;code&gt;setBounds&lt;/code&gt;, &lt;code&gt;setTitle&lt;/code&gt;, and &lt;code&gt;setContentPane&lt;/code&gt; on a newly-instantiated &lt;code&gt;JFrame&lt;/code&gt; object, finally returning the &lt;code&gt;JFrame&lt;/code&gt;. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There are lots more goodies defined in rainbow's &lt;code&gt;swing.arc&lt;/code&gt;, but that's a topic for another day.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-5374900942889935744?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/5374900942889935744/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=5374900942889935744" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5374900942889935744?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/5374900942889935744?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2009/01/calling-java-from-arc.html" title="calling java from arc" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUEFQXw_cSp7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-4959216868960169889</id><published>2008-06-12T15:07:00.000-07:00</published><updated>2009-05-20T12:26:50.249-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:26:50.249-07:00</app:edited><title>Let There Be Local Variables</title><content type="html">&lt;p&gt;Actually, there aren't any. There are only function parameters. But there's a workaround: use functions.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Suppose you're writing a token analyser for some input. 'token-generator is a generator function. You need to determine the type of a token - return 'string if you think it's a string, 'char, 'int, etc. Naïvely, you might&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym nil"&gt;token-type&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;get-token-type&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym nil"&gt;get-token-type&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\&amp;#34;&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym fn"&gt;string&lt;/span&gt;&lt;br /&gt;      &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\#&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;char&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;is-digit&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;int&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So you get your input from 'token-generator, but you're really interested in 'tok. So the function 'get-token-type provides the local variable 'tok for you to work with. The disadvantage is that your namespace gets polluted with a zillion little functions that are only useful to their immediate neighbours. Wouldn't it be nice to, like, click &lt;i&gt;Refactor &amp;gt; Inline Method&lt;/i&gt; like you can in a real language?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Well, you can.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym nil"&gt;token-type&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\&amp;#34;&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym fn"&gt;string&lt;/span&gt;&lt;br /&gt;        &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\#&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;char&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;is-digit&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;int&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The &lt;code&gt;( &lt;span style="background:lightblue"&gt;(fn (&lt;span style="background:#FCC"&gt;tok&lt;/span&gt;) (if blah))&lt;/span&gt; &lt;span style="background:#FCC"&gt;(token-generator)&lt;/span&gt; )&lt;/code&gt; is a call to an anonymous function that declares the 'tok parameter for you to work with.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now your namespace is no longer polluted, but you have this damned ugly thing in the middle of your function. No ordinary human is expected to read this.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Enter 'let&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;'let is a macro that transforms its humanly-readable input into something resembling the mess above.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;def&lt;/span&gt; &lt;span class="sym nil"&gt;token-type&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;let&lt;/span&gt; &lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;token-generator&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\&amp;#34;&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym fn"&gt;string&lt;/span&gt;&lt;br /&gt;        &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;is&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt; &lt;span class="char nil"&gt;#\#&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;char&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;is-digit&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;tok&lt;/span&gt; &lt;span class="int nil"&gt;0&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="syntax"&gt;'&lt;/span&gt;&lt;span class="sym nil"&gt;int&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;'let lets you pretend you are actually declaring a local variable. Coming from another language, you might think that this is, really and truly, a local variable. It's not. Behind the scenes, it's an anonymous function creating a lexically scoped 'tok parameter. But you don't care. You have your local variable.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here is the pattern:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;let&lt;/span&gt; &lt;span class="sym string"&gt;a&lt;/span&gt; &lt;span class="sym string"&gt;b&lt;/span&gt; &lt;span class="sym string"&gt;stuff&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;becomes:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym string"&gt;a&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym string"&gt;stuff&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym string"&gt;b&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;'with is a more general purpose macro that does the same thing, but for multiple variables.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;with&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym string"&gt;a&lt;/span&gt; &lt;span class="int nil"&gt;1&lt;/span&gt; &lt;span class="sym string"&gt;b&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="sym string"&gt;c&lt;/span&gt; &lt;span class="int nil"&gt;3&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym nil"&gt;stuff&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;becomes:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym string"&gt;a&lt;/span&gt; &lt;span class="sym string"&gt;b&lt;/span&gt; &lt;span class="sym string"&gt;c&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym nil"&gt;stuff&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="int nil"&gt;1&lt;/span&gt; &lt;span class="int nil"&gt;2&lt;/span&gt; &lt;span class="int nil"&gt;3&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;'let exists because in the special case of binding just one variable, we don't need parens to separate the variable bindings from the body of the code. Just because you write in lisp doesn't mean you actually &lt;i&gt;like&lt;/i&gt; parens ...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-4959216868960169889?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/4959216868960169889/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=4959216868960169889" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/4959216868960169889?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/4959216868960169889?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/06/let-there-be-local-variables.html" title="Let There Be Local Variables" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUAFQ3w6eip7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-6341988623665949744</id><published>2008-06-05T12:21:00.000-07:00</published><updated>2009-05-20T12:28:32.212-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:28:32.212-07:00</app:edited><title>To Do: If Only ...</title><content type="html">&lt;p&gt;One of the simplest and most pervasive macros in arc is "do". "do" is useful when you need to evaluate a sequence of expressions, but you only have room for one. A common case is when evaluating conditionals:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="sym nil"&gt;a&lt;/span&gt; &lt;span class="sym nil"&gt;b&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;c&lt;/span&gt; &lt;span class="sym nil"&gt;d&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;e&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This corresponds to the following in java:&lt;br /&gt;&lt;pre&gt;if (a) { &lt;br /&gt;  return b; &lt;br /&gt;} else if (c) {&lt;br /&gt;  return d;&lt;br /&gt;} else {&lt;br /&gt;  return e;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In java, we can execute as many statements as we desire within a &lt;code&gt;{ }&lt;/code&gt; block; arc however allows only a single expression as return value. So if we wanted&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;if (a) { &lt;br /&gt;  b();&lt;br /&gt;  c();&lt;br /&gt;  return d; &lt;br /&gt;} else if (e) {&lt;br /&gt;  return f;&lt;br /&gt;} else {&lt;br /&gt;  return g;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;we can't just write&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="sym nil"&gt;a&lt;/span&gt; &lt;span class="sym nil"&gt;b&lt;/span&gt; &lt;span class="sym nil"&gt;c&lt;/span&gt; &lt;span class="sym nil"&gt;d&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;e&lt;/span&gt; &lt;span class="sym nil"&gt;f&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;g&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Hence, do.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="sym nil"&gt;a&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym mac"&gt;do&lt;/span&gt; &lt;span class="sym nil"&gt;b&lt;/span&gt; &lt;span class="sym nil"&gt;c&lt;/span&gt; &lt;span class="sym nil"&gt;d&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;e&lt;/span&gt; &lt;span class="sym nil"&gt;f&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;g&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;code&gt;do&lt;/code&gt; expands into a call to a no-arg function containing &lt;code&gt;b c d&lt;/code&gt; - &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym nil"&gt;b&lt;/span&gt; &lt;span class="sym nil"&gt;c&lt;/span&gt; &lt;span class="sym nil"&gt;d&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; - it defines an anonymous zero-arg function and immediately calls it. Hence, &lt;code&gt;b c d&lt;/code&gt; are grouped in a single expression, and will work as desired inside a conditional:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class='arc'&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym fn"&gt;if&lt;/span&gt; &lt;span class="sym string"&gt;a&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="sym nil"&gt;fn&lt;/span&gt; &lt;span class="syntax"&gt;(&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt; &lt;span class="sym string"&gt;b&lt;/span&gt; &lt;span class="sym string"&gt;c&lt;/span&gt; &lt;span class="sym nil"&gt;d&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;e&lt;/span&gt; &lt;span class="sym nil"&gt;f&lt;/span&gt;&lt;br /&gt;    &lt;span class="sym nil"&gt;g&lt;/span&gt;&lt;span class="syntax"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-6341988623665949744?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/6341988623665949744/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=6341988623665949744" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/6341988623665949744?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/6341988623665949744?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/06/to-do-if-only.html" title="To Do: If Only ..." /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUQNSXc7fip7ImA9WxdXEEg.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-278863810432080767</id><published>2008-05-29T12:36:00.000-07:00</published><updated>2008-06-21T06:03:18.906-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-21T06:03:18.906-07:00</app:edited><title>arc functions</title><content type="html">So the long and the short of it is, we get arc to evaluate expressions. Atoms mostly evaluate to themselves: strings, characters, and numbers. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;arc&amp;gt; "foo"&lt;br /&gt;"foo"&lt;br /&gt;arc&amp;gt; 12&lt;br /&gt;12&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Symbols are also atoms, but have the special property that they may be defined to have some other value. Quoting a symbol means it doesn't get evaluated.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;arc&amp;gt; 'bar&lt;br /&gt;bar&lt;br /&gt;arc&amp;gt; (set bar "toto")&lt;br /&gt;"toto"&lt;br /&gt;arc&amp;gt; bar&lt;br /&gt;"toto"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lists are another story: when arc evaluates a list, it assumes the first item of the list is a function, and the remainder are arguments.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;arc&amp;gt; (+ 1 2)&lt;br /&gt;3&lt;br /&gt;arc&amp;gt; (expt 9 2)&lt;br /&gt;81&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first item is not necessarily a function: it might also be a reference to a macro, or in anarki, an object for whose type a function has been prepared via &lt;code&gt;defcall&lt;/code&gt;. For another day. The first place in a list is usually referred to as "functional position". So, the procedure for evaluating &lt;code&gt;(a b c d)&lt;/code&gt;, is to evaluate each of a, b, c, and d (order is unspecified). &lt;code&gt;a&lt;/code&gt; should evaluate to a function, which is then called with the values of b, c and d as arguments.&lt;br /&gt;&lt;br /&gt;But, the object in functional position doesn't have to be a symbol pointing to a function. It could also be an inline, anonymous function.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;arc&amp;gt; ((fn (a b) (+ a b)) 23 67)&lt;br /&gt;90&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Disadvantage: it's dead ugly, and totally unreadable. Nest a few of these and you have parenthesis soup. It turns out this is one of the fundamental organising principles of arc code. So why bother?&lt;ul&gt;&lt;br /&gt;&lt;li&gt;group expressions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;declare local variables&lt;/li&gt;&lt;br /&gt;&lt;li&gt;iteration&lt;/li&gt;&lt;br /&gt;&lt;li&gt;all sorts of wonderful things&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt; - all this in a neat and concise way, without namespace clutter or parameter hell. Except, we need macros to make it happen. &lt;br /&gt;&lt;br /&gt;Macros: a future post.&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-278863810432080767?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/278863810432080767/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=278863810432080767" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/278863810432080767?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/278863810432080767?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/05/arc-functions.html" title="arc functions" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DU4GQX89fyp7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-7708288071044242632</id><published>2008-05-22T14:35:00.000-07:00</published><updated>2009-05-20T12:32:00.167-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:32:00.167-07:00</app:edited><title>Lexical Scope and Closures</title><content type="html">&lt;p&gt;Lexical scope is not a radical departure from java: the concept already exists. When we create an inner instance class in java, the inner class has access to all the instance variables of all enclosing classes, and even to local variables if it's an anonymous inner class. Similarly, in arc, a locally-defined function has access to all the variables of all enclosing functions. This set of variables and their values is called the closure of the function.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="arc"&gt;&lt;div class="syntax"&gt;&lt;br /&gt; (def powerfn (y) &lt;b&gt;(fn (x) (expt x y))&lt;/b&gt;)&lt;br /&gt; &lt;br /&gt; (set square (powerfn 2)) ; --&gt; square is (fn (x) (expt x y)) with y = 2&lt;br /&gt; (set cube (powerfn 3)) ; --&gt; cube is (fn (x) (expt x y)) with y = 3&lt;br /&gt;&lt;br /&gt; (square 5) ; --&gt; 25&lt;br /&gt; (cube 5) ; --&gt; 125&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In this example, the variable y retains its value - 3 or 2 - long after &lt;tt&gt;powerfn&lt;/tt&gt; has exited, in the closure of the function returned by &lt;tt&gt;powerfn&lt;/tt&gt; (the function that is assigned to square and cube)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;When rainbow finds a locally-defined function in the course of evaluation, it creates a Closure object which encapsulates the function in question, and its closure. The Closure thus created can subsequently be stored in a variable, and invoked anywhere at any time. The implementation isn't optimal however: it keeps the &lt;i&gt;entire&lt;/i&gt; closure, rather than just the closed variables that are actually used by the function in question.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-7708288071044242632?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/7708288071044242632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=7708288071044242632" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/7708288071044242632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/7708288071044242632?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/05/lexical-scope-and-closures.html" title="Lexical Scope and Closures" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcASXY4eip7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-2280423414984957519</id><published>2008-05-15T14:34:00.000-07:00</published><updated>2009-05-20T12:34:08.832-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:34:08.832-07:00</app:edited><title>Tail-Call Optimisation</title><content type="html">&lt;p&gt;Tail-Call Optimisation lets you write&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void forever(long n) {&lt;br /&gt; System.out.println("looking for the last number: " + n)&lt;br /&gt; if (isTheLastNumber(n)) {&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt; forever(n + 1);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; - and never get a StackOverflowError. Yes. &lt;i&gt;Never&lt;/i&gt;. When a recursive call to &lt;tt&gt;forever&lt;/tt&gt; exits, there is nothing left for the parent invocation of &lt;tt&gt;forever&lt;/tt&gt; to do, so its stack frame can be discarded, and if it is, the stack simply doesn't grow.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here's an arc example:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(def a ()&lt;br /&gt; (b)&lt;br /&gt; (e))&lt;br /&gt;&lt;br /&gt;(def b ()&lt;br /&gt; (c)&lt;br /&gt; (d))&lt;br /&gt;&lt;br /&gt;(def e ()&lt;br /&gt; (f)&lt;br /&gt; (g))&lt;br /&gt;&lt;br /&gt;(def g ()&lt;br /&gt; (h)&lt;br /&gt; (i)&lt;br /&gt; (j))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Remeber, the return value of a function is the value of the last expression of the function. So the return value of (b) is (d).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;After the call from b to (c) returns, execution continues with the call from b to (d). However, when (d) returns, b has nothing more to do, so it can return directly to a.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, when we call c, we tell it to return to b at Instruction 2. However, when we call d, instead of telling it to return to b, we tell it to return to a. The stack frame representing b at this point is no longer referenced: the continuation for d is pointing back to a, bypassing b altogether.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ultimately, by the time we get to the call to j, we will tell j to return to whoever a's caller was, because neither a, nor e, nor g, make use of the value of (j). Presumably, a's caller does.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I hope this is making sense.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here is the implementation in rainbow. Inside the current continuation, the variable &lt;tt&gt;f&lt;/tt&gt; is the function we're evaluating, and &lt;tt&gt;f.nth(i)&lt;/tt&gt; gives us the nth expression of that function. To interpret the nth expression, rainbow does (approximately) this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   ArcObject expression = f.nth(index++);&lt;br /&gt;   Interpreter.interpret(&lt;b&gt;f.last(index) ? caller : this&lt;/b&gt;, expression);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So if I'm on the last expression, I tell the interpreter to return to my caller instead of to me once it's finished. Mission accomplished.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;See &lt;a href="http://en.wikipedia.org/wiki/Tail_recursion"&gt;wikipedia's tail-recursion&lt;/a&gt; article for more information. btw, rainbow doesn't do TCO modulo cons (see article). Arc on scheme, it seems, does. I will have to figure that out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-2280423414984957519?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/2280423414984957519/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=2280423414984957519" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/2280423414984957519?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/2280423414984957519?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/05/tail-call-optimisation.html" title="Tail-Call Optimisation" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkUESXgzeip7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-2584327507276071188</id><published>2008-05-08T13:45:00.000-07:00</published><updated>2009-05-20T12:36:48.682-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:36:48.682-07:00</app:edited><title>Continuations: Arc vs Java</title><content type="html">&lt;p&gt;What's a continuation? Despite much googling on the topic, continuations remained opaque to me until I stumbled upon Sam Ruby's amazingly excellent &lt;a href="http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons"&gt;Continuations for Curmudgeons&lt;/a&gt;. Please read that article instead of this, it will be much more useful.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here's a really fast description of continuations in java terms. Imagine in java we had first-class functions (like javascript). In other words, we could say&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Function p = myObject.toString // no parens!&lt;br /&gt;&lt;br /&gt;// later ...&lt;br /&gt;p(); // calls myObject.toString()&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now, let's jump a little further: imagine "return" is not just a keyword, but it is a special built-in function that is magically available in the body of every method, just like "this" and "super" are. And we have first-class functions. So, we can write&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;public String foo(int n) {&lt;br /&gt;  this.cc = return;&lt;br /&gt;  return("foo " + n); // "return" is a function&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public void bar() {&lt;br /&gt;  System.out.println("I have received " + foo(10));&lt;br /&gt;  System.out.println("end of bar");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;bar(); // displays "I have received foo 10", then "end of bar"&lt;br /&gt;cc("haha!") // displays "I have received haha!", then "end of bar", forever&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;With the call to &lt;code&gt;cc&lt;/code&gt; you are re-entering &lt;code&gt;bar&lt;/code&gt; at the instruction immediately after the call to &lt;code&gt;foo()&lt;/code&gt;, and not only that, when &lt;code&gt;bar&lt;/code&gt; returns, it will return to whoever its caller was when it was invoked the first time, and so on all the way up the stack. Not only that, the stack prior to the call to &lt;code&gt;cc&lt;/code&gt; is completely discarded and gc'd (unless, of course, there's a stored continuation somewhere pointing to that stack).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Being a java dude, this was a shocking revelation for me. Worse than &lt;code&gt;goto&lt;/code&gt;, a total abomination, a devilish contortion of everything that is right and proper in design.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;But I was undeterred. Sam Ruby's article gave me what I needed to implement continuations in rainbow, although it meant re-writing everything. Because java &lt;i&gt;doesn't&lt;/i&gt; allow me just store "return", I need to explicitly handle a stack in java code, so that I can "return" to it at any point, just in case someone decides to store it in a continuation. If the stack is stored in this way, it is not subject to garbage collection, so the entire stack - local variables, parameters, the stacktrace - is preserved.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So when rainbow invokes an arc function, it creates a new continuation for the invoked function, and passes the new continuation the &lt;i&gt;current&lt;/i&gt; continuation, so the new continuation knows where to return to when it's done.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This results in java code written in Continuation-Passing style, or CPS. CPS and continuations are separate concepts, but feel the same. Here is a quick CPS tutorial in Java. Normally we write this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt; int calculateSomething(int p, int q) {&lt;br /&gt;   return p * q;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; ...&lt;br /&gt;&lt;br /&gt; int x = calculateSomething(p, q);&lt;br /&gt; System.out.println("result is " + x);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Trivial, no? Here's the same thing in CPS:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt; void calculateSomething(int p, int q, Continuation c) {&lt;br /&gt;   c.receive(p * q);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; ... &lt;br /&gt; &lt;br /&gt; Continuation c = new Continuation() {&lt;br /&gt;  public void receive(Object o) {&lt;br /&gt;   System.out.println("result is " + o);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; calculateSomething(p, q, c);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The idea is that your methods must never return a value, they should instead pass the intended return value to a "Continuation" parameter destined to receive it. The responsibility of the Continuation object is to continue whatever was in progress. Here, the Continuation object calls &lt;tt&gt;System.out.println&lt;/tt&gt;, something that was achieved in the second line of the original version. So why would you want to write in CPS? In Java: you wouldn't, it's a nightmare, unless you happen to be writing a Lisp interpreter.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One difference between CPS and true continuations is that a true continuation never returns: the caller's stack is discarded, and the stack in scope for the called continuation is resurrected. CPS in java is a total hack. In the example above, any code following "c.receive(p * q)" is meaningless. The call to &lt;code&gt;receive&lt;/code&gt; must be the last statement executed in the method - it's replacing "return". Using CPS in java, it's easy either  to forget to invoke &lt;code&gt;receive&lt;/code&gt;, or to forget to return immediately afterwards.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A slight problem for rainbow is that CPS functions never return: the last instruction is a call to the previous continuation. So, normally, the java stack grows and grows. To avoid this, rainbow executes arc in a &lt;code&gt;while(true)&lt;/code&gt; loop. Each function invocation simply stores a reference to the function to invoke along with a reference to the caller and the lexical context - and then returns. The java stack unwinds, the loop loops, and the waiting function gets executed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-2584327507276071188?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/2584327507276071188/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=2584327507276071188" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/2584327507276071188?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/2584327507276071188?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/05/continuations-arc-vs-java.html" title="Continuations: Arc vs Java" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkUARHk-fSp7ImA9WxJRGEk.&quot;"><id>tag:blogger.com,1999:blog-7785050046571231972.post-6055079247529148849</id><published>2008-05-01T23:37:00.000-07:00</published><updated>2009-05-20T12:37:25.755-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T12:37:25.755-07:00</app:edited><title>Introducing Rainbow</title><content type="html">&lt;p&gt;Rainbow is an almost full implementation in java of Paul Graham's new lisp, &lt;a href="http://www.paulgraham.com/arc.html"&gt;arc&lt;/a&gt;. The arc compiler (ac.scm) is written in a little over 1000 lines of scheme - so I figured I could do it in a little over 10000 lines of java. In fact, I got in at about 5000.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Rainbow interprets its internal representation of arc code, and does not compile to bytecode. Hence it is not quite as fast as it might be. Rainbow sports continuations and tail-call-optimisation (which I believe &lt;a href="http://clojure.sourceforge.net/"&gt;Clojure&lt;/a&gt;, the alternative jvm lisp, lacks). These two features, being completely alien to the jvm, perhaps mean that compiling entirely to bytecode will remain out of reach for the moment.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Why java? It's a language I know reasonably well, having used it almost exclusively over the last ten years. Java gives us garbage collection and well-defined thread handling for free, as well as access to some great libraries. On the other hand, java is probably the most politically incorrect language for an arc interpreter: it might cause arc to &lt;a href="http://www.paulgraham.com/arcfaq.html"&gt;curl up like a bimetallic strip&lt;/a&gt;, a bit like writing a ruby compiler in cobol. What a concept. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Actually, here's the truth. In &lt;a href="http://www.paulgraham.com/arcll1.html"&gt;Arc at 3 weeks&lt;/a&gt; (2001), Paul Graham declares that arc is for good programmers, unlike java, which is for average programmers. I admit it, I am driven by pure hubris.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A goal of arc is to define as much as possible of the language in the language itself. So some keywords that we would expect to be a fundamental part of the language (for example, &lt;tt&gt;def&lt;/tt&gt; and &lt;tt&gt;mac&lt;/tt&gt;, for defining top-level functions and macros) are defined in arc, and not provided by the compiler at all. Rainbow respects this goal and replaces only the scheme compiler while leaving the rest of the language intact.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This blog will be the story of my travels in arc-land, of the challenges faced both in building rainbow and in using arc, from the perspective of someone who has been thinking in java for far too long now ...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here are the best places to go for more arc info:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://paulgraham.com/arc.html"&gt;Arc&lt;/a&gt; - the official site, plenty of background. Be sure to read the tutorial.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://arclanguage.org/forum"&gt;the arc forum&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://arcfn.com/"&gt;arcfn.com&lt;/a&gt; - solid and thorough documentation of the language by Ken Shirriff, along with his own experiences integrating arc and opengl&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://github.com/nex3/arc/tree/master"&gt;Anarki&lt;/a&gt;, the github "unofficial arc" repository, based on Paul Graham's release, with community-contributed features, fixes, and libraries.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://github.com/conanite/rainbow/tree/master"&gt;Rainbow&lt;/a&gt; is also on github&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;copyright 2008 conan dalton, feel free to quote, please link&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7785050046571231972-6055079247529148849?l=www.fnargs.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.fnargs.com/feeds/6055079247529148849/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7785050046571231972&amp;postID=6055079247529148849" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/6055079247529148849?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7785050046571231972/posts/default/6055079247529148849?v=2" /><link rel="alternate" type="text/html" href="http://www.fnargs.com/2008/05/introducing-rainbow.html" title="Introducing Rainbow" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="31" height="32" src="http://bp3.blogger.com/_7sjE3SRdZhk/SBJKCJJHRHI/AAAAAAAAACI/h52v1YtGCWQ/S220/approved.jpg" /></author><thr:total>0</thr:total></entry></feed>

