<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-11696659</id><updated>2011-11-06T17:33:17.367-08:00</updated><category term='stopcopy autobuild'/><title type='text'>pnkfif</title><subtitle type='html'>the informal ramblings of a formal language researcher</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-11696659.post-5767956280245662689</id><published>2011-11-06T17:33:00.000-08:00</published><updated>2011-11-06T17:33:17.590-08:00</updated><title type='text'>Middle Squares and Big Nums</title><content type='html'>No screen shots tonight.  But on the semi-bright side, at least this time I am posting something that has to do with TAOCP.&lt;p/&gt;For my second quick experiment to play with the Flash tools, I decided to make a swf that would illustrate the "middle-square" method for &lt;em&gt;pseudo-random&lt;/em&gt; sequences of numbers (aka a pseudo-random number generator, or PRNG).&lt;p/&gt;The technique is simple, and aptly named at least if you are used to reading your function compositions as (&lt;em&gt;f&lt;/em&gt;&amp;nbsp;○&amp;nbsp;&lt;em&gt;g&lt;/em&gt;) rather than as the categorical style of (&lt;em&gt;g&lt;/em&gt;&amp;nbsp;;&amp;nbsp;&lt;em&gt;f&lt;/em&gt;).  Every time you want a new "random" number of let's say 10 digits, you take the previous number &lt;em&gt;N&lt;/em&gt; (or the initial seed if you're just starting out), square it (which will yield of number of at most 20 digits, and in fact we'll pad &lt;em&gt;N&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; out with zeroes so that it is always 20 digits), and then extract the middle 10 digits from that 20 digit &lt;em&gt;N&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt;.&lt;p/&gt;It shouldn't take very much code to implement something like this.  Except (a ha), a lot of "modern" languages like ActionScript do not have built-in support for arbitrary precision arithmetic.  In the particular case of the ECMAscript family, as soon as you get above a certain threshold (usually around 2&lt;sup&gt;30&lt;/sup&gt; or so, they fall into floating-point mode.  That might suffice for a lot of the scripts out there, but it falls down miserably in this case because the majority of the ten digit numbers are obviously larger than 5⋅10&lt;sup&gt;9&lt;/sup&gt; = 5,000,000,000 which is itself larger than 4,294,967,296 = 2&lt;sup&gt;32&lt;/sup&gt;.&lt;p/&gt;So as soon as you want to actually show off Knuth's first example: 5,772,156,649, you discover that you can't use the language's built-in arithmetic to do it.&lt;p/&gt;(And for those of you saying "but it is safe to use floating point to store those ten digit numbers; you get 53 bits of precision in the significand in IEEE 754 floating point": I recommend you go back up and re-read the very first step (or second-word in our ○-composed name).  And/or double-check what 2&lt;sup&gt;53&lt;/sup&gt; is in base-10.&lt;p/&gt;Anyway, that was just a long explanation for why I had to make a quick &lt;code&gt;BigNum&lt;/code&gt; class in order to do this task.  I wasn't expecting to have to get into &lt;code&gt;BigNum&lt;/code&gt; work until I hit Chapter 4 of TAOCP, and I plan to keep the class as minimal as possible (in both performance and features) until I get there.&lt;p/&gt;(I used Emacs &lt;code&gt;htmlize.el&lt;/code&gt; to format this code.  If I knew how to integrate the CSS it generates into blogspot, I'd have font colors too.  But that will have to be a project for another day.)&lt;h3&gt;&lt;code&gt;BigNum.as&lt;/code&gt; code&lt;/h3&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;package&lt;/span&gt;  {&lt;br /&gt;    &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;class&lt;/span&gt; BigNum {&lt;br /&gt;        internal &lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="keyword"&gt;const&lt;/span&gt; &lt;span class="variable-name"&gt;bigitLen&lt;/span&gt; = 16;&lt;br /&gt;        internal &lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="keyword"&gt;const&lt;/span&gt; &lt;span class="variable-name"&gt;base&lt;/span&gt; = 10; &lt;span class="comment"&gt;// Math.pow(2, bigitLen);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// a base of 10 is *incredibly* inefficient, but it does allow&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// for a very simple toString implementation (and parse as well&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// but lets only put that in if I need to debug)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; toString():String {&lt;br /&gt;            &lt;span class="comment"&gt;// This code *definitely* only works for base == 10&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="keyword"&gt;if&lt;/span&gt; (base == 10) {&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;;&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;r&lt;/span&gt; = &lt;span class="string"&gt;""&lt;/span&gt;;&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;maxNonZeroIdx&lt;/span&gt; = 0;&lt;br /&gt;                &lt;span class="keyword"&gt;for&lt;/span&gt; (i=0; i &amp;lt; bigits.length; i++) {&lt;br /&gt;                    &lt;span class="keyword"&gt;if&lt;/span&gt; (bigits[i] &amp;gt; 0) {&lt;br /&gt;                        maxNonZeroIdx = i;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="keyword"&gt;for&lt;/span&gt; (i=0; i &amp;lt;= maxNonZeroIdx; i++) {&lt;br /&gt;                    r = bigits[i] + r;&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="keyword"&gt;return&lt;/span&gt; r;&lt;br /&gt;            } &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;                &lt;span class="keyword"&gt;throw&lt;/span&gt; &lt;span class="string"&gt;"unimplemented"&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// AF(this) = (nonNeg?1:-1) * Sum_i{ bigits[i] * base^i }&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;var&lt;/span&gt; nonNeg:&lt;span class="variable-name"&gt;Boolean&lt;/span&gt;;&lt;br /&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;var&lt;/span&gt; bigits:Vector.&amp;lt;uint&amp;gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; BigNum(&lt;span class="variable-name"&gt;num&lt;/span&gt;:*=&lt;span class="variable-name"&gt;0&lt;/span&gt;) {&lt;br /&gt;            nonNeg = &lt;span class="constant"&gt;true&lt;/span&gt;;&lt;br /&gt;            bigits = &lt;span class="keyword"&gt;new&lt;/span&gt; Vector.&amp;lt;uint&amp;gt;(1);&lt;br /&gt;            &lt;span class="keyword"&gt;if&lt;/span&gt; (num is uint &amp;amp;&amp;amp; num &amp;lt; base) {&lt;br /&gt;                bigits[0] = num;&lt;br /&gt;            } &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;                &lt;span class="keyword"&gt;this&lt;/span&gt;.parse(String(num));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// modifies: this&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// effect: sets up this to match input (base 10).&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; parse(&lt;span class="variable-name"&gt;input&lt;/span&gt;:&lt;span class="variable-name"&gt;String&lt;/span&gt;):&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="constant"&gt;false&lt;/span&gt; &amp;amp;&amp;amp; base == 10) {&lt;br /&gt;                parse_base10(input);&lt;br /&gt;            } &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;                parse_general(input);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// modifies: this&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// effect: same as parse(input)&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; parse_base10(&lt;span class="variable-name"&gt;input&lt;/span&gt;:&lt;span class="variable-name"&gt;String&lt;/span&gt;):&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="comment"&gt;// This code *definitely* only works for base == 10&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;            bigits.length = input.length;&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i &amp;lt; input.length; i++) {&lt;br /&gt;                bigits[input.length - i - 1] = uint(input.charAt(i));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// modifies: this&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// effect: same as parse(input)&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; parse_general(&lt;span class="variable-name"&gt;input&lt;/span&gt;:&lt;span class="variable-name"&gt;String&lt;/span&gt;):&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="comment"&gt;// This code probably works for bases other than 10&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i &amp;lt; input.length; i++) {&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;amount&lt;/span&gt; = uint(input.charAt(i));&lt;br /&gt;                &lt;span class="keyword"&gt;this&lt;/span&gt;.mulAndAddInPlace(10, amount);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// modifies: this&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// effect: this := this*'scalar' + 'carry'&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; mulAndAddInPlace(&lt;span class="variable-name"&gt;scalar&lt;/span&gt;:&lt;span class="type"&gt;int&lt;/span&gt;, &lt;span class="variable-name"&gt;carry&lt;/span&gt;:&lt;span class="type"&gt;int&lt;/span&gt;):&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i &amp;lt; bigits.length; i++) {&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;a&lt;/span&gt; = bigits[i];&lt;br /&gt;                a *= scalar;&lt;br /&gt;                a += carry;&lt;br /&gt;                bigits[i] = a % base;&lt;br /&gt;                carry = (a - (a % base)) / base;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="keyword"&gt;if&lt;/span&gt; (carry &amp;gt; 0) {&lt;br /&gt;                bigits[bigits.length] = carry;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// modifies: this&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;// effect: this := this * 'base'&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; leftShiftInPlace(&lt;span class="variable-name"&gt;amt&lt;/span&gt;:&lt;span class="variable-name"&gt;uint&lt;/span&gt;):&lt;span class="keyword"&gt;void&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i&amp;lt;amt; i++) {&lt;br /&gt;                bigits.unshift(0);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; bigit(&lt;span class="variable-name"&gt;idx&lt;/span&gt;:&lt;span class="variable-name"&gt;uint&lt;/span&gt;):uint&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="keyword"&gt;return&lt;/span&gt; (idx &amp;lt; bigits.length) ? bigits[idx] : 0;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; add(&lt;span class="variable-name"&gt;that&lt;/span&gt;:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt;):BigNum {&lt;br /&gt;            &lt;span class="comment"&gt;// This code may or may not work for bases other than 10&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; r:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum;&lt;br /&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;len&lt;/span&gt; = Math.max(&lt;span class="keyword"&gt;this&lt;/span&gt;.bigits.length, that.bigits.length);&lt;br /&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;carry&lt;/span&gt; = 0;&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i&amp;lt;len; i++) {&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;b&lt;/span&gt; = &lt;span class="keyword"&gt;this&lt;/span&gt;.bigit(i) + that.bigit(i) + carry;&lt;br /&gt;                r.bigits[i] = b % base;&lt;br /&gt;                carry = (b - (b % base)) / base;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="keyword"&gt;if&lt;/span&gt; (carry &amp;gt; 0) {&lt;br /&gt;                r.bigits[len] = carry;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="keyword"&gt;return&lt;/span&gt; r;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;private&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; clone():BigNum&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="keyword"&gt;this&lt;/span&gt;.add(&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;function&lt;/span&gt; mul(&lt;span class="variable-name"&gt;that&lt;/span&gt;:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt;):BigNum {&lt;br /&gt;            &lt;span class="comment"&gt;// This code may or may not work for bases other than 10&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="comment"&gt;// for now, multiply the same way you'd do it by hand:&lt;br /&gt;&lt;/span&gt;            &lt;span class="comment"&gt;// by repeated multiply-by-scalar, shift, and sum.&lt;br /&gt;&lt;/span&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; accum:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum;&lt;br /&gt;            &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i&amp;lt;that.bigits.length; i++) {&lt;br /&gt;                &lt;span class="keyword"&gt;var&lt;/span&gt; scaled:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt; = &lt;span class="keyword"&gt;this&lt;/span&gt;.clone();&lt;br /&gt;                scaled.mulAndAddInPlace(that.bigits[i], 0);&lt;br /&gt;                scaled.leftShiftInPlace(i);&lt;br /&gt;                accum = accum.add(scaled);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="keyword"&gt;return&lt;/span&gt; accum;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;Anyway, after the &lt;code&gt;BigNum&lt;/code&gt; class done, I whipped up a Flash program that let me interactively input new seeds for such sequences.  The first version was somewhat embarrassing, because I insisted on doing everything within the Actions block for the single frame of the SWF movie, rather than using any of the Flash Pro GUI to drag around UI elements.&lt;p/&gt;But at least I had the good sense to factor out the middle square generation code.  And then after I had that working acceptably, I was able to go back and experiment with using the Flash Pro GUI to use the built-in UI components more effectively (e.g. so that I could create a scrollable list for the output sequence rather than a non-scrollable label, and so that I could control the number of elements created in the sequence).&lt;p/&gt;It is still not perfect; e.g. it would be better if the sequence were created on the fly in response to the user scrolling down the list.  Then there would be no need to impose an &lt;em&gt;a priori&lt;/em&gt; limit on the sequence length.  But that would require a little bit more revision to the design than I want to undertake at the moment.&lt;p/&gt;Anyway, here are the two versions, presented in three parts: first the middle square generation routine on its own, then the first ugly UI code, and then the better code that presumes that one has used Flash Pro to set up UI components in a sane manner.&lt;p/&gt;&lt;h3&gt;Middle Square Generation&lt;/h3&gt;    &lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function-name"&gt;middleSquareSequence&lt;/span&gt;(&lt;span class="variable-name"&gt;input&lt;/span&gt;:&lt;span class="variable-name"&gt;String&lt;/span&gt;, &lt;span class="variable-name"&gt;iters&lt;/span&gt;:&lt;span class="variable-name"&gt;uint&lt;/span&gt;):Vector.&amp;lt;String&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span class="keyword"&gt;var&lt;/span&gt; r:Vector.&amp;lt;String&amp;gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; Vector.&amp;lt;String&amp;gt;();&lt;br /&gt;    &lt;span class="keyword"&gt;if&lt;/span&gt; (isNaN(Number(input))) {&lt;br /&gt;        r.push(input);&lt;br /&gt;    } &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;        &lt;span class="comment"&gt;// Illustrate middle-square method for (bad) PRNG&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;var&lt;/span&gt; digits:&lt;span class="variable-name"&gt;uint&lt;/span&gt; = input.length;&lt;br /&gt;&lt;br /&gt;        &lt;span class="comment"&gt;// Make digit count even, to simplify definitionn of "middle digits"&lt;br /&gt;&lt;/span&gt;        &lt;span class="keyword"&gt;if&lt;/span&gt; ((digits % 2) == 1)&lt;br /&gt;            digits = digits + 1;&lt;br /&gt;        &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;dig2&lt;/span&gt; = uint(digits/2);&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;var&lt;/span&gt; bn:&lt;span class="variable-name"&gt;BigNum&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(input);&lt;br /&gt;        &lt;span class="keyword"&gt;var&lt;/span&gt; s:&lt;span class="variable-name"&gt;String&lt;/span&gt; = bn.toString();&lt;br /&gt;        &lt;span class="keyword"&gt;while&lt;/span&gt; (s.length &amp;lt; digits) {&lt;br /&gt;            s = &lt;span class="string"&gt;"0"&lt;/span&gt; + s;&lt;br /&gt;        }&lt;br /&gt;        r.push(s);&lt;br /&gt;&lt;br /&gt;        &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i &amp;lt; iters; i++) {&lt;br /&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;nsqr&lt;/span&gt; = bn.mul(bn); &lt;span class="comment"&gt;// this is &amp;lt;= 2*digits;&lt;br /&gt;&lt;/span&gt;            &lt;span class="comment"&gt;// want the middle digits.&lt;br /&gt;&lt;/span&gt;            &lt;span class="comment"&gt;// Ideally I'd do this via arithmetic, but I don't feel like&lt;br /&gt;&lt;/span&gt;            &lt;span class="comment"&gt;// adding support for such to my hacked up BigNum class at the&lt;br /&gt;&lt;/span&gt;            &lt;span class="comment"&gt;// moment.&lt;br /&gt;&lt;/span&gt;            s = nsqr.toString();&lt;br /&gt;            &lt;span class="keyword"&gt;while&lt;/span&gt; (s.length &amp;lt; 2*digits) {&lt;br /&gt;                s = &lt;span class="string"&gt;"0"&lt;/span&gt;+s;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="keyword"&gt;var&lt;/span&gt; sub:&lt;span class="variable-name"&gt;String&lt;/span&gt; = s.substring(dig2,2*digits-dig2);&lt;br /&gt;            r.push(sub);&lt;br /&gt;            bn = &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(sub);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="keyword"&gt;return&lt;/span&gt; r;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;&lt;h3&gt;Ugly Hacked Up UI Code&lt;/h3&gt;    &lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.Button;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.TextInput;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.List;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.Label;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; flash.events.MouseEvent;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.NumericStepper;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;// ***************************************************************************&lt;br /&gt;// Old hand written code below that did everything without using Flash Pro GUI&lt;br /&gt;// (except for importing components into the SWF).  I.E., this code manually&lt;br /&gt;// creates and positions the UI elements.  Its not really worth the pain for&lt;br /&gt;// one-off scripts like this, especially now that I know how to get&lt;br /&gt;// code-hinting for UI componets by explicitly redeclaring the variables.&lt;br /&gt;// ***************************************************************************&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="constant"&gt;true&lt;/span&gt;) {&lt;br /&gt;    &lt;span class="keyword"&gt;var&lt;/span&gt; b:&lt;span class="variable-name"&gt;Button&lt;/span&gt;;&lt;br /&gt;    b = &lt;span class="keyword"&gt;new&lt;/span&gt; Button;&lt;br /&gt;&lt;br /&gt;    &lt;span class="comment"&gt;// Mutating b/textField doesn't seem to have&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// desirable effects.  The documentation just&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// says its a reference to the Button's internal&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// textfield, which makes me think that this never&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// should have been provided as a mutable property.&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// b.textField = t;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;    b.label = &lt;span class="string"&gt;"Click"&lt;/span&gt;&lt;br /&gt;    &lt;span class="comment"&gt;// b.setStyle("textFormat", tf);&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// b.width = 400;&lt;br /&gt;&lt;/span&gt;    &lt;span class="comment"&gt;// b.height = 300;&lt;br /&gt;&lt;/span&gt;    b.x = 120;&lt;br /&gt;    b.y = 10;&lt;br /&gt;    addChild(b);&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;var&lt;/span&gt; inp:&lt;span class="variable-name"&gt;TextInput&lt;/span&gt;;&lt;br /&gt;    inp = &lt;span class="keyword"&gt;new&lt;/span&gt; TextInput;&lt;br /&gt;    inp.x = 120;&lt;br /&gt;    inp.y = 40;&lt;br /&gt;    inp.text = &lt;span class="string"&gt;"5772156649"&lt;/span&gt;;&lt;br /&gt;    addChild(inp);&lt;br /&gt;&lt;br /&gt;    b.addEventListener(MouseEvent.CLICK,&lt;br /&gt;                       &lt;span class="keyword"&gt;function&lt;/span&gt;() {&lt;br /&gt;                           &lt;span class="keyword"&gt;var&lt;/span&gt; seq:Vector.&amp;lt;String&amp;gt;;&lt;br /&gt;                           seq = middleSquareSequence(inp.text, 400);&lt;br /&gt;                           l.text = &lt;span class="string"&gt;""&lt;/span&gt;;&lt;br /&gt;                           &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i&amp;lt;seq.length; i++) {&lt;br /&gt;                               l.text += seq[i] + &lt;span class="string"&gt;"\n"&lt;/span&gt;;&lt;br /&gt;                           }&lt;br /&gt;                       });&lt;br /&gt;&lt;br /&gt;    &lt;span class="keyword"&gt;var&lt;/span&gt; l:&lt;span class="variable-name"&gt;Label&lt;/span&gt;;&lt;br /&gt;    l = &lt;span class="keyword"&gt;new&lt;/span&gt; Label;&lt;br /&gt;    l.x = 220;&lt;br /&gt;    l.y = 10;&lt;br /&gt;    l.height = 400;&lt;br /&gt;    &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="constant"&gt;true&lt;/span&gt;) {&lt;br /&gt;        l.text = &lt;span class="string"&gt;"Hi\nworld"&lt;/span&gt;;&lt;br /&gt;    } &lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="constant"&gt;false&lt;/span&gt;) {&lt;br /&gt;        &lt;span class="comment"&gt;// (These are some tests of BigNum functionality&lt;br /&gt;&lt;/span&gt;        &lt;span class="comment"&gt;//  I put in as I was getting this going.)&lt;br /&gt;&lt;/span&gt;        l.text = (&lt;span class="string"&gt;""&lt;/span&gt;+&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1234567890"&lt;/span&gt;)&lt;br /&gt;                  +&lt;span class="string"&gt;"\n"&lt;/span&gt; + &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1234"&lt;/span&gt;).add(&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1234"&lt;/span&gt;))&lt;br /&gt;                  +&lt;span class="string"&gt;"\n"&lt;/span&gt; + &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1234"&lt;/span&gt;).add(&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1766"&lt;/span&gt;))&lt;br /&gt;                  +&lt;span class="string"&gt;"\n"&lt;/span&gt; + &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"9999"&lt;/span&gt;).add(&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1001"&lt;/span&gt;))&lt;br /&gt;                  +&lt;span class="string"&gt;"\n"&lt;/span&gt; + &lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1000"&lt;/span&gt;).mul(&lt;span class="keyword"&gt;new&lt;/span&gt; BigNum(&lt;span class="string"&gt;"1000"&lt;/span&gt;))&lt;br /&gt;                 );&lt;br /&gt;    }&lt;br /&gt;    l.selectable = &lt;span class="constant"&gt;true&lt;/span&gt;;&lt;br /&gt;    addChild(l);&lt;br /&gt;}&lt;/pre&gt;&lt;p/&gt;&lt;object width="100%" height="500"&gt;    &lt;param name="movie" value="file.swf"&gt;    &lt;embed src="http://pnkfx.org/~pnkfelix/swf/2011-11-06/Chap3_1_MiddleSquare_Ugly.swf" width="100%" height="500"&gt;    &lt;/embed&gt;&lt;/object&gt;&lt;h3&gt;Nicer looking (and shorter) UI code presuming Flash Pro&lt;/h3&gt;    &lt;pre&gt;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.Button;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.TextInput;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.List;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.Label;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; flash.events.MouseEvent;&lt;br /&gt;&lt;span class="keyword"&gt;import&lt;/span&gt; fl.controls.NumericStepper;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;// These are local variable declarations for the UI elements that I added&lt;br /&gt;// manually in Flash Pro.  Apparently the tool is too stupid to know to provide&lt;br /&gt;// code hinting unless I add these declarations (along with the above imports)&lt;br /&gt;// myself.  (Or maybe this is a "feature" rather than a "bug")&lt;br /&gt;&lt;/span&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; reseedButton:&lt;span class="variable-name"&gt;Button&lt;/span&gt;;&lt;br /&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; seedInput:&lt;span class="variable-name"&gt;TextInput&lt;/span&gt;;&lt;br /&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; outputList:&lt;span class="variable-name"&gt;List&lt;/span&gt;;&lt;br /&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; numItersStepper:&lt;span class="variable-name"&gt;NumericStepper&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;reseedButton.addEventListener(MouseEvent.CLICK,&lt;br /&gt;  &lt;span class="keyword"&gt;function&lt;/span&gt; () {&lt;br /&gt;      outputList.removeAll();&lt;br /&gt;      &lt;span class="keyword"&gt;var&lt;/span&gt; seq : Vector.&amp;lt;String&amp;gt;;&lt;br /&gt;      seq = middleSquareSequence(seedInput.text, numItersStepper.value);&lt;br /&gt;      &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;seen&lt;/span&gt; = {};&lt;br /&gt;      &lt;span class="keyword"&gt;var&lt;/span&gt; seenRepeat:&lt;span class="variable-name"&gt;Boolean&lt;/span&gt; = &lt;span class="constant"&gt;false&lt;/span&gt;;&lt;br /&gt;      &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;i&lt;/span&gt;=0; i&amp;lt;seq.length; i++) {&lt;br /&gt;          &lt;span class="keyword"&gt;if&lt;/span&gt; (seenRepeat || seq[i] &lt;span class="keyword"&gt;in&lt;/span&gt; seen) {&lt;br /&gt;              seenRepeat = &lt;span class="constant"&gt;true&lt;/span&gt;;&lt;br /&gt;              outputList.addItem({label:(seq[i]+&lt;br /&gt;                                         &lt;span class="string"&gt;" (repeat)"&lt;/span&gt;)});&lt;br /&gt;          } &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;              outputList.addItem({label:seq[i]});&lt;br /&gt;              seen[seq[i]] = &lt;span class="constant"&gt;true&lt;/span&gt;;&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  });&lt;br /&gt;&lt;/pre&gt;&lt;object width="100%" height="500"&gt;    &lt;param name="movie" value="file.swf"&gt;    &lt;embed src="http://pnkfx.org/~pnkfelix/swf/2011-11-06/Chap3_1_MiddleSquare.swf" width="100%" height="500"&gt;    &lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-5767956280245662689?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/5767956280245662689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=5767956280245662689' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/5767956280245662689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/5767956280245662689'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2011/11/middle-squares-and-big-nums.html' title='Middle Squares and Big Nums'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-7966508929813002004</id><published>2011-11-05T13:31:00.000-07:00</published><updated>2011-11-05T13:44:51.048-07:00</updated><title type='text'>A Bit of Trignometry</title><content type='html'>So I wanted to aim small for my initial foray into using Flash Professional to make a small bit of example code for this blog.&lt;p/&gt;(I have done some small proof of concept stuff in Flash Pro and in Flash Builder before, mainly to explore the runtime garbage collector or illustrate short-comings in our ActionScript API's.  But none of that has translated over to blog content here before.)&lt;p/&gt;I figure that in general I'll need to be able to render animated text&amp;nbsp;and shapes.  Other functionality (mouse event handling, UI elements like buttons or text boxes) can wait for later.&lt;p/&gt;So okay, how about "Hello World," where the text does something interesting.  Like rotate 360 degrees in a tight circle around its mid-point; that's the kind of thing that is really easy to show off in &lt;a href="http://drracket.org/"&gt;DrRacket&lt;/a&gt;.&lt;p/&gt;It was easy to get started: a few mouse clicks to select the text tool, create a "Hello World" text object, and make it rotate continuously.&lt;ol&gt;&lt;li&gt;Choose the menu item "File → New..." and choose "ActionScript 3.0" in the New Document dialog window.&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_01_NewDoc.png"/&gt;&lt;/li&gt;&lt;li&gt;Now that you have a fresh blank slate to work with, select the Text tool in the toolbar on the right hand side of the screen:&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_02_SelectTextTool.png"/&gt;&lt;/li&gt;&lt;li&gt;Create a fresh text object by clicking the Text tool on the white space (the "stage") on the left hand side of the screen:&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_03_CreateEmptyTextObject.png"/&gt;&lt;/li&gt;&lt;li&gt;Create a fresh text object by clicking the Text tool on the white space (the "stage") on the left hand side of the screen:&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_04_TypeHWInTextObject.png"/&gt;&lt;/li&gt;&lt;li&gt;If you like, you can automatically align the text to sit in the center of the stage, in four clicks: the first to open up the alignment controls, by clicking the "Align" button in the menu bar at the center of the screen, the second to turn on the "Align to stage" option in the alignment controls, and the third and fourth to turn on the "Align vertical center" and "Align horizontal center" options.  The latter three steps are illustrated below:&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_05_AlignToStage.png"/&gt;&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_06_AlignVert.png"/&gt;&lt;br/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_07_AlignHorz.png"/&gt;&lt;/li&gt;&lt;li&gt;Finally, to make the selected text actually act in a dynamic fashion, double-click one of the premade ActionScript snippets, found in the "Code Snippets" that you can select from that middle menu bar again. For this experiment, I selected the "Rotate Continously" code snippet:&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_08_ActionRotate.png"/&gt;&lt;/li&gt;&lt;li&gt;You will probably get a pop-up dialog box saying that this code snippet requires an instance name; just click okay and Flash Pro makes up a name for the text object.  And voila:&lt;img src="http://pnkfx.org/~pnkfelix/screens/2011-11-05/FlashPro_09_SemiFinal.png"/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p/&gt;Except when I tested this (menu item "Control→Test Movie→Test"), I did not get what I expected:&lt;br/&gt;&lt;embed type="application/x-shockwave-flash" src="http://pnkfx.org/~pnkfelix/swf/2011-11-05/Hello_OffCenter.swf" pluginspage=" http://www.macromedia.com/go/getflashplayer" height="400" width="400"&gt;&lt;/embed&gt;&lt;p/&gt;Yes, this text is rotating in a circle... but not around a point in the middle of the text.&lt;p/&gt;The reason is simple: the text object's position is determined relative to the (x,y) coordinate at the upper-left hand corner of the text.  When you rotate the text, it rotates around that origin at its upper-left corner, so that corner is what it rotates around.&lt;p/&gt;This discovery turned a somewhat silly test of Flash into a slightly more meaty (though mechanical) puzzle: how do I get the effect I wanted originally.&lt;p/&gt;The answer: Trigonometry!  As the rectangle rotates, we also adjust the position of its upper-left corner, moving it in a circle in synchronization with the rotation of the rectange.&lt;p/&gt;&lt;img src="http://pnkfx.org/~pnkfelix/diagrams/2011-11-05/RotationDerivation.png"/&gt;&lt;br/&gt;(The above picture has flaws; in particular, the line segment &lt;em&gt;r&lt;/em&gt; is supposed to end at the center point of the rectangle, but it clearly does not, since the horizontal line going through it is vertically above both the lower-left and the upper-right corners.  This should not be possible if that line were truly going through the center of the rectangle.  In my defense, this was my first foray into using Adobe Illustrator.  I will probably try again later using &lt;a href="http://www.texample.net/tikz/examples/"&gt;TikZ/PGF&lt;/a&gt;.)&lt;p/&gt;This derivation leads to the following change to the ActionScript code that Flash Pro inserted for us:&lt;p/&gt;&lt;pre&gt;&lt;br /&gt;textField_1.addEventListener(Event.ENTER_FRAME, fl_RotateContinuously);&lt;br /&gt;&lt;br /&gt;var w = this.width;&lt;br /&gt;var h = this.height;&lt;br /&gt;var r = Math.sqrt(w*w/4+h*h/4);&lt;br /&gt;var theta = Math.asin(h/(2*r));&lt;br /&gt;var origin = {x:stage.width/2, y:stage.height/2};&lt;br /&gt;&lt;br /&gt;function fl_RotateContinuously(event:Event)&lt;br /&gt;{&lt;br /&gt;   alpha += 0.1;&lt;br /&gt;   var psi = alpha + theta;&lt;br /&gt;   var dx = r * Math.cos(psi);&lt;br /&gt;   var dy = r * Math.sin(psi);&lt;br /&gt;   // trace(w,h,dx,dy);&lt;br /&gt;   textField_1.x = origin.x - dx;&lt;br /&gt;   textField_1.y = origin.y - dy;&lt;br /&gt;   textField_1.rotation = 360*alpha/(2*Math.PI);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p/&gt;And, voila, for real this time:&lt;br/&gt;&lt;embed type="application/x-shockwave-flash" src="http://pnkfx.org/~pnkfelix/swf/2011-11-05/Hello.swf" pluginspage=" http://www.macromedia.com/go/getflashplayer" height="400" width="400"&gt;&lt;/embed&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-7966508929813002004?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/7966508929813002004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=7966508929813002004' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/7966508929813002004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/7966508929813002004'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2011/11/bit-of-trignometry.html' title='A Bit of Trignometry'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-7671221928121067407</id><published>2011-10-29T11:27:00.001-07:00</published><updated>2011-10-29T11:27:03.960-07:00</updated><title type='text'>Bonjour de Paris</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;I have arrived in Paris!  It is great.  Stephanie has been posting pictures on &lt;a href='http://unjourdansnotrevie.wordpress.com/'&gt;her blog&lt;/a&gt;.	&lt;/p&gt;&lt;p&gt; I had to leave the majority of my library at home, but I did take a special set of textbooks with me: my old editions of TAOCP, all three volumes.  I am hoping to work through volumes 2 and 3, and post the results of my experimental implementations here, the same way I posted the code for algorithm &lt;span style='color: rgb(0, 0, 0); font-family: Georgia, serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); display: inline !important; float: none; ' class='Apple-style-span'&gt;7.2.1.1-W&lt;/span&gt; earlier.  I have many more languages available at my fingertips now: in addition to the old-standbys, Java, C, and Scheme, I now also have ActionScript, Javascript, and C++.  Imight also dabble in a bit of assembly code in x86_64 or ARM from time to time.&lt;/p&gt;&lt;p&gt;At the same time, I am experimenting with alternative tools for authoring blog content.  I'm trying to be a good little Adobe employee and try to use our own tools (Dreamweaver in this case) to interface with Blogger. My end goal is to post active Javascript and Flash content on the web, in addtion to the transcripts I post.  But that might require I shift over to my personal web server, rather than work through Blogger.  We shall see.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-7671221928121067407?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/7671221928121067407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=7671221928121067407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/7671221928121067407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/7671221928121067407'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2011/10/bonjour-de-paris.html' title='Bonjour de Paris'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-5697851162883685703</id><published>2009-08-27T18:37:00.000-07:00</published><updated>2009-08-27T19:29:13.480-07:00</updated><title type='text'>from 90sec to 9sec.</title><content type='html'>I have been reading Knuth's pre-fascicles from Chapter 7 of TAOCP.&lt;br /&gt;&lt;br /&gt;Last night when I transcribed one of the algorithms (7.2.1.1-W) to Scheme code, I got caught up in Knuth's claim that the iterative process described should take "at most a few seconds", yet my first version was taking 90 seconds to run in Larceny.  So I started the human iterative process of revising the code, inspecting the compiler output, and doing more runs to figure out where the time was going.&lt;br /&gt;&lt;br /&gt;At the end of it, I got the running time down to 9 seconds (from 90; that's a 10x speed-up!)  You can shave off a few more seconds by switching to unsafe mode via compiler switches, but it seems like the really important thing was understanding which operations were going to turn into native machine instructions, which ones would turn into millicode invocations in the C runtime, and which ones would turn into Scheme procedure invocations.&lt;br /&gt;&lt;br /&gt;(I think 9 qualifies as "a few seconds", especially for a dynamic language like Scheme.)&lt;br /&gt;&lt;br /&gt;So here, for your viewing pleasure, is both the first and last versions of the code, along with the log in the comments of the changes I made and what effect they seemed to have.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;;; ----------------------------------------------------------------------&lt;br /&gt;;; What is largest set of five letter words connected via single letter &lt;br /&gt;;; swaps?  To find out, we use specialized representation of sgb-words,&lt;br /&gt;;; where each word is mapped to an index in a bit-table with 2^25 entries&lt;br /&gt;;; (I would represent each bit by a byte for ease of coding, but Larceny&lt;br /&gt;;;  cannot construct objects &gt;= 16 MB, so my hand is forced.)&lt;br /&gt;&lt;br /&gt;(define bytevector-bit-ref &lt;br /&gt;  (lambda (bv k)&lt;br /&gt;    (let ((q (quotient k 8))&lt;br /&gt;          (r (remainder k 8)))&lt;br /&gt;      (fxarithmetic-shift-right&lt;br /&gt;       (fxand (bytevector-u8-ref bv q)&lt;br /&gt;              (fxarithmetic-shift-left 1 r)) r))))&lt;br /&gt;&lt;br /&gt;(define bytevector-bit-ref? &lt;br /&gt;  (lambda (bv k)&lt;br /&gt;    (not (zero? (bytevector-bit-ref bv k)))))&lt;br /&gt;&lt;br /&gt;(define bytevector-bit-set! &lt;br /&gt;  (lambda (bv k bit)&lt;br /&gt;    (let ((q (quotient k 8))&lt;br /&gt;          (r (remainder k 8)))&lt;br /&gt;      (bytevector-u8-set! &lt;br /&gt;       bv q &lt;br /&gt;       (fxior (fxand (bytevector-u8-ref bv q)&lt;br /&gt;                     (fxxor #b11111111 (fxarithmetic-shift-left 1 r)))&lt;br /&gt;              (fxarithmetic-shift-left bit r))))))&lt;br /&gt;&lt;br /&gt;(define (word-&gt;index w)&lt;br /&gt;  (let ((char-&gt;num (lambda (c) (- (char-&gt;integer c) (char-&gt;integer #\a))))&lt;br /&gt;        (offsets (map (lambda (e) (expt 2 e)) '(20 15 10 5 0))))&lt;br /&gt;    (apply + (map * (map char-&gt;num (string-&gt;list w)) &lt;br /&gt;                  offsets))))&lt;br /&gt;&lt;br /&gt;(define (index-&gt;word i)&lt;br /&gt;  (let ((num-&gt;char (lambda (n) (integer-&gt;char (+ n (char-&gt;integer #\a)))))&lt;br /&gt;        (offsets (map (lambda (e) (expt 2 e)) '(20 15 10 5 0))))&lt;br /&gt;    (list-&gt;string (map num-&gt;char (map (lambda (o) (remainder (quotient i o) (expt 2 5)))&lt;br /&gt;                                      offsets)))))&lt;br /&gt;&lt;br /&gt;(define (read-sgb-words file)&lt;br /&gt;  (call-with-input-file file&lt;br /&gt;    (lambda (p)&lt;br /&gt;      (let loop ((words '()))&lt;br /&gt;        (let ((x (read-line p)))&lt;br /&gt;          (cond &lt;br /&gt;           ((eof-object? x)&lt;br /&gt;            (reverse words))&lt;br /&gt;           (else &lt;br /&gt;            (loop (cons x words)))))))))&lt;br /&gt;&lt;br /&gt;(define (make-sgb-words-table words)&lt;br /&gt;  (let ((table (make-bytevector (quotient (+ (expt 2 25) 7) 8))))&lt;br /&gt;    (for-each (lambda (x) (bytevector-bit-set! table (word-&gt;index x) 1))&lt;br /&gt;              words)&lt;br /&gt;    table))&lt;br /&gt;&lt;br /&gt;(define words (read-sgb-words "sgb-words.txt"))&lt;br /&gt;(define t (make-sgb-words-table words))&lt;br /&gt;&lt;br /&gt;;; This procedure takes 96sec on Chimaera.&lt;br /&gt;;; Knuth says this process should finish in "at most a few seconds"; see below.&lt;br /&gt;(define (find-max-intermix t words)&lt;br /&gt;  (let ((A-best '())&lt;br /&gt;        (l-best 0)&lt;br /&gt;        (wiz (map word-&gt;index words))&lt;br /&gt;        (two^25 (expt 2 25))&lt;br /&gt;        (two^20 (expt 2 20))&lt;br /&gt;        (two^15 (expt 2 15))&lt;br /&gt;        (two^10 (expt 2 10))&lt;br /&gt;        (two^5  (expt 2  5)))&lt;br /&gt;    (let loop1 ((w1 wiz))&lt;br /&gt;      (cond &lt;br /&gt;       ((not (null? w1))&lt;br /&gt;        (let loop2 ((w2 (cdr w1)))&lt;br /&gt;          (cond &lt;br /&gt;           ((null? w2)&lt;br /&gt;            (loop1 (cdr w1)))&lt;br /&gt;           (else &lt;br /&gt;            (let* ((w (car w1))&lt;br /&gt;                   (w* (car w2))&lt;br /&gt;                   (z (fxxor w w*))&lt;br /&gt;                   (m (+ two^20 two^15 two^10 two^5 1))&lt;br /&gt;                   (m* (* two^5 m)))&lt;br /&gt;              (cond&lt;br /&gt;               ((not (zero? (fxand (fxxor (fx- z m) z m) m*)))&lt;br /&gt;                (loop2 (cdr w2)))&lt;br /&gt;               (else &lt;br /&gt;                (let ((m (vector (fxand z (fx- two^5  1))      ; m_0 &lt;br /&gt;                                 (fxand z (fx- two^10 two^5))  ; m_1&lt;br /&gt;                                 (fxand z (fx- two^15 two^10)) ; m_2&lt;br /&gt;                                 (fxand z (fx- two^20 two^15)) ; m_3&lt;br /&gt;                                 (fxand z (fx- two^25 two^20)) ; m_4&lt;br /&gt;                                 )))&lt;br /&gt;                  (let ((l 1) (A (list w)))&lt;br /&gt;                    (let* ((sw (lambda (j) &lt;br /&gt;                                 (set! w (fxxor w (vector-ref m j)))&lt;br /&gt;                                 (cond ((bytevector-bit-ref? t w)&lt;br /&gt;                                        (set! l (+ l 1))&lt;br /&gt;                                        (set! A (cons w A))))))&lt;br /&gt;                           (swap-0 (lambda () (sw 0)))&lt;br /&gt;                           (swap-1 (lambda () (swap-0) (sw 1) (swap-0)))&lt;br /&gt;                           (swap-2 (lambda () (swap-1) (sw 2) (swap-1)))&lt;br /&gt;                           (swap-3 (lambda () (swap-2) (sw 3) (swap-2)))&lt;br /&gt;                           (swap-4 (lambda () (swap-3) (sw 4) (swap-3))))&lt;br /&gt;                      (swap-4)&lt;br /&gt;                      (cond ((&gt; l l-best)&lt;br /&gt;                             (display A) (newline)&lt;br /&gt;                             (set! l-best l)&lt;br /&gt;                             (set! A-best A))))))&lt;br /&gt;                (loop2 (cdr w2)))))))))))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;;; Knuth says this process should finish in "at most a few seconds" but its &lt;br /&gt;;; taking Chimaera 96.4sec; lets see if allowing more inlining helps matters...&lt;br /&gt;;; - Using internal define for bytevector-bit-ref and bytevector-bit-ref?&lt;br /&gt;;;   shaved off 6 seconds to 90.1sec&lt;br /&gt;;; - Using macros to define { sw, swap-0, swap-1, swap-2, swap-3, swap-4 }&lt;br /&gt;;;   brings time down to 77.7sec&lt;br /&gt;;; - Using macros to define bytevector-bit-ref and bytevector-bit-ref? &lt;br /&gt;;;   did not improve the time at all... (but I did not do it properly the first time!)&lt;br /&gt;;; - Lifting the definitions of m and m* did not improve the time.&lt;br /&gt;;; - Replacing the encoding of m_i via a 5-elem vector with explicit&lt;br /&gt;;;   variables { m_0 .. m_4 } may have shaved a fraction of a second off&lt;br /&gt;;;   the time...&lt;br /&gt;;; - Fixing the macro for bytevector-bit-ref and bytevector-bit-ref? did not help.&lt;br /&gt;;; - Replacing fxarithmetic-shift-left and fxarithmetic-shift-right with fxlsh and fxrsh&lt;br /&gt;;;   was huge; brought time down to 40.5sec&lt;br /&gt;;; - Changing encoding of 2^k to thunks rather than let-bound constants did not help anything.&lt;br /&gt;;; - Changing encoding of 2^k to macros rather than thunks did not help anything [[ but I may have been timing the wrong code here ]]&lt;br /&gt;;; - Changing encoding of m and m' to macros rather than let-bound constants did not help anything.&lt;br /&gt;;; &lt;br /&gt;;;   [[ note on last three items: it looks strongly like Twobit is&lt;br /&gt;;;      reintroducing the let-bindings for temporaries rather than&lt;br /&gt;;;      inline their values in the code, which is interesting.]]&lt;br /&gt;;;   [[ (are fxlsh and friends not interpreted at compile time?) ]]&lt;br /&gt;&lt;br /&gt;;; - Manually constant folding fxlsh and friends got down to 39.8sec (maybe not statistically sig delta).&lt;br /&gt;;; - Adding check for bytevector? of t at outset got down to 39.1sec (again maybe not stat sig on own).&lt;br /&gt;;; - Switching to multi-valued fxdiv-and-mod was a terrible idea (x2.5 slowdown)&lt;br /&gt;;; - And even using fxdiv fxmod separately was a terrible idea (x2 slowdown)&lt;br /&gt;&lt;br /&gt;;;   [[ We apparently do not have any compiler optimizations for fxquotient and similar; hmm. ]]&lt;br /&gt;&lt;br /&gt;;; - Changing the code to use fxrhsl and fxand instead of quotient and remainder&lt;br /&gt;;;   brings running time down to 9sec (from between 37 and 39 seconds; another huge leap!).&lt;br /&gt; &lt;br /&gt;(define (find-max-intermix.v16 t words)&lt;br /&gt;&lt;br /&gt;  (let*-syntax ((bytevector-bit-ref &lt;br /&gt;                 (syntax-rules () &lt;br /&gt;                   ((_ bv k)&lt;br /&gt;                    (let ((q (fxrshl k 3))&lt;br /&gt;                          (r (fxand  k #b111)))&lt;br /&gt;                      (fxrsha&lt;br /&gt;                       (fxand (bytevector-u8-ref bv q)&lt;br /&gt;                              (fxlsh 1 r)) r)))))&lt;br /&gt;&lt;br /&gt;               (bytevector-bit-ref? &lt;br /&gt;                (syntax-rules () &lt;br /&gt;                  ((_ bv k)&lt;br /&gt;                   (not (zero? (bytevector-bit-ref bv k))))))&lt;br /&gt;&lt;br /&gt;               (two^25 (syntax-rules () ((_) 33554432)))&lt;br /&gt;               (two^20 (syntax-rules () ((_) 1048576)))&lt;br /&gt;               (two^15 (syntax-rules () ((_) 32768)))&lt;br /&gt;               (two^10 (syntax-rules () ((_) 1024)))&lt;br /&gt;               (two^5  (syntax-rules () ((_) 32)))&lt;br /&gt;               (m      (syntax-rules () ((_) 1082401 )))   ;; (+ (two^20) (two^15) (two^10) (two^5) 1) &lt;br /&gt;               (m*     (syntax-rules () ((_) 34636832 ))) ;; (* (two^5) (m)))))&lt;br /&gt;               )&lt;br /&gt;&lt;br /&gt; (let* ((A-best '())&lt;br /&gt;        (l-best 0)&lt;br /&gt;        (wiz (map word-&gt;index words)))&lt;br /&gt;   (cond &lt;br /&gt;    ((not (bytevector? t)) (error))&lt;br /&gt;    (else &lt;br /&gt;    (let loop1 ((w1 wiz))&lt;br /&gt;      (cond &lt;br /&gt;       ((not (null? w1))&lt;br /&gt;        (let loop2 ((w2 (cdr w1)))&lt;br /&gt;          (cond &lt;br /&gt;           ((null? w2)&lt;br /&gt;            (loop1 (cdr w1)))&lt;br /&gt;           (else &lt;br /&gt;            (let* ((w (car w1))&lt;br /&gt;                   (w* (car w2))&lt;br /&gt;                   (z (fxxor w w*)))&lt;br /&gt;              (cond&lt;br /&gt;               ((not (fxzero? (fxand (fxxor (fx- z (m)) z (m)) (m*))))&lt;br /&gt;                (loop2 (cdr w2)))&lt;br /&gt;               (else &lt;br /&gt;                (let ((m_0 (fxand z (fx- (two^5)  1)))&lt;br /&gt;                      (m_1 (fxand z (fx- (two^10) (two^5))))&lt;br /&gt;                      (m_2 (fxand z (fx- (two^15) (two^10))))&lt;br /&gt;                      (m_3 (fxand z (fx- (two^20) (two^15))))&lt;br /&gt;                      (m_4 (fxand z (fx- (two^25) (two^20)))))&lt;br /&gt;                  (let ((l 1) (A (list w)))&lt;br /&gt;                    (let*-syntax ((upd (syntax-rules ()&lt;br /&gt;                                         ((upd) (cond ((bytevector-bit-ref? t w)&lt;br /&gt;                                                       (set! l (+ l 1))&lt;br /&gt;                                                       (set! A (cons w A)))))))&lt;br /&gt;                                  (sw (syntax-rules ()&lt;br /&gt;                                        ((sw 0) (begin (set! w (fxxor w m_0)) (upd)))&lt;br /&gt;                                        ((sw 1) (begin (set! w (fxxor w m_1)) (upd)))&lt;br /&gt;                                        ((sw 2) (begin (set! w (fxxor w m_2)) (upd)))&lt;br /&gt;                                        ((sw 3) (begin (set! w (fxxor w m_3)) (upd)))&lt;br /&gt;                                        ((sw 4) (begin (set! w (fxxor w m_4)) (upd)))))&lt;br /&gt;                                  (swap-0 (syntax-rules () &lt;br /&gt;                                            ((_) (sw 0))))&lt;br /&gt;                                  (swap-1 (syntax-rules ()&lt;br /&gt;                                            ((_) (begin (swap-0) (sw 1) (swap-0)))))&lt;br /&gt;                                  (swap-2 (syntax-rules () &lt;br /&gt;                                            ((_) (begin (swap-1) (sw 2) (swap-1)))))&lt;br /&gt;                                  (swap-3 (syntax-rules () &lt;br /&gt;                                            ((_) (begin (swap-2) (sw 3) (swap-2)))))&lt;br /&gt;                                  (swap-4 (syntax-rules () &lt;br /&gt;                                            ((_) (begin (swap-3) (sw 4) (swap-3))))))&lt;br /&gt;                     (begin&lt;br /&gt;                       (swap-4)&lt;br /&gt;                       (cond ((&gt; l l-best)&lt;br /&gt;                              (display A) (newline)&lt;br /&gt;                              (set! l-best l)&lt;br /&gt;                              (set! A-best A)))))))&lt;br /&gt;                (loop2 (cdr w2))))))))))))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;UPDATE: I realized it might be worthwhile to identify how much speed-up would have resulted if I had just applied the most important steps to the original version at the outset.&lt;br /&gt;&lt;br /&gt;The answer is that just:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Turning the bit-referencing operations into internal defines within the procedure, and &lt;/li&gt;&lt;br /&gt;&lt;li&gt; Using the fxlsh, fxrshl, and fxand operations for the definitions of the bit-referencing operations &lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;brings the running time down to 18 seconds.  So somewhere around 70 seconds of the time was spent on inefficiencies due to using general purpose arithmetic operations when fixnum operations (that the compiler specializes) would probably suffice for most people; no need to use macros to force an inlined swap(4) operation (which is what Knuth recommends in his text).&lt;br /&gt;&lt;br /&gt;Here is the 18 second version.  Note that its code bytevector after being compiled by Twobit is 4.0 kilobytes, while the more heavily optimized find-max-intermix.v16 is 17.8 kilobytes; that is a 4x space regression for a 2x speed improvement.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (find-max-intermix t words)&lt;br /&gt;&lt;br /&gt;  (define bytevector-bit-ref &lt;br /&gt;    (lambda (bv k)&lt;br /&gt;      (let ((q (fxrshl k 3))&lt;br /&gt;            (r (fxand k #b111)))&lt;br /&gt;        (fxrshl&lt;br /&gt;         (fxand (bytevector-u8-ref bv q)&lt;br /&gt;                (fxlsh 1 r)) r))))&lt;br /&gt;&lt;br /&gt;  (define bytevector-bit-ref? &lt;br /&gt;    (lambda (bv k)&lt;br /&gt;      (not (zero? (bytevector-bit-ref bv k)))))&lt;br /&gt;&lt;br /&gt;  (let ((A-best '())&lt;br /&gt;        (l-best 0)&lt;br /&gt;        (wiz (map word-&gt;index words))&lt;br /&gt;        (two^25 (expt 2 25))&lt;br /&gt;        (two^20 (expt 2 20))&lt;br /&gt;        (two^15 (expt 2 15))&lt;br /&gt;        (two^10 (expt 2 10))&lt;br /&gt;        (two^5  (expt 2  5)))&lt;br /&gt;    (let loop1 ((w1 wiz))&lt;br /&gt;      (cond &lt;br /&gt;       ((not (null? w1))&lt;br /&gt;        (let loop2 ((w2 (cdr w1)))&lt;br /&gt;          (cond &lt;br /&gt;           ((null? w2)&lt;br /&gt;            (loop1 (cdr w1)))&lt;br /&gt;           (else &lt;br /&gt;            (let* ((w (car w1))&lt;br /&gt;                   (w* (car w2))&lt;br /&gt;                   (z (fxxor w w*))&lt;br /&gt;                   (m (+ two^20 two^15 two^10 two^5 1))&lt;br /&gt;                   (m* (* two^5 m)))&lt;br /&gt;              (cond&lt;br /&gt;               ((not (zero? (fxand (fxxor (fx- z m) z m) m*)))&lt;br /&gt;                (loop2 (cdr w2)))&lt;br /&gt;               (else &lt;br /&gt;                (let ((m (vector (fxand z (fx- two^5  1))      ; m_0 &lt;br /&gt;                                 (fxand z (fx- two^10 two^5))  ; m_1&lt;br /&gt;                                 (fxand z (fx- two^15 two^10)) ; m_2&lt;br /&gt;                                 (fxand z (fx- two^20 two^15)) ; m_3&lt;br /&gt;                                 (fxand z (fx- two^25 two^20)) ; m_4&lt;br /&gt;                                 )))&lt;br /&gt;                  (let ((l 1) (A (list w)))&lt;br /&gt;                    (let* ((sw (lambda (j) &lt;br /&gt;                                 (set! w (fxxor w (vector-ref m j)))&lt;br /&gt;                                 (cond ((bytevector-bit-ref? t w)&lt;br /&gt;                                        (set! l (+ l 1))&lt;br /&gt;                                        (set! A (cons w A))))))&lt;br /&gt;                           (swap-0 (lambda () (sw 0)))&lt;br /&gt;                           (swap-1 (lambda () (swap-0) (sw 1) (swap-0)))&lt;br /&gt;                           (swap-2 (lambda () (swap-1) (sw 2) (swap-1)))&lt;br /&gt;                           (swap-3 (lambda () (swap-2) (sw 3) (swap-2)))&lt;br /&gt;                           (swap-4 (lambda () (swap-3) (sw 4) (swap-3))))&lt;br /&gt;                      (swap-4)&lt;br /&gt;                      (cond ((&gt; l l-best)&lt;br /&gt;                             (display A) (newline)&lt;br /&gt;                             (set! l-best l)&lt;br /&gt;                             (set! A-best A))))))&lt;br /&gt;                (loop2 (cdr w2)))))))))))))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-5697851162883685703?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/5697851162883685703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=5697851162883685703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/5697851162883685703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/5697851162883685703'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/08/from-90sec-to-9sec.html' title='from 90sec to 9sec.'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-8368908342819203624</id><published>2009-08-27T08:52:00.000-07:00</published><updated>2009-09-09T20:08:33.697-07:00</updated><title type='text'>mismatch twixt formals and invocation forms</title><content type='html'>As a follow up to my &lt;a href="http://pnkfif.blogspot.com/2009/08/yet-another-yield-scheme-macro.html"&gt;yet-another-generator macro post&lt;/a&gt;: &lt;br /&gt;&lt;br /&gt;yesterday at lunch I was trying to describe my problems generalizing my generator macro to handle arbitrary lambda formals lists.  Ryan was the one who summed the problem up best; I think he said "there is a asymmetry between the format of the formals list and the format of invocation"&lt;br /&gt;&lt;br /&gt;The problem in essence is that there are two distinct cases that are easy.&lt;br /&gt;If you want to match a proper list of formals and generate a corresponding invocation, you do something like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax adder &lt;br /&gt;  (syntax-rules () &lt;br /&gt;    ((_ (args ...) k ...) &lt;br /&gt;     (lambda (args ...) (+ k ... args ...)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And, if you want to do variable arity, you can do it by matching an identifier representing the whole list of arguments&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax adder &lt;br /&gt;  (syntax-rules () &lt;br /&gt;    ((_ argl k ...) &lt;br /&gt;     (lambda argl (apply + k ... argl)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But notice the difference between the bottom and the top.  If some users of the &lt;code&gt;adder&lt;/code&gt; macro want to be able to specify that they are generating a procedure of arity 2, with appropriate error detection, they can use the first but not the second.  And of course, the first does not do variable arity procedures.&lt;br /&gt;&lt;br /&gt;To deal with this problem in the context of my generator macro, I introduced a helper macro that builds up an application expression based on the form of the formals list.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax build-apply &lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((build-apply (rator rands ...) (args ...)) ;; usual case&lt;br /&gt;     (rator rands ... args ...))&lt;br /&gt;    ((build-apply (rator rands ...) (x . y))    ;; improper list, inductive case&lt;br /&gt;     (build-apply (rator rands ...   x)  y))&lt;br /&gt;    ((build-apply (rator rands ...) rest-args)  ;; improper list, base case&lt;br /&gt;     (apply rator rands ... rest-args))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The order of all three clauses above is very significant.&lt;br /&gt;&lt;br /&gt;With that in place, here is the new form of my generator macro(s):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;;; (generator ARGS BODY ...) =&gt; procedure &lt;br /&gt;;;   in whose body yield is bound to coroutine with caller&lt;br /&gt;(define-syntax generator&lt;br /&gt;  (transformer &lt;br /&gt;   (lambda (exp ren cmp)&lt;br /&gt;     `(,(ren 'generator-via) yield ,(cadr exp) ,@(cddr exp)))))&lt;br /&gt;&lt;br /&gt;(define-syntax generator-via&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((generator-via yield-id args body ...)&lt;br /&gt;       (let ((get-next #f))&lt;br /&gt;         (lambda args&lt;br /&gt;           (call-with-current-continuation&lt;br /&gt;            (lambda (exit)&lt;br /&gt;              (cond &lt;br /&gt;               (get-next (build-apply (get-next exit) args))&lt;br /&gt;               (else (let ((yield-id &lt;br /&gt;                            (lambda results &lt;br /&gt;                              (call-with-current-continuation&lt;br /&gt;                               (lambda (next)&lt;br /&gt;                                 (set! get-next (lambda (new-exit . args)&lt;br /&gt;                                                  (set! exit new-exit)&lt;br /&gt;                                                  (build-apply (next) args)))&lt;br /&gt;                                 (apply exit results))))))&lt;br /&gt;                       (call-with-values (lambda () body ...)&lt;br /&gt;                         ;; below could also use build-apply with&lt;br /&gt;                         ;; args, but then the "done-value"(s)&lt;br /&gt;                         ;; returned from a generator would be forced&lt;br /&gt;                         ;; to have value-count = length args&lt;br /&gt;                         (lambda argl &lt;br /&gt;                           (set! get-next (lambda (new-exit . args)&lt;br /&gt;                                            (apply new-exit argl)))&lt;br /&gt;                           (apply exit argl)))))))))))))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-8368908342819203624?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/8368908342819203624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=8368908342819203624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/8368908342819203624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/8368908342819203624'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/08/mismatch-twixt-formals-and-invocation.html' title='mismatch twixt formals and invocation forms'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-1346017733286283641</id><published>2009-08-25T21:40:00.000-07:00</published><updated>2009-08-25T21:59:49.579-07:00</updated><title type='text'>yet another yield Scheme macro</title><content type='html'>I have seen &lt;code&gt;yield&lt;/code&gt; done plenty of times before, but I managed to reinvent it again tonight.&lt;br /&gt;&lt;br /&gt;A lot of the time when I've played with &lt;code&gt;call/cc&lt;/code&gt;, I have approached it trying to recreate a form in a statement-oriented language, and so I would end up not caring about the argument I would pass to the invocation of the captured continuation (because all I cared about was reestablishing the control flow of the prior context; the prior context itself would just discard any value I passed to it).  I think the usual interpretation of &lt;code&gt;yield&lt;/code&gt; is an instance of this in statement oriented languages.&lt;br /&gt;&lt;br /&gt;However, when I was playing with some code tonight, I saw that dummy value and said, "ugly!  why is that there?"  And I decided to see what would happen if I got rid of it.&lt;br /&gt;&lt;br /&gt;This macro is the result.  (Obviously you want a bit of sugar around it to non-hygenically bind &lt;code&gt;yield&lt;/code&gt;, although there are cases where it is nice to bind a different name like &lt;code&gt;visit&lt;/code&gt; instead of &lt;code&gt;yield&lt;/code&gt;, depending on the domain.)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax generator-via&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ;; puzzle 4 U: what role(s) does arg-list serve?  (all occurrences matter)&lt;br /&gt;    ((generator-via yield-id arg-list body ...)&lt;br /&gt;     (let ((yield-id #f) (get-next #f))&lt;br /&gt;       (lambda arg-list&lt;br /&gt;         (call-with-current-continuation&lt;br /&gt;          (lambda (exit)&lt;br /&gt;            (cond (get-next (get-next exit . arg-list))&lt;br /&gt;                  (else (set! yield-id (lambda results &lt;br /&gt;                                         (call-with-current-continuation&lt;br /&gt;                                          (lambda (next)&lt;br /&gt;                                            (set! get-next &lt;br /&gt;                                                  (lambda (new-exit . arg-list)&lt;br /&gt;                                                    (set! exit new-exit)&lt;br /&gt;                                                    (next . arg-list)))&lt;br /&gt;                                            (apply exit results)))))&lt;br /&gt;                        (call-with-values (lambda () body ...)&lt;br /&gt;                          ;; puzzle 4 U: why below eta-expansion required?&lt;br /&gt;                          (lambda args (apply exit args))))))))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Its got some fun behaviors.  Consider:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (define grows &lt;br /&gt;    (generator-via yield (x) &lt;br /&gt;      (let loop ((i 0)) &lt;br /&gt;        (loop (+ i x (yield i))))))&lt;br /&gt;&lt;br /&gt;&gt; (grows 1)&lt;br /&gt;0&lt;br /&gt;&lt;br /&gt;&gt; (grows 0)&lt;br /&gt;1&lt;br /&gt;&lt;br /&gt;&gt; (grows 0)&lt;br /&gt;2&lt;br /&gt;&lt;br /&gt;&gt; (grows 0)&lt;br /&gt;3&lt;br /&gt;&lt;br /&gt;&gt; (grows 1)&lt;br /&gt;5&lt;br /&gt;&lt;br /&gt;&gt; (grows 0)&lt;br /&gt;6&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(yes I just realized I could/should have &lt;code&gt;let&lt;/code&gt;-bound the &lt;code&gt;yield-id&lt;/code&gt; itself.  The other &lt;code&gt;set!&lt;/code&gt; invocations are believed to be necessary, barring tricks mixing &lt;code&gt;letrec&lt;/code&gt; and &lt;code&gt;call/cc&lt;/code&gt;.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-1346017733286283641?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/1346017733286283641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=1346017733286283641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/1346017733286283641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/1346017733286283641'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/08/yet-another-yield-scheme-macro.html' title='yet another yield Scheme macro'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-9026788559417067708</id><published>2009-07-29T12:13:00.000-07:00</published><updated>2009-07-29T12:31:41.144-07:00</updated><title type='text'>(no) interpreters on iphone</title><content type='html'>I'm collecting blog posts and web pages discussing clause 3.3.2 of the iPhone SDK EULA and semi-related restrictions on iPhone apps.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mobilephonedevelopment.com/archives/830"&gt;mobilephonedevelopment article&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rhomobile.com/blog/2009/05/29/iphone-app-store-rules-and-guidelines-on-use-of-frameworks/"&gt;rhomobile's interpretation of no interpreters rule&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://smartcalc.coollittlethings.com/?p=3"&gt;story&lt;/a&gt; of how a Basic interpreter got downgraded to a calculator (and how to bring the interpreter back if you're willing to jailbreak).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.google.com/group/phonegap/browse_thread/thread/3ab8cc64b5d6ea35"&gt;PhoneGap Discussion&lt;/a&gt; of arbitrariness of rejection&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.macnn.com/articles/09/05/19/phonegap.vs.app.store/"&gt;MacNN&lt;/a&gt; coverage of the PhoneGap issue.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://iphoneblips.dailyradar.com/story/full_commodore_64_emulator_rejected_from_app_store/"&gt;Commodore 64 emulator&lt;/a&gt; rejection article&lt;br /&gt;&lt;br /&gt;FrotZ got through the filter; I asked the developer about that in this &lt;a href="http://groups.google.com/group/ifrotz-discuss/browse_thread/thread/4f4562962c5f06bb"&gt;discussion&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-9026788559417067708?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/9026788559417067708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=9026788559417067708' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/9026788559417067708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/9026788559417067708'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/07/no-interpreters-on-iphone.html' title='(no) interpreters on iphone'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-4177608528939927934</id><published>2009-07-21T18:56:00.000-07:00</published><updated>2009-07-22T09:03:33.674-07:00</updated><title type='text'>git-svn argh!</title><content type='html'>CCIS decommissioned a number of its Solaris machines recently.&lt;br /&gt;&lt;br /&gt;I was using one of them as the point of access for the Larceny SVN repository, via the svn+ssh protocol. &lt;br /&gt;&lt;br /&gt;More recently I have been playing with git-svn, using that as my way to interact with the repository.  I made a local git-svn clone of the Larceny SVN repository, and then I would clone the clone and make branches in the cloned clones as part of my experimentation with new ideas.  Fun fun fun.&lt;br /&gt;&lt;br /&gt;Except that CCIS decommissioned a number of its Solaris machines recently, and I was using one of them as the point of access, which mean that the repository url looked something like &lt;code&gt;svn+ssh://zulu.ccs.neu.edu/path-to-repos/&lt;/code&gt;, and git-svn (somewhat reasonably) assumes that these URLS would remain valid forever, and puts a copy of that URL into &lt;span style="font-style:italic;"&gt;every log message&lt;/span&gt; of the clone.&lt;br /&gt;&lt;br /&gt;Now, its easy to update those log messages; that's what git-filter-branch is for.  (See also &lt;a href="http://translate.org.za/blogs/wynand/en/content/changing-your-svn-repository-address-git-svn-setup"&gt;this related blog entry&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;But what's not so easy is dealing with the sudden split in the tree structure of the development on my cloned clones; all of my local deltas seem to point to the old changesets with the old bad URL.  And "git rebase" does not seem to be magically able to handle this case.&lt;br /&gt;&lt;br /&gt;Thus: git-svn argh!&lt;br /&gt;&lt;br /&gt;If the SVN folks though that a "svn switch --relocate" command was important, maybe the git-svn developer(s) should also consider their design decisions...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-4177608528939927934?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/4177608528939927934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=4177608528939927934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/4177608528939927934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/4177608528939927934'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/07/git-svn-argh.html' title='git-svn argh!'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-2855241859910205637</id><published>2009-01-12T19:57:00.000-08:00</published><updated>2009-01-12T20:01:01.206-08:00</updated><title type='text'>Zecreasing Zerived Zvariables</title><content type='html'>This is a great little story.  And probably something I could explain to my Mom.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.freedom-to-tinker.com/blog/felten/debugging-zune-blackout"&gt;http://www.freedom-to-tinker.com/blog/felten/debugging-zune-blackout&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(plus I've had &lt;a href="http://groups.google.com/group/comp.lang.scheme/msg/ac67dbd03048c86d?hl=en&amp;dmode=source"&gt;this obsession&lt;/a&gt; with date-oriented code lately...)&lt;br /&gt;&lt;br /&gt;(p.s. can one even pronounce "Zvariables"?)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-2855241859910205637?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/2855241859910205637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=2855241859910205637' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/2855241859910205637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/2855241859910205637'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/01/zecreasing-zerived-zvariables.html' title='Zecreasing Zerived Zvariables'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-6736843753738012438</id><published>2009-01-09T16:25:00.001-08:00</published><updated>2009-01-09T16:59:14.733-08:00</updated><title type='text'>5 or 6 forced restarts later...</title><content type='html'>I wasted some time this evening trying to use &lt;tt&gt;gprof&lt;/tt&gt; to profile Larceny.&lt;br /&gt;&lt;br /&gt;Eventually I discovered that the &lt;tt&gt;-pg&lt;/tt&gt; option simply does not work with &lt;tt&gt;gcc&lt;/tt&gt; on Intel Macs.  (Why on earth doesn't the man page for &lt;tt&gt;gprof&lt;/tt&gt; say something about this?)&lt;br /&gt;&lt;br /&gt;Apple instead recommends that one use &lt;a href="http://developer.apple.com/tools/shark_optimize.html"&gt;Shark&lt;/a&gt; or &lt;a href="http://developer.apple.com/documentation/DeveloperTools/Conceptual/SaturnUserGuide/Introduction/chapter_1_section_1.html"&gt;Saturn&lt;/a&gt;, both provided when you install the &lt;em&gt;CHUD Tools&lt;/em&gt; (Computer Hardware Understanding Developer Tools)&lt;br /&gt;&lt;br /&gt;So I did that.  I downloaded a copy of the CHUD Tools (and as far as I can remember, I did it by searching on ADC for them, and got a copy of &lt;tt&gt;chud.dmg&lt;/tt&gt;).  I was a little surprised by the file times (they said something like 2007) but I pressed on, eager to start seeing some profiler output, especially since all of my searches to read about Shark sounded very positive about it.&lt;br /&gt;&lt;br /&gt;And then when I attempted to compile with &lt;tt&gt;-finstrument-functions&lt;/tt&gt;, so I could use &lt;tt&gt;Saturn&lt;/tt&gt; in the same way that I might have used &lt;tt&gt;gprof&lt;/tt&gt;, I got a link error:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Undefined symbols:&lt;br /&gt;  "___cyg_profile_func_exit", referenced from:&lt;br /&gt;      _consolemsg in larceny.o&lt;br /&gt;      _consolemsg in larceny.o&lt;br /&gt;     ...&lt;br /&gt;  "___cyg_profile_func_enter", referenced from:&lt;br /&gt;      _panic_abort in larceny.o&lt;br /&gt;      _panic_exit in larceny.o&lt;br /&gt;    ...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I abandoned further attempts to use Saturn pretty quickly.&lt;br /&gt;&lt;br /&gt;So then I tried Shark.  And that was, if anything, worse.  Because every time I tried to stop a profiling session, it would &lt;b&gt;restart&lt;/b&gt; my machine!&lt;br /&gt;&lt;br /&gt;Eventually I discovered (though not &lt;em&gt;easily&lt;/em&gt;) &lt;a href="http://lists.apple.com/archives/PerfOptimization-dev/2008/Sep/msg00050.html"&gt;this discussion post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hmm.  CHUD 4.4.4 panics.  I look at my version.  Yep, its 4.4.4.&lt;br /&gt;&lt;br /&gt;So I did a more careful search for a more recent version of CHUD (4.6.1, specifically).  We'll see how that works out for me in a bit.&lt;br /&gt;&lt;br /&gt;(I'm mostly posting this so that other people who run into a similar problem know that they need to get a newer version of CHUD.  Maybe later I'll try to retrace my steps that led me to thinking that CHUD 4.4.4 was the version I needed to use...)&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt; I do not know who linked to it, but some page (that I believe was on the Apple site) sent me to the follow ftp link, which has the version of CHUD that is incompatible with newer versions of OS X: &lt;tt&gt;ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/CHUD_4.4.4.dmg&lt;/tt&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-6736843753738012438?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/6736843753738012438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=6736843753738012438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/6736843753738012438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/6736843753738012438'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2009/01/5-or-6-forced-restarts-later.html' title='5 or 6 forced restarts later...'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-8830809241663831462</id><published>2008-12-15T09:55:00.000-08:00</published><updated>2008-12-15T09:56:43.039-08:00</updated><title type='text'>CFER : "suitable for blogs"</title><content type='html'>ICFP 2009 has a "Call For Experience Reports", and specifically mentions that its suitable for posting on blogs.  &lt;br /&gt;&lt;br /&gt;So here goes.  :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://web.cecs.pdx.edu/~apt/icfp09_cfer.html"&gt;ICFP 2009: CFER&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-8830809241663831462?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/8830809241663831462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=8830809241663831462' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/8830809241663831462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/8830809241663831462'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2008/12/cfer-suitable-for-blogs.html' title='CFER : &quot;suitable for blogs&quot;'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-2644668922966420407</id><published>2008-07-02T15:41:00.000-07:00</published><updated>2008-07-02T15:47:06.715-07:00</updated><title type='text'>data structures, network outages, and php</title><content type='html'>The most "productive" portion of my day was spent prototyping the interface to summary set matrix that I will be putting into the regional collector RSN.  I have the header file worked out and started working on the representation itself.  I got part way through writing a constructor function before deciding that I wanted to think a bit more about how I want to handle allocation and deallocation of the entries in the sparse matrix.&lt;br /&gt;&lt;br /&gt;(Some of that time was spent reviewing the existing source for the Larceny runtime, especially the different attribute bits one can put on pages of memory in Larceny, and the history of when they were introduced and/or shifted around by Lars...)&lt;br /&gt;&lt;br /&gt;I also had a back-and-forth with the Systems staff since artichoke and poblano became inaccessible from the outside world at some point yesterday evening.&lt;br /&gt;&lt;br /&gt;I finished off the day trying to figure out why my GC benchmarking script is still failing on the dynregion/ branch.  I have more of a clue about it now, but am pretty unhappy about how much of a kludge this supposedly simpler script is becoming.  (Maybe I should give up doing these things in shell script and just do them as Larceny scripts.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-2644668922966420407?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/2644668922966420407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=2644668922966420407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/2644668922966420407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/2644668922966420407'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2008/07/data-structures-network-outages-and-php.html' title='data structures, network outages, and php'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-6267493255795795973</id><published>2008-06-30T14:31:00.001-07:00</published><updated>2008-06-30T14:44:48.918-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stopcopy autobuild'/><title type='text'>hi after hiatus</title><content type='html'>This weekend I mentioned that I had a blog to my family, and then showed the url to Stephanie.&lt;br /&gt;&lt;br /&gt;I proceeded to become engrossed in reading over my old posts; I had forgotten some of the interesting software experiments I had been posting online.&lt;br /&gt;&lt;br /&gt;Of course, I have not made a post in almost two years.  I have since switched to keeping an internal work diary, so that I would not worry about giving away the farm (or embarrassing outcomes of my day to day research), and also posting any interesting links that I wanted to see later to &lt;a href="http://del.icio.us/pnkfelix/"&gt;my del.icio.us account&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But I realized after looking at the old entries that I liked broadcasting my progress.  &lt;br /&gt;&lt;br /&gt;So I am going to try to maintain this blog again, and see if I can figure out how to distill my daily work diary into something small (and publicly distributable) each day (or perhaps every other day or so... who knows).&lt;br /&gt;&lt;br /&gt;So, today:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt; Rasputin's disk was full; I had to wrestle with that for a little while.  It seems like each disk fills up on such a regular basis that I really should consider fixing the autobuild scripts to clean up after themselves or to compress their generated directories or both...&lt;/li&gt;&lt;br /&gt;&lt;li&gt; I finally checked in a fix to Larceny's simplistic stopcopy collector on the IAssassin backend so that when allocation fills up a chunk in a semispace, the runtime first attempts to switch the allocation pointer to a free chunk within the semispace rather than attempt a whole heap collection.  This is a crucial fix, because the stopcopy collector's performance had asymptotically terrible performance before, which affected both our benchmark results &lt;span style="font-weight:bold;"&gt;and&lt;/span&gt;  some of our users who wanted to load a lot of code before performing a heap dump.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I spent some time trying to double-check the runtime source code's make dependencies, because I thought I saw evidence that not everything was being rebuilt properly in response to changes I made for fixing the stopcopy collector.  Unfortunately I was unable to pin down any particular missing dependency.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I tried generalizing the nightly GC benchmarking script so that it could also benchmark my &lt;code&gt;dynregion&lt;/code&gt; development branch.  But then my attempts to just double-check the behavior of the GC benchmarking script itself failed, and my investigations there led me to file Ticket #547 in Larceny's trac database.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I also spent some time browsing the web/google groups/etc.  I added some links to my aforementioned del.icio.us account.  I don't think I'll be explicitly mentioning such activity on my part in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-6267493255795795973?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/6267493255795795973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=6267493255795795973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/6267493255795795973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/6267493255795795973'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2008/06/hi-after-hiatus.html' title='hi after hiatus'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-115794581504166041</id><published>2006-09-10T20:34:00.000-07:00</published><updated>2006-09-10T20:45:29.550-07:00</updated><title type='text'>Oh hdiutil, what can't you do?</title><content type='html'>&lt;a href="http://www.tech-recipes.com/rx/1529/convert_mac_osx_dmg_cd_dvd_image_to_iso_format_burn_windows"&gt;(orig article)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The punchline:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;hdiutil convert image.dmg -format UDTO -o image.iso &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Although this makes a file with the extension &lt;code&gt;.cdr&lt;/code&gt;, the article claims that it is an iso file and can be renamed as such.&lt;br /&gt;&lt;br /&gt;This allows me to use the OS X Disk Utility to create .iso images that can then be mounted from Parallels desktop or VMware.&lt;br /&gt;&lt;br /&gt;UPDATE:&lt;br /&gt;The above article seems to be a complete lie, but at least it pointed me at &lt;code&gt;hdiutil&lt;/code&gt;... the above approach makes iso images that Mac OS X can mount, but do not work within Parallels.&lt;br /&gt;&lt;br /&gt;However, the following command seems like it does the job:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;hdiutil makehybrid -o image image.dmg&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-115794581504166041?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/115794581504166041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=115794581504166041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115794581504166041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115794581504166041'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/09/oh-hdiutil-what-cant-you-do.html' title='Oh hdiutil, what can&apos;t you do?'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-115506237422421221</id><published>2006-08-08T11:37:00.000-07:00</published><updated>2006-08-08T11:39:34.240-07:00</updated><title type='text'>stupid LEA tricks</title><content type='html'>&lt;code&gt;LEA&lt;/code&gt; is the "load effective address" instruction on x86 processors.&lt;br /&gt;&lt;br /&gt;Despite the "L" in the name, this is solely an arithmetic instruction.  Which means there are some nasty little games you can play with it.  Like this one I got courtesy of Frank Kotler from:&lt;br /&gt;&lt;br /&gt;http://groups.google.com/group/alt.lang.asm/msg/27d6ed6183448057?hl=en&amp;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;global _start &lt;br /&gt;&lt;br /&gt;section .data &lt;br /&gt;     number_string db '123', 10 &lt;br /&gt;&lt;br /&gt;section .text &lt;br /&gt;_start: &lt;br /&gt;     nop &lt;br /&gt;&lt;br /&gt;     push number_string &lt;br /&gt;     call atoi &lt;br /&gt;     add esp, byte 4 &lt;br /&gt;&lt;br /&gt;     mov ebx, eax &lt;br /&gt;     mov eax, 1 &lt;br /&gt;     int 80h &lt;br /&gt;&lt;br /&gt;atoi: &lt;br /&gt;     mov edx, [esp + 4]  ; pointer to string &lt;br /&gt;     xor eax, eax        ; clear "result" &lt;br /&gt;.top: &lt;br /&gt;     movzx ecx, byte [edx] &lt;br /&gt;     inc edx &lt;br /&gt;     cmp ecx, byte '0' &lt;br /&gt;     jb .done &lt;br /&gt;     cmp ecx, byte '9' &lt;br /&gt;     ja .done &lt;br /&gt;&lt;br /&gt;     ; we have a valid character - multiply &lt;br /&gt;     ; result-so-far by 10, subtract '0' &lt;br /&gt;     ; from the character to convert it to &lt;br /&gt;     ; a number, and add it to result. &lt;br /&gt;&lt;br /&gt;     lea eax, [eax + eax * 4] &lt;br /&gt;     lea eax, [eax * 2 + ecx - 48] &lt;br /&gt;&lt;br /&gt;     jmp short .top &lt;br /&gt;.done &lt;br /&gt;     ret &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-115506237422421221?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/115506237422421221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=115506237422421221' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115506237422421221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115506237422421221'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/08/stupid-lea-tricks.html' title='stupid LEA tricks'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-115325474507230271</id><published>2006-07-18T13:26:00.000-07:00</published><updated>2006-07-18T13:32:25.083-07:00</updated><title type='text'>free smalltalk! (books, that is)</title><content type='html'>Just discovered this page today:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.iam.unibe.ch/~ducasse/FreeBooks.html"&gt;20 smalltalk books&lt;/a&gt;, all available for free viewing online.&lt;/li&gt;&lt;/ul&gt;On a related note, here are some other free books online that I wasn't aware of until recently:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.rubycentral.com/book/"&gt;"Programming Ruby: The Pragmatic Programmer's Guide"&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://thinking-forth.sourceforge.net/"&gt;"Thinking Forth"&lt;/a&gt;; the PDFs there didn't work for me, but the LaTeX source is supposedly up there as well...&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-115325474507230271?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/115325474507230271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=115325474507230271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115325474507230271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/115325474507230271'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/07/free-smalltalk-books-that-is.html' title='free smalltalk! (books, that is)'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-114667527970009377</id><published>2006-05-03T09:38:00.000-07:00</published><updated>2006-05-03T09:55:34.516-07:00</updated><title type='text'>321 contact!</title><content type='html'>Larceny's just ran x86 code &lt;em&gt;in heap&lt;/em&gt; for the first time!&lt;br /&gt;&lt;br /&gt;The initial scheme code:&lt;font color="red"&gt;&lt;pre&gt;(define seg (assemble (compile 321)))&lt;br /&gt;(define env (environment-copy (interaction-environment)))&lt;br /&gt;(define cseg (sassy-postpass-segment seg))&lt;br /&gt;(define linked (link-lop-segment cseg env))&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;br /&gt;Note that the "program" we're compiling here is just evaluating the literal &lt;code&gt;321&lt;/code&gt;.  Not very exciting to interpret, but to run off the heap, &lt;em&gt;marvelous!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The (insane) hack on the x86 implementation of MacScheme's invoke:&lt;br /&gt;&lt;font color="blue"&gt;&lt;pre&gt; dec dword [GLOBALS+G_TIMER]&lt;br /&gt; jnz short %%L1&lt;br /&gt;%%L0: mcall M_INVOKE_EX&lt;br /&gt; jmp short %%L1&lt;br /&gt;%%L2:   storer 0, RESULT&lt;br /&gt; const2regf RESULT, fixnum(%1)&lt;br /&gt; int3 ;; debugging interrupt &lt;br /&gt; ;;; (the lack of space is significant; gdb ignores "int 3")&lt;br /&gt; add     TEMP,-BVEC_TAG+BVEC_HEADER_BYTES&lt;br /&gt; jmp     TEMP&lt;br /&gt;%%L1: lea TEMP, [RESULT+(8-PROC_TAG)]&lt;br /&gt; test TEMP_LOW, tag_mask&lt;br /&gt; jnz short %%L0&lt;br /&gt; ;; Felix inserted checks if we actually have a&lt;br /&gt; ;; fixnum here...&lt;br /&gt; mov TEMP, [TEMP-8+PROC_CODEVECTOR_NATIVE]&lt;br /&gt; test    TEMP_LOW, fixtag_mask&lt;br /&gt; jnz short %%L2&lt;br /&gt; storer 0, RESULT&lt;br /&gt; const2regf RESULT, fixnum(%1)&lt;br /&gt; jmp     TEMP&lt;/pre&gt;&lt;/font&gt;&lt;br /&gt;The heart of the hack is that invoke is now dispatching based on the kind of code pointer it got.  This should allow me to keep using Petit for the heart of the system, but still test the code in the heap directly.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;For fixnums (which are actually addresses into the text segment, but don't tell the garbage collector), we do the old invocation routine.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For bytevector pointers (which should point at codevectors in the heap), strip the tag off the pointer, then add the offset to skip over the bytevector header (on the heap object itself).  Finally, JUMP!&lt;/ul&gt;&lt;br /&gt;And, at long last, the actual result:&lt;br /&gt;&lt;font color="green"&gt;&lt;pre&gt;(gdb) r -heap sassy.heap&lt;br /&gt;Starting program: /home/pnkfelix/larcenydev/trunk/larceny_src/twobit.bin -heap sassy.heap&lt;br /&gt;(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...(no debugging symbols found)...LARCENY_ROOT not set; using current directory&lt;br /&gt;Larceny v0.91 "Children's Ice Cream" (May  2 2006 10:41:54, precise:Linux:unified)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt; (load "testsass.scm") &lt;br /&gt;&lt;br /&gt;&gt; (linked)&lt;br /&gt;&lt;br /&gt;Program received signal SIGTRAP, Trace/breakpoint trap.&lt;br /&gt;0x08342d49 in ..@6866.L2 ()&lt;br /&gt;(gdb) stepi&lt;br /&gt;0x08342d4c in ..@6866.L2 ()&lt;br /&gt;(gdb) stepi&lt;br /&gt;0x00767454 in ?? ()&lt;br /&gt;(gdb) c&lt;br /&gt;Continuing.&lt;br /&gt;321&lt;/pre&gt;&lt;/font&gt;&lt;br /&gt;Did you see it???  Did you???  That 321 at the end, that was produced by code in the &lt;em&gt;heap&lt;/em&gt;.  (Well, the &lt;em&gt;value&lt;/em&gt; was; the actual action of printing the value is still happening from code in the text segment). &lt;br /&gt;&lt;br /&gt;Woo hoo!!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-114667527970009377?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/114667527970009377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=114667527970009377' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/114667527970009377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/114667527970009377'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/05/321-contact.html' title='321 contact!'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-113884862840115375</id><published>2006-02-01T18:25:00.000-08:00</published><updated>2006-02-01T18:50:28.413-08:00</updated><title type='text'>on parallelizing a garbage collector</title><content type='html'>So here are the lessons I learned from attempting to parallelize a stop-and-copy garbage collector, as implemented in the &lt;a href="http://www.ccs.neu.edu/home/will/Larceny/"&gt;Larceny&lt;/a&gt; runtime, using &lt;a href="http://supertech.csail.mit.edu/cilk/"&gt;Cilk's&lt;/a&gt; primitives as the basis for the parallelization.&lt;br /&gt;&lt;br /&gt;At a high level, based on &lt;a href="http://research.sun.com/jtech/pubs/01-pargc.pdf"&gt;Flood's&lt;/a&gt; paper on parallel collection on SMP machines, I decided to start with a naive recursive stop-and-copy collection algorithm, and parallelize that using Cilk's spawn and sync primitives.  (The Flood paper points out the utility of a work-stealing approach to load-balancing, which the Cilk runtime gives you "for free.")&lt;br /&gt;&lt;br /&gt;Of course, the devil is in the details.  First of all, all I had to start with was an kernel collector that uses Cheney's algorithm, which is not trivial to parallelize (as far as I can tell).  So I had to develop a recursive algorithm that behaved in a manner compatible with the behavior of the Cheney collector (this is not as trivial as it sounds; the devil's in the details).&lt;br /&gt;&lt;br /&gt;Even after I developed the recursive algorithm, I discovered a new set back: the Cilk language, as currently documented, has a restriction that you can only call Cilk functions from other Cilk functions.  That is, Cilk functions can call out to C functions, but not vice versa.&lt;br /&gt;&lt;br /&gt;This immediately leads to a huge problem for Larceny, because the Scheme code is meant to be able to call into the garbage collector.  So that means that the Scheme code needs to be output as Cilk code, not C code.  And in fact, the entire runtime and compiler system needs to be shifted to use Cilk instead of C.  ACK!&lt;br /&gt;&lt;br /&gt;Luckily, the very newest version of Cilk has a beta interface for calling Cilk functions from C code.  Unluckily, the interface is indeed beta, and there were some bugs that were showstoppers for me (in hindsight, there were workarounds for the bugs, but that's neither here nor there).&lt;br /&gt;&lt;br /&gt;So, here's the important lessons from the project:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Reverse engineering is hard.  Even when you're going from a complex algorithm to a simple one, there's always details in "real systems" that get overlooked.  (For me, it was particular invariants in terms of the Cheney algorithm deliberately not traversing certain structures at certain times, and it was overloading the generation bits to control this, even though it was still relevant even for non-generational collection.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; If you want your language extension/variant A to interoperate with language B, it needs to go in both directions.  You may think it will suffice to have one layered on top of the other, but in the end, you will be wrong, and your users will hate you.  You're better off designing that interoperability in from the beginning.  (This is relevant for languages that seek to interoperate with the CLR or the JVM, in that your extension language should define classes that themselves can be invoked or extended by terms in C# or Java, respectively.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-113884862840115375?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/113884862840115375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=113884862840115375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113884862840115375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113884862840115375'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/02/on-parallelizing-garbage-collector.html' title='on parallelizing a garbage collector'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-113631250482625296</id><published>2006-01-03T10:19:00.000-08:00</published><updated>2006-01-03T10:21:44.853-08:00</updated><title type='text'>They ID'ed me 100%</title><content type='html'>&lt;TABLE align="center" cellpadding="20"&gt;    &lt;TBODY&gt;&lt;TR&gt;&lt;TD align="center"&gt;      &lt;FONT size="5"&gt;&lt;B&gt;Bourbon&lt;/B&gt;&lt;/FONT&gt;&lt;BR&gt;      Congratulations! You're 118 proof, with specific scores in beer (20) , wine (100), and liquor (78).&lt;br /&gt;     &lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;      Screw all that namby-pamby chick stuff, you're going straight for the bottle and a shot glass!  It'll take more than a few shots of Wild Turkey or 99 Bananas before you start seeing pink elephants.  You know how to handle your alcohol, and yourself at parties.     &lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD align="center"&gt;      &lt;IMG src="http://is2.okcupid.com/mt_pics/146/14674075597740859281/16336235046633759176-6.jpg"&gt;     &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;TABLE cellpadding="20"&gt; &lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;   &lt;SPAN id="comparisonarea"&gt;My test tracked 4 variables How you compared to other people &lt;I&gt;your age and gender&lt;/I&gt;:&lt;BLOCKQUOTE&gt;&lt;TABLE cellspacing="4" cellpadding="0" border="0"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD valign="middle"&gt;&lt;TABLE cellpadding="0" cellspacing="1" border="0" bgcolor="black"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD height="20" bgcolor="#b2cfff" width="45"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;TD width="105" bgcolor="white"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/TD&gt;&lt;TD valign="middle"&gt;You scored higher than &lt;B&gt;30%&lt;/B&gt; on &lt;B&gt;proof&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD valign="middle"&gt;&lt;TABLE cellpadding="0" cellspacing="1" border="0" bgcolor="black"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD height="20" bgcolor="#b2cfff" width="75"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;TD width="75" bgcolor="white"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/TD&gt;&lt;TD valign="middle"&gt;You scored higher than &lt;B&gt;50%&lt;/B&gt; on &lt;B&gt;beer index&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD valign="middle"&gt;&lt;TABLE cellpadding="0" cellspacing="1" border="0" bgcolor="black"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD height="20" bgcolor="#b2cfff" width="126"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;TD width="24" bgcolor="white"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/TD&gt;&lt;TD valign="middle"&gt;You scored higher than &lt;B&gt;84%&lt;/B&gt; on &lt;B&gt;wine index&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD valign="middle"&gt;&lt;TABLE cellpadding="0" cellspacing="1" border="0" bgcolor="black"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD height="20" bgcolor="#b2cfff" width="99"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;TD width="51" bgcolor="white"&gt;&lt;A href="http://www.okcupid.com"&gt;&lt;IMG src="http://is1.okcupid.com/graphics/0.gif" border="0" alt="free online dating"&gt;&lt;/A&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/TD&gt;&lt;TD valign="middle"&gt;You scored higher than &lt;B&gt;66%&lt;/B&gt; on &lt;B&gt;liquor index&lt;/B&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/BLOCKQUOTE&gt;&lt;/SPAN&gt;&lt;br /&gt;  &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;table cellpadding=20&gt;&lt;tr&gt;&lt;td&gt;Link: &lt;a href='http://www.okcupid.com/tests/take?testid=16336235046633759176'&gt;The Alcohol Knowledge Test&lt;/a&gt; written by &lt;a href='http://www.okcupid.com/profile?tuid=14674075597740859281'&gt;hoppersplit&lt;/a&gt; on &lt;a  href='http://www.okcupid.com'&gt;Ok Cupid&lt;/a&gt;, home of the &lt;a href='http://www.okcupid.com/oktest3'&gt;32-Type Dating Test&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-113631250482625296?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/113631250482625296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=113631250482625296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113631250482625296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113631250482625296'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2006/01/they-ided-me-100.html' title='They ID&apos;ed me 100%'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-113194129941279293</id><published>2005-11-13T20:07:00.000-08:00</published><updated>2005-11-13T20:11:46.276-08:00</updated><title type='text'>Swapping Ctrl/CapsLock (PCs or Macs!)</title><content type='html'>Someone else cares about this, and he cares enough to catalogue how to do it on all sorts of machines!&lt;br /&gt;Just go &lt;a href="http://www.manicai.net/comp/swap-caps-ctrl.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(hmm.  Actually, that was a total lie; the link above only treats windows and linux machines.  Well, &lt;a href="http://www.cv.nrao.edu/~jmalone/mac.html"&gt;this&lt;/a&gt; guys says how to do it on 10.4 machines.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-113194129941279293?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/113194129941279293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=113194129941279293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113194129941279293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113194129941279293'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/11/swapping-ctrlcapslock-pcs-or-macs.html' title='Swapping Ctrl/CapsLock (PCs or Macs!)'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-113108087901959793</id><published>2005-11-03T20:57:00.000-08:00</published><updated>2005-11-03T21:07:59.033-08:00</updated><title type='text'>some windows stuff worth knowing.</title><content type='html'>&lt;ul&gt;&lt;br /&gt;&lt;li&gt;This &lt;a href="http://www.winprog.org/tutorial/msvc.html"&gt;page&lt;/a&gt; tells you how to get &lt;i&gt;free&lt;/i&gt; copies of the command line development tools that are including in Visual Studio.  That's right, get yourself the C/C++ compiler and header files (as well as some batch scripts to set up your environment properly), all direct from Microsoft.&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&amp;DisplayLang=en"&gt;.NET Framework SDK&lt;/a&gt; (for the compiler and linker).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&amp;displaylang=en"&gt;Platform SDK&lt;/a&gt; (for the header files).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As a side note to this, I had to learn about the &lt;a href="http://www.computerhope.com/call.htm"&gt;call&lt;/a&gt; statement for DOS Batch scripts in order to learn how to make a batch file that would call each of the batch files in sequence, because each of the above SDK has a different batch file to set up the environment.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;This &lt;a href="http://www.annoyances.org/exec/forum/winxp/r1017256194"&gt;page&lt;/a&gt; tells you how to edit the Windows Registry to change the behavior of the Caps Lock key.  For a Emacs user like me, this was a crucial thing to learn, since the control key is really hard to get at on modern Windows laptops.  Speaking of which . . .&lt;/li&gt;&lt;br /&gt;&lt;li&gt;This &lt;a href="http://math.claremontmckenna.edu/ALee/emacs/emacs.html"&gt;page&lt;/a&gt; tells you how to install Emacs on a Windows machine.  It works well enough.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://x.cygwin.com/"&gt;Cygwin&lt;/a&gt;.  Nuff said.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-113108087901959793?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/113108087901959793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=113108087901959793' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113108087901959793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/113108087901959793'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/11/some-windows-stuff-worth-knowing.html' title='some windows stuff worth knowing.'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112551048429512895</id><published>2005-08-31T10:41:00.000-07:00</published><updated>2005-08-31T10:48:04.306-07:00</updated><title type='text'>GC'ing classes</title><content type='html'>.NET as far as I can tell, does not garbage collect unreachable code.  At best, you can try to manually manage the memory associated with dynamically loaded code by loading into separate &lt;code&gt;AppDomain&lt;/code&gt;s that you unload by hand.  I have not really experimented with this option.&lt;br /&gt;&lt;br /&gt;I was discussing this problem with a friend, who asserted that Java has the same problem.&lt;br /&gt;&lt;br /&gt;To prove him wrong, I wrote the following class.  You run it on the command line, passing an numeric argument that indicates the number of distinct classes you want to load.  Try it out with and without the -Xnoclassgc option in Java!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;import java.lang.Integer;&lt;br /&gt;import java.lang.ClassLoader;&lt;br /&gt;import java.lang.Class;&lt;br /&gt;import java.lang.ClassNotFoundException;&lt;br /&gt;&lt;br /&gt;public class ClassSFS {&lt;br /&gt;&lt;br /&gt;    public static void println(String s) {&lt;br /&gt;        System.out.println(s);&lt;br /&gt;    }&lt;br /&gt;    public static void println() {&lt;br /&gt;        System.out.println();&lt;br /&gt;    }&lt;br /&gt;    public static void print(String s) {&lt;br /&gt;        System.out.print(s);&lt;br /&gt;    }&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        println("Hello World");&lt;br /&gt;        int num_classes = Integer.parseInt(args[0]);&lt;br /&gt;        initbytes();&lt;br /&gt;        for(int i = 0; i &lt; num_classes; i++) {&lt;br /&gt;            &lt;br /&gt;            Tbytes[ 48 + 5 ] = (byte) (0x61 + (i/100) % 26);&lt;br /&gt;            Tbytes[ 48 + 6 ] = (byte) (0x61 + (i/10)  % 26);&lt;br /&gt;            Tbytes[ 48 + 7 ] = (byte) (0x61 + (i/1)   % 26);&lt;br /&gt;            &lt;br /&gt;            CLoader cl = new CLoader();&lt;br /&gt;            try {&lt;br /&gt;                Class c = cl.findClass("T");&lt;br /&gt;                Object x = c.newInstance();&lt;br /&gt;                System.out.println("ClassLoader "+i+", x:"+x);&lt;br /&gt;            } catch (ClassNotFoundException e) {&lt;br /&gt;                System.out.println("ClassLoader "+i+", ClassNotFound e:"+e);&lt;br /&gt;            } catch (InstantiationException e) {&lt;br /&gt;                System.out.println("ClassLoader "+i+", InstantiationException e:"+e);&lt;br /&gt;            } catch (IllegalAccessException e) {&lt;br /&gt;                System.out.println("ClassLoader "+i+", IllegalAccessException e:"+e);&lt;br /&gt;            } &lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    static class CLoader extends ClassLoader {&lt;br /&gt;        CLoader() { super(); }&lt;br /&gt;        public Class findClass(String name) throws ClassNotFoundException {&lt;br /&gt;            return &lt;br /&gt;                super.defineClass(name, &lt;br /&gt;                                  Tbytes,&lt;br /&gt;                                  0,&lt;br /&gt;                                  Tbytes.length);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    private static int[] iTbytes = {&lt;br /&gt;&lt;br /&gt;        0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x20, 0x0a, 0x00, 0x0a, 0x00, 0x16, 0x07,&lt;br /&gt;        0x00, 0x17, 0x0a, 0x00, 0x02, 0x00, 0x16, 0x08, 0x00, 0x18, 0x0a, 0x00, 0x02, 0x00, 0x19, 0x09,&lt;br /&gt;        0x00, 0x09, 0x00, 0x1a, 0x0a, 0x00, 0x02, 0x00, 0x1b, 0x08, 0x00, 0x0b, 0x07, 0x00, 0x1c, 0x07,&lt;br /&gt;        /*                               f     e     e                                              */&lt;br /&gt;        0x00, 0x1d, 0x01, 0x00, 0x03, 0x66, 0x65, 0x65, 0x01, 0x00, 0x12, 0x4c, 0x6a, 0x61, 0x76, 0x61,&lt;br /&gt;        0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3b, 0x01, 0x00, 0x06,&lt;br /&gt;        0x3c, 0x69, 0x6e, 0x69, 0x74, 0x3e, 0x01, 0x00, 0x03, 0x28, 0x29, 0x56, 0x01, 0x00, 0x04, 0x43,&lt;br /&gt;        0x6f, 0x64, 0x65, 0x01, 0x00, 0x0f, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,&lt;br /&gt;        0x54, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, 0x08, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,&lt;br /&gt;        0x01, 0x00, 0x14, 0x28, 0x29, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,&lt;br /&gt;        0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3b, 0x01, 0x00, 0x08, 0x3c, 0x63, 0x6c, 0x69, 0x6e, 0x69,&lt;br /&gt;        0x74, 0x3e, 0x01, 0x00, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01,&lt;br /&gt;        0x00, 0x06, 0x54, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x01, 0x00, 0x16,&lt;br /&gt;        0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,&lt;br /&gt;        0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x01, 0x00, 0x03, 0x54, 0x3c, 0x3e, 0x0c, 0x00, 0x1e, 0x00,&lt;br /&gt;        0x1f, 0x0c, 0x00, 0x0b, 0x00, 0x0c, 0x0c, 0x00, 0x11, 0x00, 0x12, 0x01, 0x00, 0x01, 0x54, 0x01,&lt;br /&gt;        0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65,&lt;br /&gt;        0x63, 0x74, 0x01, 0x00, 0x06, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x01, 0x00, 0x2c, 0x28, 0x4c,&lt;br /&gt;        0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,&lt;br /&gt;        0x3b, 0x29, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x53, 0x74, 0x72,&lt;br /&gt;        0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x3b, 0x00, 0x21, 0x00, 0x09, 0x00, 0x0a,&lt;br /&gt;        0x00, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01,&lt;br /&gt;        0x00, 0x0d, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x01,&lt;br /&gt;        0x00, 0x00, 0x00, 0x05, 0x2a, 0xb7, 0x00, 0x01, 0xb1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00,&lt;br /&gt;        0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x12, 0x00,&lt;br /&gt;        0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0xbb,&lt;br /&gt;        0x00, 0x02, 0x59, 0xb7, 0x00, 0x03, 0x12, 0x04, 0xb6, 0x00, 0x05, 0xb2, 0x00, 0x06, 0xb6, 0x00,&lt;br /&gt;        0x05, 0xb6, 0x00, 0x07, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00,&lt;br /&gt;        0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x13, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x0f, 0x00,&lt;br /&gt;        0x00, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x12, 0x08, 0xb3, 0x00, 0x06,&lt;br /&gt;        0xb1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,&lt;br /&gt;        0x02, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x15&lt;br /&gt;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    private static byte[] Tbytes;&lt;br /&gt;&lt;br /&gt;    public static void initbytes()&lt;br /&gt;    { &lt;br /&gt;        Tbytes = new byte[ iTbytes.length  ];&lt;br /&gt;        for(int i = 0; i &lt; iTbytes.length; i++) {&lt;br /&gt;            Tbytes[i] = (byte)(iTbytes[i]);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        print(""+nybble2char((Tbytes[0]&gt;&gt;4) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[0]&gt;&gt;0) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[1]&gt;&gt;4) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[1]&gt;&gt;0) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[2]&gt;&gt;4) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[2]&gt;&gt;0) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[3]&gt;&gt;4) &amp; 0xF));&lt;br /&gt;        print(""+nybble2char((Tbytes[3]&gt;&gt;0) &amp; 0xF));&lt;br /&gt;        println();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    private static char nybble2char(int b) {&lt;br /&gt;        switch (b) {&lt;br /&gt;        case 0xf: return 'f';&lt;br /&gt;        case 0xe: return 'e';&lt;br /&gt;        case 0xd: return 'd';&lt;br /&gt;        case 0xc: return 'c';&lt;br /&gt;        case 0xb: return 'b';&lt;br /&gt;        case 0xa: return 'a';&lt;br /&gt;        default: return (char) (b+'a');&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static int Tcounter = 0;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The iTbytes array was generated by compiling &lt;code&gt;public class T { private static String fee = "fee"; public String toString() { return "T&lt;&gt;"+fee; }}&lt;/code&gt;, then loading the resulting class file into emacs, switching to hexl-mode, and doing some keyboard-macrology to convert it to something &lt;code&gt;javac&lt;/code&gt; would accept.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112551048429512895?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112551048429512895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112551048429512895' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112551048429512895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112551048429512895'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/gcing-classes.html' title='GC&apos;ing classes'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112499708792115750</id><published>2005-08-25T11:49:00.000-07:00</published><updated>2005-08-25T12:11:27.926-07:00</updated><title type='text'>C#, pass-by-value, pass-by-reference</title><content type='html'>Here's a nice little snippet of C# for you.&lt;pre&gt;using System;&lt;br /&gt;&lt;br /&gt;namespace InterfaceSample {&lt;br /&gt;  public delegate void Changed();&lt;br /&gt;  interface IPoint {&lt;br /&gt;    int X { get; set; }&lt;br /&gt;    int Y { get; set; }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  struct Point: IPoint {&lt;br /&gt;    private int xValue, yValue;&lt;br /&gt;    public int X { get { return xValue; } set { xValue = value; } }&lt;br /&gt;    public int Y { get { return yValue; } set { yValue = value; } }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public class EntryPoint {&lt;br /&gt;    public static int Main() {&lt;br /&gt;      String formatstr = "  p1.X: {0}, p1.Y: {1}, p2.X: {2}, p2.Y: {3} ip1.X: {4}, ip1.Y: {5}, ip2.X: {6}, ip2.Y: {7}";&lt;br /&gt;&lt;br /&gt;      Point p1 = new Point();&lt;br /&gt;      p1.X = p1.Y = 42;&lt;br /&gt;      IPoint ip1 = p1;&lt;br /&gt;      Point p2 = (Point) ip1;&lt;br /&gt;      IPoint ip2 = ip1;&lt;br /&gt;&lt;br /&gt;      Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);&lt;br /&gt;      p1.X = p1.Y = 21; Console.WriteLine("p1.X = p1.Y = 21;");&lt;br /&gt;      Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);&lt;br /&gt;      ip1.X = ip1.Y = 84; Console.WriteLine("ip1.X = ip1.Y = 84;");&lt;br /&gt;      Console.WriteLine(formatstr, p1.X, p1.Y, p2.X, p2.Y, ip1.X, ip1.Y, ip2.X, ip2.Y);&lt;br /&gt;      return 0;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;In C#, classes and interfaces can have properties, which have usage syntax similar to fields but semantics similar to methods.  In the interface, you just declare the property name and whether it has getters/setters; in the class, you then define the behavior you want for the property.&lt;br /&gt;&lt;br /&gt;In C#, you can declare struct types, which are value types in the language.  This means that they are passed by value.  However, they are &lt;b&gt;not&lt;/b&gt; immutable.&lt;br /&gt;&lt;br /&gt;In C#, a struct type can implement an interface.  Ah, what fun.&lt;br /&gt;&lt;br /&gt;Here's the output of the above program: &lt;pre&gt;  p1.X: 42, p1.Y: 42, p2.X: 42, p2.Y: 42 ip1.X: 42, ip1.Y: 42, ip2.X: 42, ip2.Y: 42&lt;br /&gt;p1.X = p1.Y = 21;&lt;br /&gt;  p1.X: 21, p1.Y: 21, p2.X: 42, p2.Y: 42 ip1.X: 42, ip1.Y: 42, ip2.X: 42, ip2.Y: 42&lt;br /&gt;ip1.X = ip1.Y = 84;&lt;br /&gt;  p1.X: 21, p1.Y: 21, p2.X: 42, p2.Y: 42 ip1.X: 84, ip1.Y: 84, ip2.X: 84, ip2.Y: 84&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The mutation to &lt;code&gt;p&lt;/code&gt;'s properties is not propagated over to &lt;code&gt;ip&lt;/code&gt;, which looks odd to a Java programmer like me.  This is because the assignment &lt;code&gt;ip1 = p1&lt;/code&gt; makes a &lt;b&gt;copy&lt;/b&gt; of &lt;code&gt;p1&lt;/code&gt; when it "boxes" it into &lt;code&gt;ip1&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;And even odder, given the previous paragraph, the mutations to ip1 &lt;b&gt;are&lt;/b&gt; carried over to &lt;code&gt;ip2&lt;/code&gt;.  Actually, this isn't so odd, since &lt;code&gt;ip1&lt;/code&gt; is an interface after all, that might ("must", considering boxing?) be implemented by an object, and therefore the assignment must copy a reference to the object.&lt;br /&gt;&lt;br /&gt;Finally, you can copy from the interface back to a &lt;code&gt;Point&lt;/code&gt;, but this requires a cast.  This makes sense (see previous paragraph).&lt;br /&gt;&lt;br /&gt;In the end, I don't think I have a big problem with value types. Its just the &lt;b&gt;mutable&lt;/b&gt; value types that I get nervous about, because then you actually need to start thinking about the copy/reference semantics.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112499708792115750?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112499708792115750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112499708792115750' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112499708792115750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112499708792115750'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/c-pass-by-value-pass-by-reference.html' title='C#, pass-by-value, pass-by-reference'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112368320523188797</id><published>2005-08-10T07:08:00.000-07:00</published><updated>2005-08-10T07:16:03.710-07:00</updated><title type='text'>old stack based languages</title><content type='html'>We all know that I've been looking at &lt;a href="http://www.forth.com/resources/evolution/"&gt;Forth&lt;/a&gt; to digest its approach to allowing powerful compile-time constructions.&lt;br /&gt;&lt;br /&gt;Fare, an LL-discuss member, mentioned &lt;a href="http://www.poplog.org/docs/poplog.info.html"&gt;POP-11&lt;/a&gt; as an alternative to Forth (that might be even older).  It seems to also have the ability to define compile-time programs; it remains to be seen how it compares to Forth (or Lisp/Scheme, for that matter). &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;heh&lt;/h4&gt;&lt;br /&gt;I just realized that my use of "We all know" up above is completely unfounded, because I didn't bother to blog during the month of July, which was when I was investigating Forth so heavily.  I suppose I should finish the investigation (or at least both the books from the library) and write something up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112368320523188797?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112368320523188797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112368320523188797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112368320523188797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112368320523188797'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/old-stack-based-languages.html' title='old stack based languages'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112365791713777561</id><published>2005-08-10T00:02:00.000-07:00</published><updated>2005-08-10T00:11:57.163-07:00</updated><title type='text'>rules for intermediate representations</title><content type='html'>And the muse of compiler development did rise from her murky swamp, and did say unto the Larceny developers, "Thou shalt not convert your aye-arrh into object form, be it string, bytecode, or otherwise, until the last possible moment."&lt;br /&gt;&lt;br /&gt;The Larceny developers did take exception to this rule, pleading "but we have chosen an invertible object form, from which the most exhalted client developer may extract the original structured aye-arrh.  Its strings are formatted thusly, isomorphic to the structure of the input, and thus less painful for my mortal eyes to gaze upon than the radiance of the aye-arrh structure itself."&lt;br /&gt;&lt;br /&gt;To this, the muse of compiler development rules responds, "verily, you might take such a path; but then you must also provide such inversion functions, and not place the onus of developing such functions upon the shoulders of the most exhalted client developer, who is already fed up with trying to make sense of your underspecified and confusingly named interfaces.&lt;br /&gt;&lt;br /&gt;Here endeth the lesson.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112365791713777561?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112365791713777561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112365791713777561' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112365791713777561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112365791713777561'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/rules-for-intermediate-representations.html' title='rules for intermediate representations'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112319703196351920</id><published>2005-08-04T16:01:00.000-07:00</published><updated>2005-08-04T16:55:46.330-07:00</updated><title type='text'>On Macros and JavaDot</title><content type='html'>Tonight I made a fun macro that tries to cut down on the verbosity when you refer to classes using Javadot; normally you have to explicit write out the full name with all the package prefixes.  What I want is to introduce a nice shorthand, similar to the shorthand introduced by the &lt;code&gt;import&lt;/code&gt; statement in Java.&lt;br /&gt;&lt;br /&gt;Here is the macro: &lt;pre&gt;;; (let/import ((X Y Z1 Z2 ...)) BODY ...) binds Y.Z1, Y.Z2, ... to&lt;br /&gt;;; the expressions X.Y.Z1, X.Y.Z2, ..., and naturally generalizes to&lt;br /&gt;;; more than one prefix X.&lt;br /&gt;;; As one special case, if Zn is (), then that means import the constructor&lt;br /&gt;;; X.Y. as the name Y. (note the period on the end).&lt;br /&gt;(define-syntax let/import&lt;br /&gt;  (transformer (lambda (stx ren cmp)&lt;br /&gt;   (let ((bindings (cadr stx))&lt;br /&gt;         (body (cddr stx))&lt;br /&gt;         (construct-new-bindings &lt;br /&gt;   (lambda (binding)&lt;br /&gt;     (let* ((-&gt;s (lambda (x)&lt;br /&gt;     (if (null? x)&lt;br /&gt;         ""&lt;br /&gt;         (symbol-&gt;string x))))&lt;br /&gt;     (prefix (-&gt;s (car binding)))&lt;br /&gt;     (middle (-&gt;s (cadr binding)))&lt;br /&gt;     (suffixes (map -&gt;s (cddr binding)))&lt;br /&gt;     (s-&gt;/append (lambda l &lt;br /&gt;            (string-&gt;symbol (apply string-append l))))&lt;br /&gt;     (make-binding (lambda l&lt;br /&gt;       (list (apply s-&gt;/append l)&lt;br /&gt;             (symbol-&gt;javadot-symbol&lt;br /&gt;       (apply s-&gt;/append prefix "." l))))))&lt;br /&gt;       (map (lambda (suffix) (make-binding middle "." suffix))&lt;br /&gt;     suffixes)))))&lt;br /&gt;     `(,(ren 'let) (,@(apply append (map construct-new-bindings bindings))) &lt;br /&gt;       ,@body)))))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This pretty much works.&lt;br /&gt;&lt;br /&gt;However, using it seems to have exposed what I'd call a bug in how Common Larceny's macro expander interacts with Javadot.&lt;br /&gt;&lt;br /&gt;Watch this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; (let () System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave$)&lt;br /&gt;#&amp;lt;procedure of 0 arguments&amp;gt;&lt;br /&gt;&lt;br /&gt;&gt; (let () System.Reflection.Emit.AssemblyBuilderAccess.Run$)&lt;br /&gt;#&amp;lt;procedure of 0 arguments&amp;gt;&lt;br /&gt;&lt;br /&gt;&gt; (let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) AssemblyBuilderAccess.RunAndSave$)&lt;br /&gt;#&amp;lt;procedure of 0 arguments&amp;gt;&lt;br /&gt;&lt;br /&gt;&gt; (let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) System.Reflection.Emit.AssemblyBuilderAccess.Run$)&lt;br /&gt;#&amp;lt;procedure of 0 arguments&amp;gt;&lt;br /&gt;&lt;br /&gt;&gt; (let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave$)&lt;br /&gt;&lt;br /&gt;Error: Reference to undefined global variable "system.reflection.emit.assemblybuilderaccess.runandsave$".&lt;br /&gt;&lt;br /&gt;&gt; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;What huppen!?!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I dunno, but Ryan and I tried looking at the expanded output:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; (macro-expand '(let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) System.Reflection.Emit.AssemblyBuilderAccess.Run$))&lt;br /&gt;((lambda () ((lambda (.assemblybuilderaccess.runandsave$|4) (clr/find-static-field-getter '#f 'system.reflection.emit.assemblybuilderaccess.run)) (clr/find-static-field-getter '#f 'system.reflection.emit.assemblybuilderaccess.runandsave))))&lt;br /&gt;&lt;br /&gt;&gt; (macro-expand '(let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) AssemblyBuilderAccess.RunAndSave$))&lt;br /&gt;((lambda () ((lambda (.assemblybuilderaccess.runandsave$|4) .assemblybuilderaccess.runandsave$|4) (clr/find-static-field-getter '#f 'system.reflection.emit.assemblybuilderaccess.runandsave))))&lt;br /&gt;&lt;br /&gt;&gt; (macro-expand '(let/import ((System.Reflection.Emit AssemblyBuilderAccess RunAndSave$)) System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave$))&lt;br /&gt;((lambda () ((lambda (.assemblybuilderaccess.runandsave$|4) (clr/find-static-field-getter '#f 'system.reflection.emit.assemblybuilderaccess.runandsave)) system.reflection.emit.assemblybuilderaccess.runandsave$)))&lt;br /&gt;&lt;br /&gt;&gt; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Update&lt;/h3&gt;&lt;br /&gt;It turns out this isn't even a problem with Macros; it looks like its just a bug in our JavaDot implementation when you refer to the same identifier more than once.  E.g.: &lt;pre&gt;&gt; (begin (display System.String.class) (display System.String.class))&lt;br /&gt;#&amp;lt;System.RuntimeType System.String&amp;gt;&lt;br /&gt;Error: Reference to undefined global variable "system.string.class".&lt;/pre&gt;  So much for getting excited about some strange new bug...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112319703196351920?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112319703196351920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112319703196351920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112319703196351920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112319703196351920'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/on-macros-and-javadot.html' title='On Macros and JavaDot'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112309990508253354</id><published>2005-08-03T12:41:00.000-07:00</published><updated>2005-08-03T13:12:35.606-07:00</updated><title type='text'>Tales from the Larceny source: Eta the Ultimate</title><content type='html'>&lt;blockquote&gt;&lt;br /&gt;; Note: the idiom that is seen in this file,&lt;br /&gt;;   &lt;code&gt;(emit-fixup-proc! as (lambda (b l) (fixup b l)))&lt;/code&gt;&lt;br /&gt;; when `fixup' is a local procedure, avoids allocation of the closure&lt;br /&gt;; except in the cases where the fixup is in fact needed, for gains in&lt;br /&gt;; speed and reduction in allocation.  (Ask me if you want numbers.)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I didn't understand this note in &lt;code&gt;sparcasm.sch&lt;/code&gt; when I read it a week or so ago, so I asked Will to explain it to me.  Here is what I got out of the explanation.&lt;br /&gt;&lt;br /&gt;The code is something like:&lt;pre&gt;(define (foo as x)&lt;br /&gt;   (define (fixup bv loc) &lt;em&gt;--omitted--&lt;/em&gt;)&lt;br /&gt;   (if (usually-true)&lt;br /&gt;       (bar)&lt;br /&gt;       (emit-fixup-proc! as (lambda (b l) (fixup b l)))))&lt;/pre&gt;The idea here is that we know all the points where &lt;code&gt;fixup&lt;/code&gt; is used, and it is being invoked at each one.  Thus, &lt;code&gt;fixup&lt;/code&gt; qualifies as a "known local procedure.", and we can compile it directly to a sequence of machine code instructions in the current text segment, and make it just another label in the compiled machine code for &lt;code&gt;foo&lt;/code&gt; that we can jump to. &lt;br /&gt;&lt;br /&gt;If we hadn't eta-expanded the reference to &lt;code&gt;fixup&lt;/code&gt;, a la:&lt;pre&gt;(define (foo as x)&lt;br /&gt;   (define (fixup bv loc) &lt;em&gt;--omitted--&lt;/em&gt;)&lt;br /&gt;   (if (usually-true)&lt;br /&gt;       (bar)&lt;br /&gt;       (emit-fixup-proc! as fixup)))&lt;/pre&gt;then &lt;code&gt;fixup&lt;/code&gt; is no longer a "known local procedure", because we cannot tell what &lt;code&gt;emit-fixup-proc!&lt;/code&gt; will do with it (e.g. it may store it into a global variable which will later be invoked), and therefore in this latter case, we will conservatively generate a closure object and bind that to &lt;code&gt;fixup&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;In the former case, we also generate a closure object for the whole lambda expression, but we only generate this object on the uncommon control flow path; &lt;code&gt;fixup&lt;/code&gt; itself is a free variable referenced by the closure, and therefore remains a simple label in the machine code text of &lt;code&gt;foo&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;This leads to a few questions, none of which I thought of in time to ask Will about them: &lt;ol&gt;&lt;li&gt;Couldn't we have acheived the same effect (but without eta-expanding) by pushing the definition of &lt;code&gt;fixup&lt;/code&gt; down closer to its use?  &lt;ul&gt;&lt;li&gt;Quesswork answer: yes, but in the real source tree, &lt;code&gt;fixup&lt;/code&gt; is actually referenced multiple times.  Even then, one might be able to get away with cloning the definition and pushing the seperate clones down, but now you have to trade off the blow up in static code size versus the cost of allocating the closure at runtime.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;What about an optimization pass to automatically introduce eta expansions on references like these to otherwise known local procedures? &lt;ul&gt;&lt;li&gt;Quesswork answer: well, note here we rely on a human provided assurance as to what the common code path is.  If it were more common to take the other route, then I don't think eta-expansion would be a win anymore.  What kind of performance hit could such a transformation introduce then?&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;What about optimizing whatever is introducing the code for the allocation of the closure for &lt;code&gt;fixup&lt;/code&gt;, so that the introduced code doesn't allocate until  it absolutely must (due to data-dependency requirements, either by a use of &lt;code&gt;fixup&lt;/code&gt; or a mutation of some data that the construction of &lt;code&gt;fixup&lt;/code&gt; requires)? &lt;ul&gt;&lt;li&gt;I dunno.  Sounds tricky.  Also note that this is pretty similar to (1.) above, except applied at a lower level than Scheme source.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112309990508253354?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112309990508253354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112309990508253354' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112309990508253354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112309990508253354'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/08/tales-from-larceny-source-eta-ultimate.html' title='Tales from the Larceny source: Eta the Ultimate'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112013397436483631</id><published>2005-06-30T05:19:00.000-07:00</published><updated>2005-06-30T05:19:58.016-07:00</updated><title type='text'>I am . . .</title><content type='html'>&lt;a href="http://blogsurvey.media.mit.edu/request"&gt;&lt;img src="http://blogsurvey.media.mit.edu/images/survey-statistic.gif" alt="Take the MIT Weblog Survey" style="border:none" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112013397436483631?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112013397436483631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112013397436483631' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112013397436483631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112013397436483631'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/i-am.html' title='I am . . .'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112004121333149411</id><published>2005-06-29T03:29:00.000-07:00</published><updated>2005-06-29T03:33:33.333-07:00</updated><title type='text'>bonus (dfw) !</title><content type='html'>And as an added bonus, &lt;a href="http://www.marginalia.org/dfw_kenyon_commencement.html"&gt;here&lt;/a&gt; is pretty good commencement speech by David Foster Wallace.  Its no "Wear Sunscreen", in that I don't see it being put to music and put on VH1 anytime soon, but its probably bettter than "No Sex in the Champagne Room."&lt;br /&gt;&lt;br /&gt;David Foster Wallace, in case you didn't know, is the author of Infinite Jest, a book which I'm still not sure whether was worth finishing (other than to be able to say at dinner, "I finished Infinite Jest.", which is a great test of the people you're talking to, because the right response to this statement really is "Why?").&lt;br /&gt;&lt;br /&gt;He has other books as well ("Interviews with hideous men") but those didn't grab me (and drop me) in the same way that Infinite Jest did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112004121333149411?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112004121333149411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112004121333149411' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112004121333149411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112004121333149411'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/bonus-dfw.html' title='bonus (dfw) !'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-112004051466145199</id><published>2005-06-29T03:18:00.000-07:00</published><updated>2005-06-29T03:21:54.666-07:00</updated><title type='text'>self and virtual types</title><content type='html'>I've been listening on discussions in the lab lately on handling self types.  Sam mentioned something called virtual types.  I know nothing about them.&lt;br /&gt;&lt;br /&gt;However, I happened to run into an &lt;a href="http://pauillac.inria.fr/~remy/work/virtual/index.html"&gt;article&lt;/a&gt; by Remy and Vouillon arguing that virtual types (or at least common uses of virtual types) do not need special treatment in O'Caml, and gives some example code.&lt;br /&gt;&lt;br /&gt;So I want to go back over the article later and really digest what is going on.  I followed the argument as presented when I read it directly, but I'm feeling I may have missed the point when they were talking about camels at the end.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-112004051466145199?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/112004051466145199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=112004051466145199' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112004051466145199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/112004051466145199'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/self-and-virtual-types.html' title='self and virtual types'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111931153160172156</id><published>2005-06-20T16:45:00.000-07:00</published><updated>2005-06-20T16:52:11.656-07:00</updated><title type='text'>larceny unleashed</title><content type='html'>Last week, Will finally decided it was time to "release" Petit &lt;a href="http://www.larceny.org/"&gt;Larceny&lt;/a&gt; (as well as the latest build for Native Larceny).&lt;br /&gt;&lt;br /&gt;I don't have much else to add to the subject.  (other than its not really what anyone is willing to call a formal release; Will calls it a "Developer's Alpha", and I call it "Potentially Unembarressing")&lt;br /&gt;&lt;br /&gt;However, it is nice that we've hit this stage.  &lt;br /&gt;&lt;br /&gt;Next items on my agenda:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Finish term paper on "Computability and Complexity of Type Inference" (this mostly consists of poking &lt;a href="http://ccedevdiary.blogspot.com/"&gt;Carl&lt;/a&gt; with progressively larger sticks).&lt;/li&gt;&lt;li&gt;Finish getting NASM support working for Larceny on win32 platforms (so that we can release for windows as well as the current Mac OS X and Sparc).&lt;/li&gt;&lt;li&gt;Merge the Common Larceny and Petit Larceny (aka &lt;code&gt;release_2&lt;/code&gt;) source branches in the CVS repository.&lt;/li&gt;&lt;li&gt;Start planning out how to implement the Garbage First collector in Larceny's runtime.&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111931153160172156?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111931153160172156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111931153160172156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111931153160172156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111931153160172156'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/larceny-unleashed.html' title='larceny unleashed'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111896025107109585</id><published>2005-06-16T15:13:00.000-07:00</published><updated>2005-06-16T15:17:31.076-07:00</updated><title type='text'>garbage collection in cylone</title><content type='html'>I just read a nice lil' &lt;a href="http://www.cs.cornell.edu/people/fluet/safe-runtime/"&gt;paper&lt;/a&gt; that gives me hope for my own research.&lt;br /&gt;&lt;br /&gt;It sounds like they put a region system to good use in developing a simple two-space garbage collector.&lt;br /&gt;&lt;br /&gt;However, this &lt;a href="http://www.kimbly.com/blog/000325.html"&gt;blog&lt;/a&gt; entry indicates that they haven't figured out how to do a generational collector yet, and that they think it might require dependent types.  Yowza.  I've been thinking about the problem as well, but I never got to the point where it seemed like something that sophisticated would be required. . .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111896025107109585?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111896025107109585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111896025107109585' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111896025107109585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111896025107109585'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/garbage-collection-in-cylone.html' title='garbage collection in cylone'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111832983003935869</id><published>2005-06-09T08:08:00.000-07:00</published><updated>2005-06-09T08:10:30.043-07:00</updated><title type='text'>before you die, i'd like to. . .</title><content type='html'>&lt;a href="http://borkware.com/miniblog/one-entry?entry%5fid=41444"&gt;Here&lt;/a&gt; is a page of links on PowerPC assembly programming.&lt;br /&gt;&lt;br /&gt;Yeah, I've taken my sweet time getting around to learning ppc asm, so now one must wonder, "why bother?"&lt;br /&gt;&lt;br /&gt;No answer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111832983003935869?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111832983003935869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111832983003935869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111832983003935869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111832983003935869'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/before-you-die-id-like-to.html' title='before you die, i&apos;d like to. . .'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111832632636930927</id><published>2005-06-09T07:09:00.000-07:00</published><updated>2005-06-09T07:12:06.373-07:00</updated><title type='text'>apple, suicide, and analogies</title><content type='html'>&lt;a href="http://projects.csail.mit.edu/gsb/archives/old/gsb-archive/gsb2001-06-29.html"&gt;This&lt;/a&gt; is a "fun" posting from 2001.&lt;br /&gt;&lt;br /&gt;No, the analogy doesn't entirely stand up on its own.  But its still worth considering.&lt;br /&gt;&lt;br /&gt;The other issue that some people are talking about is DRM.  Is that a driving issue?  Its certainly not one that Steve Jobs was willing to mention on stage.  Maybe its just paranoia.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111832632636930927?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111832632636930927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111832632636930927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111832632636930927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111832632636930927'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/apple-suicide-and-analogies.html' title='apple, suicide, and analogies'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111808236502448864</id><published>2005-06-06T11:23:00.000-07:00</published><updated>2005-06-06T11:26:09.746-07:00</updated><title type='text'>"i for one welcome our new intel overlords"</title><content type='html'>. . . but not really.&lt;br /&gt;&lt;br /&gt;Yep, Apple is going to be a &lt;a href="http://www.apple.com/pr/library/2005/jun/06intel.html"&gt;Switcher&lt;/a&gt;.  And I'm somewhat pissed about it.&lt;br /&gt;&lt;br /&gt;I really had bought into the argument that RISC processors were the right solution for the long term, and that PowerPC was more scalable than Intel, etc etc.  If nothing else, Intel processors meager register set &lt;b&gt;really&lt;/b&gt; sucks.&lt;br /&gt;&lt;br /&gt;Perhaps the worst thing is that it is going to be very hard to convince anyone to buy a new mac for the next year, at least.  Sigh.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111808236502448864?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111808236502448864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111808236502448864' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111808236502448864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111808236502448864'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/06/i-for-one-welcome-our-new-intel.html' title='&quot;i for one welcome our new intel overlords&quot;'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111712328334071403</id><published>2005-05-26T08:37:00.000-07:00</published><updated>2005-05-26T09:01:23.350-07:00</updated><title type='text'>The power set axiom and the specification schema</title><content type='html'>Some people at the lab know that I occasionally (half-jokingly) question the existence of the real numbers and the (informal) validity of a set of axioms that imply that the reals exist.&lt;br /&gt;&lt;br /&gt;Most recently I had pinned this down to the powerset axiom in Zermelo set theory.  The powerset axiom is: "For any set z, there is a set whose members are just the subsets of z."  [ forall z exists y forall x (x in y iff forall w ( w in x implies w in z )) ].&lt;br /&gt;&lt;br /&gt;Let me be clear here: I have no problem with the powerset operator being applied to finite sets.  I definitely see that for any finite set z, the powerset of z is easily constructed.  The questionable part is: why should I believe that the powerset operator is applicable to infinite sets?  Given the set of natural numbers N, if we allow the existance of its powerset, 2^N, then there are elements of 2^N that cannot be described by a finite piece of text.  Why should we assume that such sets exist?&lt;br /&gt;&lt;br /&gt;I recently picked up Boolos' book, "Logic, Logic, and Logic", again, and started looking there for answers to questions I've been having recently about Linear Logic.  The first chapter presents "The Iterative Conception of Set", where Boolos describes a staged model for constructing the sets described by Zermelo's axioms (which include the powerset axiom above).&lt;br /&gt;&lt;br /&gt;There are a lot of rules for building up these stages, but most of them are straightforward and believable.  I skimmed them over, said "okay", and moved on to the next section, which argues that the axioms of Zermelo Set theory follow from the rules given for building the stages.   This includes the Powerset axiom; so I was naturally interested in reading this more carefully.&lt;br /&gt;&lt;br /&gt;The derivation of the Powerset axiom hinges on the truth of the "specification axioms" of the staged model.  When I saw that, I said, "okay, I missed the details of the specification axioms, lets revisit it. . ."  It is actually a &lt;em&gt;schema&lt;/em&gt; describing an infinite set of formulas that we take as axioms.  It is phrased as follows: &lt;br /&gt;&lt;br /&gt;"forall s exists y forall x (x in y iff [X] and exists t (t earlierThan s and x formedAt t)))"&lt;br /&gt;where [X] is a formula of in which no occurrence of "y" is free.&lt;br /&gt;&lt;br /&gt;As Boolos puts it, "any such axiom will say that for any stage there is a set of just those sets to which [X] applies that are formed before that stage.  Let us call these axioms &lt;em&gt;specification axioms&lt;/em&gt;."&lt;br /&gt;&lt;br /&gt;To derive the powerset axiom, one starts with the specification axiom:&lt;br /&gt;"forall s exists y forall x (x in y iff (forall w (w in x implies w in z) and exists t (t earlierThan s and x formedAt t)))"&lt;br /&gt;which is the same as the above with [X] := "forall w (w in x implies w in z)".  This specification axiom says "for any stage, there is a set of all subsets of z formed at earlier stages."  (the argument continues from there, but I don't want to relay the remainder of it at this point.)&lt;br /&gt;&lt;br /&gt;z is free in the above specification axioms.  So it seems that we're actually going to be employing an infinite number of the specification axioms to argue that the powerset axiom is true, since the powerset axiom is quantified over all z; is this okay?  Plus, I'm no longer so sure that it is sensible to put no constraints on [X] other than that no occurrence of "y" be free in [X].  &lt;br /&gt;&lt;br /&gt;But these are pretty flimsy questions; and that's a good thing for me, because it means that I'm narrowing down my uneasiness about the powerset axiom into more bite-size chunks that I can process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111712328334071403?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111712328334071403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111712328334071403' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111712328334071403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111712328334071403'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/05/power-set-axiom-and-specification.html' title='The power set axiom and the specification schema'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111691875533460036</id><published>2005-05-23T22:13:00.001-07:00</published><updated>2005-05-24T08:38:23.746-07:00</updated><title type='text'>Linear Logic (with urls!)</title><content type='html'>&lt;a href="http://iml.univ-mrs.fr/~girard/linear.pdf"&gt;Girard, 1987&lt;/a&gt;.  Very hard to read.  Found on &lt;br /&gt;Girard's &lt;a href="http://iml.univ-mrs.fr/~girard/Articles.html"&gt;pubs&lt;/a&gt; page.  &lt;a href="http://iml.univ-mrs.fr/~girard/Synsem.pdf.gz"&gt;Girard, 1995&lt;/a&gt; has a significantly lower barrier to entry.&lt;br /&gt;&lt;br /&gt;Lafont's &lt;a href="http://iml.univ-mrs.fr/~lafont/papers.html"&gt;collection&lt;/a&gt;.  The only one I've skimmed is a Linear Abstract Machine, which isn't even downloadable there.&lt;br /&gt;&lt;br /&gt;Another &lt;a href="http://www-2.cs.cmu.edu/~carsten/linearbib/llb.html"&gt;collection&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wadler's &lt;a href="http://homepages.inf.ed.ac.uk/wadler/topics/linear-logic.html"&gt;collection&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111691875533460036?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111691875533460036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111691875533460036' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111691875533460036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111691875533460036'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/05/linear-logic-with-urls_23.html' title='Linear Logic (with urls!)'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111669603227216343</id><published>2005-05-21T10:19:00.000-07:00</published><updated>2005-05-21T10:20:32.276-07:00</updated><title type='text'>mailman, the return</title><content type='html'>As the subject indicates, I had a brief reencounter with a &lt;a href=http://pnkfif.blogspot.com/2005/04/mailman-postfix-and-pain.html&gt;prior post&lt;/a&gt; today.&lt;br /&gt;&lt;br /&gt;Short version of story (which is all I have time for today): when in doubt, check that the qrunner daemon has actually been started.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111669603227216343?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111669603227216343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111669603227216343' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111669603227216343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111669603227216343'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/05/mailman-return.html' title='mailman, the return'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111639643523716278</id><published>2005-05-17T22:57:00.000-07:00</published><updated>2005-05-18T12:41:36.366-07:00</updated><title type='text'>dlopen on win32 ?</title><content type='html'>I spent today getting &lt;a href="http://www.ccs.neu.edu/home/will/Larceny/"&gt;Larceny&lt;/a&gt; to build on Cygwin.  After I finished getting something that seemd to evaluate simple Scheme expressions, I tried dynamic loading.  And it didn't work.&lt;br /&gt;&lt;br /&gt;So at last I realized that I had been misinterpreting many of Lars' statements: dynamic loading doesn't work &lt;b&gt;at all&lt;/b&gt; on Windows (even under Cygwin, which was the key bit I was missing).&lt;br /&gt;&lt;br /&gt;Thus began a huge quest to figure out how dynamic loading works on Windows.  Ha.  Ha.  Ha.&lt;br /&gt;&lt;br /&gt;Here are some links I've found trying to explain it to Unix-heads like myself (or just looked interesting as I browsed over the Google output).&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/win32.html"&gt;ld and WIN32 (cygwin/mingw)&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://cphoenix.best.vwh.net/winvunix.html"&gt;Windows vs Unix linking dynamic module&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.iecc.com/linker/linker10.html"&gt;Dynamic Linking and Loading&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://list-archive.xemacs.org/xemacs-beta/199809/msg00328.html"&gt;Re: Need internal help please (dynamic loading support)&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://edll.sourceforge.net/"&gt;Enhanced Dynamic Linking for MS-Windows&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.linuxjournal.com/article/3687"&gt;Dynamic Class Loading for C++ on Linux&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/C++-dlopen-mini-HOWTO.html"&gt;C++ dlopen mini HOWTO&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.franz.com/support/documentation/7.0/doc/main.htm"&gt;User defined main()&lt;/a&gt;&lt;br /&gt;&lt;li&gt; &lt;a href="http://www.zsh.org/mla/workers/2000/msg03245.html"&gt;RE: Dynamic loading on Cygwin - status&lt;/a&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I think I need to pay special attention to the "Gimp" solution documented on the &lt;a href="http://edll.sourceforge.net/"&gt;EDLL&lt;/a&gt; page; I don't mind writing a .def file that has all the millicode routines listed in it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111639643523716278?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111639643523716278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111639643523716278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111639643523716278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111639643523716278'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/05/dlopen-on-win32.html' title='dlopen on win32 ?'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111593840961624938</id><published>2005-05-12T15:52:00.000-07:00</published><updated>2005-05-12T16:02:56.150-07:00</updated><title type='text'>linear objects</title><content type='html'>This is just a note to myself to revisit the &lt;br /&gt;following article by Henry Baker:&lt;br /&gt;&lt;a href="http://home.pipeline.com/~hbaker1/Use1Var.html"&gt;'Use-Once' Variables and Linear Objects&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I really should start making a big list for Stevie and I to go through in preparation for our PL Jr talk.&lt;br /&gt;&lt;br /&gt;See also:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://home.pipeline.com/~hbaker1/ForthStack.html"&gt;Linear Logic and Permutation Stacks--The Forth Shall Be First&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://home.pipeline.com/~hbaker1/LQsort.html"&gt;A 'Linear Logic' Quicksort&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://home.pipeline.com/~hbaker1/LBoyer.html"&gt;The Boyer Benchmark Meets Linear Logic&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://home.pipeline.com/~hbaker1/LFrpoly.html"&gt;Sparse Polynomials and Linear Logic&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://home.pipeline.com/~hbaker1/LinearLisp.html"&gt;Lively Linear Lisp--'Look Ma, No Garbage!'&lt;/a&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111593840961624938?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111593840961624938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111593840961624938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111593840961624938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111593840961624938'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/05/linear-objects.html' title='linear objects'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111479084492935286</id><published>2005-04-29T09:05:00.000-07:00</published><updated>2005-04-29T09:07:24.930-07:00</updated><title type='text'>publication pressure</title><content type='html'>I have to say, I need to try to publish my work more often.  (For other than &lt;br /&gt;the obvious reason that I need to publish work, period.)&lt;br /&gt;&lt;br /&gt;It really forces you to make everything concrete.  To the max.  &lt;br /&gt;&lt;br /&gt;Almost as much as actually implementing it would.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111479084492935286?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111479084492935286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111479084492935286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111479084492935286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111479084492935286'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/04/publication-pressure.html' title='publication pressure'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111394988105756538</id><published>2005-04-19T15:26:00.000-07:00</published><updated>2005-04-19T15:33:23.346-07:00</updated><title type='text'>System F and semi-unification</title><content type='html'>&lt;a href="http://lists.seas.upenn.edu/pipermail/types-list/2004/000314.html"&gt;This&lt;/a&gt; is somewhat of a note to myself to revist the responses posted.&lt;br /&gt;&lt;br /&gt;I'm not 100% percent sure the original author (Mike) really had a grasp on what he was saying.  On the one hand, he wanted to get an intuition as to which programs would be problematic to infer types for.  But then he started talking about reducing inference for those problems to semi-unification; that's not the right idea!  The idea is that you take a bog-standard undecidable problem (e.g.  the halting problem), reduce that to semi-unification, and then reduce the reduction to a sample term in System F.&lt;br /&gt;&lt;br /&gt;Of course, this would probably yield a term so complex that it would boggle the mind, and not provide the intuition that he was hoping for.&lt;br /&gt;&lt;br /&gt;If, on the other hand, he was just interested in the idea of using a  (partial) semi-unifier to (partially) perform type inference for System F, then that's a different story.  Hard to tell.  But lots of interesting points and links in the responses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111394988105756538?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111394988105756538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111394988105756538' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111394988105756538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111394988105756538'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/04/system-f-and-semi-unification.html' title='System F and semi-unification'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111392551187140512</id><published>2005-04-19T08:39:00.000-07:00</published><updated>2005-04-19T08:45:11.873-07:00</updated><title type='text'>subtextual response</title><content type='html'>I've been looking at Jonathan Edwards' experimental programming&lt;br /&gt;environment/language, &lt;a href="http://www.subtextual.org/"&gt;Subtextual&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am semi-underwhelmed.  But there are some interesting connections with spreadsheet programming here.&lt;br /&gt;&lt;br /&gt;I later read this &lt;a href="http://alarmingdevelopment.org/index.php?p=5"&gt;post&lt;/a&gt; from the related Alarming Development blog, and there was one thing there that irk'ed me: the idea that we should embraced copy-and-paste programming.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;cut&lt;/b&gt;-and-paste programming, I have learned to accept.  That's when, if you are tempted to copy-and-paste a snippet of code, you instead cut it out entirely, and then turn it into a seperate subroutine/superclass/unit/module.  Then you parameterize accordingly (and of course you are expected to add documentation about the mental model you have in your head about what this piece of code does).&lt;br /&gt;&lt;br /&gt;But copy-and-paste is very dangerous.  And in fact, in Subtextual, it seems like Edwards has embraced a sort of hybrid between cut and copy, because when you copy subtrees, you don't get a fresh copy immediately; instead you get a tree that is linked back to the original tree, and changes to either will propogate to both.  You have a seperate operation, "introduce variant", to actually do the copying in place.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111392551187140512?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111392551187140512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111392551187140512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111392551187140512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111392551187140512'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/04/subtextual-response.html' title='subtextual response'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111332868547240106</id><published>2005-04-12T10:54:00.000-07:00</published><updated>2005-04-12T10:58:05.473-07:00</updated><title type='text'>mailman, postfix, and pain</title><content type='html'>Was up late last night trying to set up a mailman-based mailing list to demonstrate such things to my cousin.&lt;br /&gt;&lt;br /&gt;I made much use of &lt;a href="http://www.afp548.com/Articles/Jaguar/mailman21-new.html"&gt;this page&lt;/a&gt; to figure out how to get the whole thing going.  But when I went to bed, the damn thing still wasn't working.&lt;br /&gt;&lt;br /&gt;Eventually I figured out that I never actually started the mailman daemon that is in charge of processing information as it comes in.  I just figured that apache and postfix would &lt;i&gt;know&lt;/i&gt; that they needed to call out to these command line procedures when they got certain inputs (e.g. mail to a particular address).  Silly me.&lt;br /&gt;&lt;br /&gt;So I was dumped into the sewer of systems administration once again.  But I've pulled myself out now; I'm so happy I'm a PL researcher.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111332868547240106?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111332868547240106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111332868547240106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111332868547240106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111332868547240106'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/04/mailman-postfix-and-pain.html' title='mailman, postfix, and pain'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111328292202184783</id><published>2005-04-11T22:10:00.000-07:00</published><updated>2005-04-11T22:28:47.756-07:00</updated><title type='text'>Observing Finalizers and References on the JVM</title><content type='html'>As a followup to clarify my previous comment on &lt;a href="http://calculist.blogspot.com/2005/04/resurrecting-java-objects.html"&gt;this post&lt;/a&gt; (since Dave and I discussed this question personally):&lt;br /&gt;&lt;br /&gt;Here is an experimental revision of the code that Dave posted; it is meant to demonstrate a number of things.  The most important are: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt; If you want to really observe a space leak, it is helpful to actually use objects which are large (&lt;code&gt;new int[X]&lt;/code&gt; is your friend here).&lt;br /&gt;&lt;li&gt; If you want to really observe a space leak, it (unfortunately) seems like you may have to employ the (non-standard) &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt; options to the JVM.&lt;br /&gt;&lt;li&gt; There are more reliable/sensible alternatives for monitoring whether an object has been collected than attempting to maintain a hashtable of object identifiers.  Namely, use of classes in &lt;code&gt;java.lang.ref.*&lt;/code&gt;.  &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Having said this, I admit that I do not fully understand the semantics of weak references, because I was not able to naively replace all of Dave's uses of &lt;code&gt;kill(int)&lt;/code&gt; with my &lt;code&gt;killAlt(int)&lt;/code&gt; procedure.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt; Finalizers really are run only once.  However, that doesn't always mean that you can't collect an object just because the call to its finalizer makes it live again.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I had to backport the code to JDK 1.4 since that's all I have on my poor little Mac OS X box.  Sorry.  I tried to make the backport clean by using trampoline instantiation of the generic collections rather than cluttering up the code with casts everywhere.&lt;br /&gt;&lt;br /&gt;Sample command line invocations of this class:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;% java -Xmx1mb -Xms1mb Immortal -dummysize 100000 -num 10&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;% java -Xmx1mb -Xms1mb Immortal -dummysize 100000 -blowup 10&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(Note that due to the braindead way I'm doing argument parsing, the order of the options above is VERY significant).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.util.Hashtable;&lt;br /&gt;import java.util.Vector;&lt;br /&gt;import java.lang.ref.Reference;&lt;br /&gt;import java.lang.ref.WeakReference;&lt;br /&gt;import java.lang.ref.ReferenceQueue;&lt;br /&gt;&lt;br /&gt;public class Immortal {&lt;br /&gt;&lt;br /&gt;    static class HashtableFromIntegerToInteger {&lt;br /&gt; Hashtable me = new Hashtable();&lt;br /&gt; public int get(int k) { return ((Integer)me.get(new Integer(k))).intValue(); }&lt;br /&gt; public void put(int k, int v) { me.put(new Integer(k), new Integer(v)); }&lt;br /&gt; public void remove(int k) { me.remove(new Integer(k)); }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    static class HashtableFromIntegerToImmortal {&lt;br /&gt; Hashtable me = new Hashtable();&lt;br /&gt; public Immortal get(int k) { return ((Immortal)me.get(new Integer(k))); }&lt;br /&gt; public void put(int k, Immortal v) { me.put(new Integer(k), v); }&lt;br /&gt; public void remove(int k) { me.remove(new Integer(k)); }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    static class HashtableFromIntegerToRef {&lt;br /&gt; Hashtable me = new Hashtable();&lt;br /&gt; public Reference get(int k) { return ((Reference)me.get(new Integer(k))); }&lt;br /&gt; public void put(int k, Reference v) { me.put(new Integer(k), v); }&lt;br /&gt; public void remove(int k) { me.remove(new Integer(k)); }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /** tracks the number of times each finalizer is run */&lt;br /&gt;    // private static Hashtable&lt;Integer,Integer&gt; finalizeCounts = new Hashtable&lt;Integer,Integer&gt;();&lt;br /&gt;    private static HashtableFromIntegerToInteger finalizeCounts = new HashtableFromIntegerToInteger();&lt;br /&gt;&lt;br /&gt;    /** used to control object lifetimes */&lt;br /&gt;    private static HashtableFromIntegerToImmortal pointers = new HashtableFromIntegerToImmortal();&lt;br /&gt;&lt;br /&gt;    private static HashtableFromIntegerToRef  phantoms = new HashtableFromIntegerToRef();&lt;br /&gt;    &lt;br /&gt;    private static ReferenceQueue refqueue = new ReferenceQueue();&lt;br /&gt;&lt;br /&gt;    private static boolean nomesg = false;&lt;br /&gt;&lt;br /&gt;    private static void mesg(String s) {&lt;br /&gt; if (! nomesg) {&lt;br /&gt;     System.out.println(s);&lt;br /&gt; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /** used to generate unique identifier codes */&lt;br /&gt;    private static int unique = 0;&lt;br /&gt;&lt;br /&gt;    /** some "large" state so that we can observe blowup */&lt;br /&gt;    public int[] dummydata;&lt;br /&gt;    private static int dummysize = 100;&lt;br /&gt;&lt;br /&gt;    public static void killAlt(int id) {&lt;br /&gt;        int finalizeCount = finalizeCounts.get(id);&lt;br /&gt;        pointers.remove(id);&lt;br /&gt;        while ( ! phantoms.get(id).isEnqueued())&lt;br /&gt;        {&lt;br /&gt;            mesg("(alt) trying to kill " + id + "...");&lt;br /&gt;            System.gc();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /** deletes the object with the given id. */&lt;br /&gt;    public static void kill(int id)&lt;br /&gt;    {&lt;br /&gt;        int finalizeCount = finalizeCounts.get(id);&lt;br /&gt;        pointers.remove(id);&lt;br /&gt;        while (finalizeCounts.get(id) == finalizeCount)&lt;br /&gt;        {&lt;br /&gt;            mesg("trying to kill " + id + "...");&lt;br /&gt;            System.gc();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // The code from these two methods can't be inlined, because&lt;br /&gt;    // we rely on their stack frame disappearing to prevent the&lt;br /&gt;    // link to the tracked object from persisting.&lt;br /&gt;&lt;br /&gt;    public static int makeTemporaryObject()&lt;br /&gt;    {&lt;br /&gt;        Immortal temp = new Immortal();&lt;br /&gt;        return temp.id;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void doSomethingWith(int id)&lt;br /&gt;    {&lt;br /&gt;        Immortal temp = pointers.get(id);&lt;br /&gt;        temp.sayHello();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /** identifier code */&lt;br /&gt;    private int id;&lt;br /&gt;&lt;br /&gt;    private Immortal()&lt;br /&gt;    {&lt;br /&gt;        id = unique++;&lt;br /&gt;        mesg("creating instance " + id);&lt;br /&gt;        finalizeCounts.put(id, 0);&lt;br /&gt;        pointers.put(id, this);&lt;br /&gt; phantoms.put(id, new WeakReference(this, refqueue));&lt;br /&gt; int last = dummysize;&lt;br /&gt; dummydata = new int[last + 1];&lt;br /&gt; dummydata[0] = 1;&lt;br /&gt; dummydata[last] = 1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void sayHello()&lt;br /&gt;    {&lt;br /&gt;        System.out.println("hi, I'm number " + id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void finalize()&lt;br /&gt;    {&lt;br /&gt;        mesg("finalizing " + id + "...");&lt;br /&gt;        finalizeCounts.put(id, finalizeCounts.get(id) + 1);&lt;br /&gt;        // clear! *khzh-thump*&lt;br /&gt;        pointers.put(id, this);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt; if (args.length == 0) {&lt;br /&gt;     int id = Immortal.makeTemporaryObject();&lt;br /&gt;     &lt;br /&gt;     // This causes the finalizer to run (in the GC thread.)&lt;br /&gt;     Immortal.kill(id);&lt;br /&gt;     &lt;br /&gt;     // And yet, the object is still alive!&lt;br /&gt;     Immortal.doSomethingWith(id);&lt;br /&gt;     &lt;br /&gt;     // This will now loop infinitely, since the finalizer&lt;br /&gt;     // will never be run a second time.&lt;br /&gt;     Immortal.kill(id); &lt;br /&gt; } else { &lt;br /&gt;     for(int i = 0; i &lt; args.length; i++) {&lt;br /&gt;  if (false) {&lt;br /&gt;      // dummy case for uniform syntax&lt;br /&gt;  } else if (args[i].equals("-nomesg")) {&lt;br /&gt;      nomesg = true;&lt;br /&gt;  } else if (args[i].equals("-dummysize")) {&lt;br /&gt;      int num = Integer.parseInt(args[++i]);&lt;br /&gt;      dummysize = num;&lt;br /&gt;  } else if (args[i].equals("-num")) {&lt;br /&gt;      int num = Integer.parseInt(args[++i]);&lt;br /&gt;      &lt;br /&gt;      for(int j = 0; j &lt; num; j++) {&lt;br /&gt;   int id = Immortal.makeTemporaryObject();&lt;br /&gt;   &lt;br /&gt;   // This causes the finalizer to run (in the GC thread.)&lt;br /&gt;   Immortal.kill(id);&lt;br /&gt;   &lt;br /&gt;   // And yet, the object is still alive!&lt;br /&gt;   Immortal.doSomethingWith(id);&lt;br /&gt;   &lt;br /&gt;   // FSK: alternative variant of kill which uses weak references&lt;br /&gt;   Immortal.killAlt(id); &lt;br /&gt;      }&lt;br /&gt;  } else if (args[i].equals("-blowup")) {&lt;br /&gt;      int num = Integer.parseInt(args[++i]);&lt;br /&gt;      &lt;br /&gt;      for(int j = 0; j &lt; num; j++) {&lt;br /&gt;   int id = Immortal.makeTemporaryObject();&lt;br /&gt;   &lt;br /&gt;   // This causes the finalizer to run (in the GC thread.)&lt;br /&gt;   Immortal.kill(id);&lt;br /&gt;   &lt;br /&gt;   // And yet, the object is still alive!&lt;br /&gt;   Immortal.doSomethingWith(id);&lt;br /&gt;   &lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111328292202184783?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111328292202184783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111328292202184783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111328292202184783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111328292202184783'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/04/observing-finalizers-and-references-on.html' title='Observing Finalizers and References on the JVM'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111188656905543946</id><published>2005-03-26T17:18:00.000-08:00</published><updated>2005-03-26T17:28:29.573-08:00</updated><title type='text'>"Well-going programs can be typed"</title><content type='html'>Here is one of the stranger papers I've seen since the Forsythe one:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.kent.ac.uk/pubs/2003/1649/"&gt;Well-going programs can be typed&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The abstract:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Our idiomatically objectionable title is a pun on Milner's ``well-typed programs do not go wrong' --- because we provide a completeness result for type-checking rather than a soundness result.&lt;br /&gt;&lt;br /&gt; We show that the well-behaved functions of untyped PCF are already expressible in typed PCF: any equivalence class of the partial logical equivalence generated from the flat natural numbers in the model given by PCF's operational semantics is inhabited by a well-typed term.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Its got Scott's $D_{\infty}$, PCF, Retractions, PERs, Logical Relations, . . .&lt;br /&gt;&lt;br /&gt;And yet the paper itself is 50% tricks with Haskell type classes and GHC extensions.&lt;br /&gt;&lt;br /&gt;I think the title is extremely misleading, at least based on my interpretation of the abstract.  I thought the title meant: "if your untyped PCF program is well-behaved, then there is some way to add type annotations to yield a well-typed program (presumably with the same behavior)."  But abstract semes to really be saying that if you have a well-behaved function, then there is some well-typed function with extensionally equivalent behavior; note the lack of constraint on the form of the typed program text and its relation to the untyped text.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111188656905543946?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111188656905543946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111188656905543946' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111188656905543946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111188656905543946'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/03/well-going-programs-can-be-typed.html' title='&quot;Well-going programs can be typed&quot;'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11696659.post-111188616745045559</id><published>2005-03-26T17:15:00.000-08:00</published><updated>2005-03-26T17:16:07.450-08:00</updated><title type='text'>test</title><content type='html'>My first post.  Woot.&lt;br /&gt;&lt;br /&gt;Catching up on West Wing.  This one has Castro.  Lots of Cuban-sounding music in the background.  Its kind of like watching The Godfather Part II&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11696659-111188616745045559?l=pnkfif.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pnkfif.blogspot.com/feeds/111188616745045559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11696659&amp;postID=111188616745045559' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111188616745045559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11696659/posts/default/111188616745045559'/><link rel='alternate' type='text/html' href='http://pnkfif.blogspot.com/2005/03/test.html' title='test'/><author><name>Felix</name><uri>http://www.blogger.com/profile/04222189622973190255</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
