Older blog entries for wingo (starting at number 316)

read what i wrote on my shirt

The light of summer has died, but not the heat. The sky failed to rain today. I'm sure that if cloud seeding actually worked, Pfizer would arrange to dispense rain by means of little purple pills.

I finally got around to uploading photos recently, for the first time since May. Photos are the new inbox.

It's a good thing a few of these turned out well, because I burned my glasses taking them -- on the inside of the lens. No wonder the EU wants to ban fireworks in the street, but what a pity. Up next: lifejacket beach sunbathing.

states that start with p

Two places I offer to you, both in the new-to-me state of Pennsylvania.

One: Eastern State Penitentiary, a "model prison", back from the days of utopia. From the outside, Eastern State imposes, with high, silent walls -- as if it had its back to the city, all around. And inside... well, it was built under the idea that 23 hours of silent isolation + 1 hour of solitary exercise would be good for the soul, somehow. So there are two sides of the experience: one space in which to see everything, linear wards radiating from the one-point center, and the other in-cell space, in which you see no one. Ever.

And two, Wharton Esherick's house/museum/autobiography. Beautiful and inventive woodwork, this.

pollack and the cia

I went to New York's Museum of Modern Art for the first time, which was lovely -- to see so many icons of the last century, there, just on the wall.

Walking through the Rockefeller rooms of 1950s American art, I couldn't help but think of Who Paid the Piper?, or, as it was titled in the US, The Cultural Cold War. The deal, as I recall the book's argument, is that in the aftermath of World War II, Europe was really up for grabs. Of course we know how it played out politically, but art was also at stake -- that for the elites of Europe to be on board with the US politically, they had to believe.

So, the US did have whiz-bang technology, but man cannot live on atomic energy alone, as they say. Humanity needs dreams and interpretation: a function of art. The CIA wanted the dreamers and interpreters to (a) not be allied to communists, at all; and (b) to promote an "American" art, something in keeping with modernity and transgression. So Jackson Pollock was funded to be a cowboy-artist, on purpose.

Yes, I am struck, standing in front of his works; they have that something. I like it. But it is complicit.

Apparently, enough time has passed that even the CIA itself can talk about it -- https-only link because, er, apparently art is that important.

Syndicated 2009-10-08 20:55:05 from wingolog

thigh fives

The intertron seems to be misled as to the nature of thigh fives.

As a citizen it is my duty to assist in correcting this oversight.

Syndicated 2009-10-06 09:27:37 from wingolog

wikipedia & guile

Good evening, internet!

Oftener then not, when posting dispatches to this ship's log, it's with an air of surprise: of the turned head over the shoulder, smiling at the unexpected appearance of a friend. Well hello world, then, it's just been like that, punctuated ensimismamiento.

* * *

This particular evening finds me in Los Angeles, here for work. I have loads of stories and photos, hopefully soon forthcoming, but the present impetus for text is more mundane. And nerdy, may I mention. For the laity, imagine a pendulous pocketwatch, you are getting sleepy, yes, yes -- you need not read the rest -- you might remember suddenly that you wanted to make some tea, and that upon your return to the machine will remember having read all of this log entry, and that its writer was a genteel and amiable fellow.

You should probably stop reading now, your tea water is aboil!

* * *

For the rest of you, please forgive the verbal excess, I've been reading too much Jane Austen recently.

My friend and colleague B. Tregre pointed me to Guile's wikipedia page today, basically asking, "is it true?"?

Because if you read that page, it's pretty clear that Guile is a bad thing. I mean, in deference to Norvig, let's condense that page:

  1. Guile

    1. Implementation of Scheme

    2. Since 1993

    3. Embeddable as a C library

    4. But let's get to the dirt

  2. Scheme compliance

    1. Still bitter about Guile following the 1998 Scheme standard but not the 1991 one

    2. For some reason we're going to complain about Guile's call/cc implementation

    3. Also we're going to demonize conservative collectors some more.

  3. Salt, wounds

    1. Etc.

meta

Perhaps actually I should start with a meta-meta: I hack on Guile for a number of reasons. I like it, first of all. It's good software, widely deployed, with some neat stuff in it. I like the folks that hack on it -- the people and what they do. I like the project's stated goals of freedom, and I like the hack. &c.

But what of that neat stuff shows up in the Wikipedia article? Practically nothing. Lack of enthusiasm in an encyclopedia is to be expected; but lack of information is something else.

The Guile wikipedia entry simply doesn't tell you much about Guile itself. So that's my first meta-complaint.

My second meta-complaint is perhaps more to the point -- that the real message, the message if you read between the lines, is "Guile is a bad implementation of Scheme". This is editorialization through tone and fact selection. That most of the facts are strictly true does not mean that the message is true.

So to me, while the facts of the article are mostly (though not entirely) right, the article itself is wrong. The selection of facts is not representative of Guile, the object under consideration.

non-meta

I guess it's worthwhile to discuss the principal argument against Guile expounded more explicitly in the article: namely, conservative garbage collection.

Conservative collection is a way to scan all memory, looking for pointers. If it finds something that looks like a pointer, it considers the pointed-to address to be in use. At the end of "marking" the memory, the collector "sweeps" all non-marked locations.

If you're confused but interested, I discussed this topic last year in some detail. Wikipedia itself has a good discussion, too.

Guile now uses the Boehm-Demers-Weiser collector, instead of having an in-Guile implementation; Boehm himself discusses the topic as well.

Basically, there is a potential problem with conservative GC: one might see an integer somewhere in memory, but mistakenly interpret it as a pointer, thus keeping around data unnecessarily. If this happened often enough, or on a big enough data structure, you could leak lots of memory.

In practice, this rarely happens.

In the very very unlikely event that you keep memory around that should be freed, there are tools to work around the condition; but in a language implementation, where you really control what's in addressable memory (both heap and stack), you might be able to eliminate such misidentifications altogether. Finally in a 64-bit system such a collision is highly unlikely. I've never had a problem with Guile leaking memory.

But, there are some programmers who see this hack (and it is a hack) as a Pavlovian bell for vitriol. I really don't get it. It's not like you have any options in plain C. And if your language implementation exposes itself broadly to C, your implementation doesn't have many options either.

PLT Scheme was able to switch away from conservative collection because they were able to lessen their exposure to C, via development of a good in-Scheme foreign function interface (FFI). Guile will have this possibility in the future.

culpability

I've thought about these issues fairly hard. One of my goals is to get Guile into Emacs within the next 12-18 months. But what if pointers were consistently and persistently misidentified, making it impossible to keep Emacs sessions open for months or years? Then the snarky Wikipedians would add a paragraph explaining how it was Guile that broke Emacs.

So the question to consider is, what bit pattern is identified by libGC as a pointer, and what non-pointer words on your system have a value that matches that pattern? Pointers to heap-allocated objects are aligned on 8-byte boundaries, so their lower three bits will be 0. In addition, the pointer value must lie within an allocated heap segment, which typically are large values, at least a million or so. So integers that you typically see are most unlikely to collide.

Furthermore, while it is typically said that "certain integer values" can be mistakenly identified, those are integer values in C. Guile's representation of integers (at least, those less than 2^30 or 2^62) has the lower two bits of the integer to be "10" -- so a Guile integer will never be confused with a pointer.

What can be confused are native (C) integers. Native C integers can appear ephemerally on the stack, or in packed memory blocks, i.e. in a packed uint32 array. In the latter case, libGC would allocate that block as a "pointerless" segment, so the integers would not be scanned, leaving us only with the stack case.

For the stack, you have two cases -- code introduced by your runtime, e.g. the VM code, and code introduced by Scheme. I've already argued that Scheme values cannot be misidentified. The VM code is so small it is auditable -- and extremely unlikely to persistently store a large integer on the stack, because such integers are not used in the VM.

Even these stack unknowns will be eliminated when Guile does native compilation (within 12-24 months), so we completely control all bits on the stack, too.

That leaves the C runtime, which if there are problems in Emacs, they can be worked around with the libGC tools. But in the end, removing most GC annotations from Guile's runtime (and eventually, remove the GCPRO mess from Emacs) has hugely positive maintenance benefits -- and, I am convinced, no downsides in practice.

stories

I could conclude that "you shouldn't let others write your wikipedia pages" -- given a sufficiently broad conception of self-as-project -- but that makes Wikipedia look the victim here.

The ultimate meta-conclusion is more about message and transmission -- in short, about story. That is, to not let others define who or what you are. Make sure they are telling your story.

And if they aren't telling your story, to motivate your own story-tellers and retellers to get the word out. I'm hoping to get others to fix that article over the next few months, by getting guile-users subscribers to garden it a bit.

Until next time, intertube. Happy October!

Syndicated 2009-10-01 15:49:33 from wingolog

goto 1965

travels through space

Time passes, and space with it. I don't like airplanes overmuch, so I caught a train up to Paris last weekend, and from there Kate & I took a plane to Dublin to visit Jan Jaime Jingle Hemmett Schmidt.

Dublin was lovely, lovely -- performing for us in weather and in song, in light and dark -- the dark being the fine stout, of course. I couldn't pick a favorite part, though the one that keeps popping into mind is Newgrange, a 5000-year-old neolithic passage tomb, forty-some meters in diameter, aligned so that a shaft of light would pass into the chamber on the winter solstice.

That image aligns nicely with my Mumford readings of late. Before the construction of such artifacts, either as sticks planted in the ground or as massive monuments, time did not exist -- at least, not as we know it now, as an outside thing ticking on discretely without us -- as opposed to the spurting yet continuous flow experienced within.

I spent the rest of last week hanging out in deserted August Paris, the city-time of open-air cinema and ambles in unpeopled streets. But I won't lie: I spent a fair piece of it indoors, hack on the mind.

travels through time

At my last dispatch, I was in 1987, implementing flat closures, described in Dybvig's dissertation.

The recent spatial travel to Dublin, unaccompanied by the laptop, left my mind unusually clear. So spatially back in Paris on Wednesday I left again for 2002, implementing Fixing Letrec. The important contribution of that paper was a systematic, direct way to translate mutually recursive lambda expressions to a generalized form of the fixed-point operator, also known as the Y combinator. Quoth the prophets Waddell, Sarkar & Dybvig:

The transformation converts letrec expressions into an equivalent mix of let, set!, and fix expressions. A fix expression is a variant of letrec that binds only unassigned variables to lambda expressions. It represents a subset of letrec expressions that can be handled easily by later passes of a compiler.

In particular, no assignments through external variables are necessary to implement mutually recursive procedures bound by fix. Instead, the closures produced by a fix expression can be block allocated and “wired” directly together. This leaves the fix-bound variables unassigned, thus simplifying optimizations such as inlining and loop recognition.

fix is identical to the labels construct handled by Steele’s Rabbit compiler and the Y operator of Kranz’s Orbit compiler and Rozas’ Liar compiler.

For me, this passage was tantalizing, but I didn't quite understand the optimizations that a transformation to fix allowed. Yes, I had read Steele's dissertation a number of times, but Guile's compiler doesn't do a CPS rewrite, so it was unclear how some of the optimizations applied.

But my recent "flat closure" work had pointed out one optimization, the "block allocation" mentioned in the above paragraph. Consider two mutually recursive functions:

  (define (analyze n)
    (define (even? n)
      (or (= n 0)
          (odd? (- n 1))))
    (define (odd? n)
      (or (= n 1)
          (even? (- n 1))))

    (cond ((< n 0)   'negative-number)
          ((even? n) 'even-number)
          (else 'odd-number)))

Ignore for the moment the dubious "analysis" that this function performs. (Can you spot the bug?) What I want to focus on are the internal definitions, even? and odd?. Using define in a nested context like this is simply sugar around letrec, so this is equivalent to:

  (define (analyze n)
    (letrec ((even? (lambda (n)
                      (or (= n 0)
                          (odd? (- n 1)))))
             (odd?  (lambda (n)
                      (or (= n 1)
                          (even? (- n 1))))))
      (cond ((< n 0)   'negative-number)
            ((even? n) 'even-number)
            ((odd? n)  'odd-number)))

Here we see the mutual recursion expressed more clearly. Looking more closely at the even? and odd? bindings, we see that each has one free variable:

  (lambda (n)
    (or (= n 0)
        (odd? (- n 1))))
          ^ odd? is free in even?

  (lambda (n)
    (or (= n 1)
        (even? (- n 1))))
          ^ even? is free in odd?

If even? and odd? are compiled as mutually recursive closures (a point to which I will return shortly), they need to capture each other's bindings -- kindof a chicken-and-egg problem, no?

In the lambda calculus, this problem is solved via the Y combinator, which basically involves passing the functions of interest to another function, which in turn invokes the functions of interest, passing themselves as their arguments. It's pretty neat. Thomas Holubar and Jos Koot have been discussing this very topic at FLIBUG, incidentally (see Thomas's slides on the need for Y for a brief introduction).

origins of letrec

To continue the digression, I understand that the letrec construct was originally defined by Peter Landin in a 1965 paper, A Correspondence between ALGOL 60 and Church's Lambda-Notation. He uses a very schemely intermediate language to model ALGOL 60's semantics with sugar on top of a slightly extended lambda calculus.

In the following discussion, from the paper, Landin describes how mutually recursive definitions and labels (goto targets) can be expressed using letrec. Take φn to mean an arbitrary expression; italics are mine.

Definitions can also arise from the block-body -- their definees being the labels that are local to the block. These are defined in terms of locals, including each other, and they may be referred to by procedure and switch declarations. Hence labels must be grouped with switches and procedures as a single simultaneously recursive definition. The overall treatment of a block is therefore as follows.

[On the left we have ALGOL 60, on the right Landin's "Applicative Expression" intermediate language.]

begin                     let a=φ1
    real a;                   and A=φ2
    array A φ2;             let rec P=φ3
    procedure P φ3;                 and S=φ4
    switch S φ4;                    and L=φ6
    φ5;                             and M=φ7
 L: φ6;                       φ5            
 M: φ7;
end

[Here is the translation into the lambda calculus. Note the Y!]

{λ(a,A).{λ(P,S,L,M).φ5}
        [Yλ(P,S,L,M).(φ3,φ4,φ6,φ7)]}
[φ1,φ2]

Applying Y to mutually recursive procedures/labels binds them together, allowing them to see themselves. So you see, Y was in letrec from the very beginning.

Note that labels, denoting basic blocks, are modelled as procedures of 0 arguments. In the light of Steele's 1977 contribution, which I will discuss shortly, Landin's 1965 paper was particularly prescient. Landin says:

The treatment of jumps springs from the observation that the symbol 'go to' in ALGOL 60 is redundant, and could be ignored by a preprocessor. That is to say, there is a considerable similarity between labels and the identifiers of parameterless nontype procedures. It is possible to use the same "calling mechanism" for both, leaving any difference to be made by the thing that is "called"...

It might therefore be supposed that labels can be eliminated formally by considering each labelled segment of program as a parameterless procedure declaration (and hence as a definition whose defiens is a λ()-expression).

Steele turns this isomorphism around, saying instead:

In general, procedure calls may be usefully thought of as GOTO statements which also pass parameters, and can be uniformly encoded as JUMP instructions. This is a simple, universal technique... Our approach results in all tail-recursive procedure calls being compiled as iterative code, almost without trying, for it is more a matter of the code generation strategy than of a specific attempt to remove recursions.

Landin passed away in June of this year.

mischief managed

Anyway, back to 2002. Scheme's letrec construct is more general than Landin's let rec; it allows arbitrary expressions on the right-hand side, not just procedures. So the first trick Waddell shows is how to transform letrec into "an equivalent mix of let, set!, and fix". Once he has the fix, which is the same as Y, we need to compile it -- and that's where we were before longjmping back to 1965.

In the lambda calculus, a very minimal language, often there are more efficient ways to implement higher-order constructs, such as fix.

So fix-bound procedures need to capture an environment including themselves, fine. The standard way (in Scheme now, not the lambda calculus) is to bind e.g. even? and odd? (as in our example above) to empty "boxes", then set! the contents of the boxes to the procedures. The fix-bound lambda-expressions have bound the right variables, and after the boxes have been filled in via set!, those expressions hold each other's value: mischief managed. Like this:

(let ((even? #f) (odd? #f))
  (set! even? (lambda (n) (or (= n 0) (odd? (- n 1)))))
  (set! odd? (lambda (n) (or (= n 1) (even? (- n 1)))))
  ...)

But this is not ideal, because it forces the fix-bound lambda expressions to be allocated on the heap, in boxes, whereas in fact they are never set! in the source text.

We can do better. Since the lambda expressions don't actually run until after the bindings have been made, and thus don't reference their free bindings until then, we can allocate them on the stack, then fix up their free variables, mutating the closures in place.

Thus we don't introduce extraneous set! constructs into the code. This simplifies inlining and loop detection, as Waddell notes, and also allows the fix-bound variables to be allocated on the stack instead of in boxes, removing an indirection at runtime.

even better

But we can do even better than that. In this example, we still allocate a closure for even? and for odd? -- but we can avoid that too. Notice that even? and odd? are always called in tail position with respect to the letrec construct. Landin tells us that labels, the targets of go to, may be viewed as procedures of 0 arguments, with respect to the lambda calculus; Steele goes the other way, in his 1977 paper, Debunking the 'Expensive Procedure Call' Myth, or, Procedure Call Implementations Considered Harmful, or, Lambda: The Ultimate GOTO. (If you program, and want just one article to read out of all of these, read this paper.)

So, for a tail-call to a fix-bound procedure, we can simply render the bindings of the procedures inline to the parent procedure, jump over them, then enter the body of the fix. Any tail-call to a fix-bound procedure compiles a goto -- after setting its arguments. Since the procedure is lexically bound, and never set!, we know exactly where those arguments are going to be, so we set them directly -- no need to shuffle them around.

So an empty loop:

(letrec ((loop (lambda () (loop))))
  (loop))

Looks like this:

   ;; jump over definition of `loop'
   0    (br :L124)                      ;; -> 16
   ;; definition of `loop'
   8    (br :L125)                      ;; -> 8
   ;; letrec body
  16    (br :L125)                      ;; -> 8

(You get this by typing ,x (lambda () (let loop () (loop))) into the Guile REPL.)

A loop counting down from 100 looks like this:

scheme@(guile-user)> ,x (lambda ()
                          (let lp ((n 100))
                            (or (zero? n)
                                (lp (1- n)))))
Disassembly of #<program b742e6d0 at <unknown port>:51:3 ()>:

   0    (br :L141)                      ;; -> 32
   8    (local-ref 0)                   ;; `n'
  10    (make-int8:0)                   ;; 0
  11    (ee?)                           
  12    (local-set 1)                   ;; `t'
  14    (local-ref 1)                   ;; `t'
  16    (br-if-not :L142)               ;; -> 24
  19    (local-ref 1)                   ;; `t'
  21    (return)                        
  24    (local-ref 0)                   ;; `n'
  26    (sub1)
  27    (local-set 0)                   ;; `n'
  29    (br :L143)                      ;; -> 8
  32    (make-int8 100)                 ;; 100
  34    (local-set 0)                   
  36    (br :L143)                      ;; -> 8

I mean, that's pretty damn good. We could do better if we reordered the blocks a bit, and compiled the conditional branch br-if-not into something more specific, but still -- pretty tight for compiling scheme to bytecode.

(The `t', if you are curious, is a result of the expansion of or.)

conclusions

Guile has applied Waddell's "Fixing Letrec" strategy to transform Scheme's general letrec into more primitive constructs, including fix. fix-bound lambda expressions that need to be allocated as closures are now faster and cons less, given that they aren't allocated in boxes, and an important subset of fix expressions is now rendered as inline code and wired together using goto, a pleasant illustration that indeed, lambda is the ultimate goto.

I didn't think I would get to this kind of bytecode this fast, but once the simplification to fix was made, the rest of the optimizations were obvious. But the hack continues, there's always more to do. Expect to see this out in Guile's 1.9.2 release that's coming on Saturday. Happy hacking!

Syndicated 2009-08-10 07:45:43 from wingolog

farewell, amat ciutat

I came down the stairs this morning -- pants cuffed, helmet on, cross strap buckled -- and sauntered around the corner to unlock my bike, but alas, it was not there. Last night they stole my bike.

I knew it would happen some day. Bikes are on loan to us from God, who works in mysterious ways indeed. But I didn't think it would happen this way.

See, I had a dinner on my terrace last weekend. In a fit of silliness, when people would come to the door, I'd just drop them my keys off the side of the balcony. Amusement for all!

But when I went to lock up my bike yesterday evening at a restaurant -- it had spent the weekend in the office -- of course it was the bike lock key that broke in the weekend's antics, and I hadn't noticed it.

Luckily I had the wee cable lock that ran through my seatpost, so I crossed my fingers and used that instead. So it was with pleasure that, leaving the restaurant, I found that my bike was still there.

We had a great ride last night, me and the bike. We hit all the lights, and beat the metro back to my house by 10 minutes. I figured it would last one more evening out with the wee lock, in my relatively calm neighborhood, but no, it was not to be.

So farewell, Amat Ciutat, my friend. We hardly knew ye.

Syndicated 2009-07-28 08:47:22 from wingolog

the good hack

Good evening, internet!

I haven't written in a little while, and I suppose a hack-update is due. So first an overview, then a digression into nargery, then a discussion of what's really on my mind these days: Mumford and Eisenstein.

Hup hup, then!

guile

Guile is now on a monthly release schedule, in the runup to 2.0. We've already made two releases, 1.9.0 and 1.9.1.

The feedback has generally been that it works, that it is faster, but that in a few cases, some old macros have to change. The NEWS describe all the gory details, so I'll spare you them here.

Still though, I'm really proud for what we've been able to do: retrofit a compiler on top of a large base of informally defined interpreter semantics, expressed in code afloat on the internet. It's a pretty momentous refactoring effort.

I spoke at GUADEC briefly about Guile, in the impromptu lightning talk session. The story I really wanted to get out was not the details of Guile's compiler, but that Scheme is just one element of Guile. Elisp can exist there too, and Daniel Kraft's elisp branch seems to really be shaping up.

Of course, that's not to mention Daniel's brainfuck compiler, amusingly already merged as an example:

scheme@(guile-user)> ,L brainfuck
Guile Brainfuck interpreter 1.0 on Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc.

Enter `,help' for help.
brainfuck@(guile-user)> +++ +++ +++ +           initialize counter (cell #0) to 10
... [                       use loop to set the next four cells to 70/100/30/10
...     > +++ +++ +             add  7 to cell #1
...     > +++ +++ +++ +         add 10 to cell #2 
...     > +++                   add  3 to cell #3
...     > +                     add  1 to cell #4
...     <<< < -                 decrement counter (cell #0)
... ]                   
... >++ .                   print 'H'
... >+.                     print 'e'
... +++ +++ +.              print 'l'
... .                       print 'l'
... +++ .                   print 'o'
... >++ .                   print ' '
... <<+ +++ +++ +++ +++ ++. print 'W'
... >.                      print 'o'
... +++ .                   print 'r'
... --- --- .               print 'l'
... --- --- --.             print 'd'
... >+.                     print '!'
... >.                      print '\n'
... 
... ]
Hello World!
brainfuck@(guile-user)>

The example is from wikipedia. You can see that the brainfuck reader actually integrates with readline. Since brainfuck programs are normally terminated by end-of-file, we provide an alternate terminal: if ] (the loop terminator) is seen while not inside a loop, we stop reading the brainfuck expression.

Actually, I have to use a similar trick with the ECMAScript reader -- while the grammar does not require it in all situations, you have to terminate expressions entered at the REPL with a semicolon.

Anyway! Guile progresses apace. My favorite addition from the last release was a set of vector and bytevector instructions to the VM. Probably the biggest effect for existing users is that vector-ref and vector-set have their own VM operations now, and are thus much faster.

But the bit that I like is that there are now VM ops for bytevector refs and sets for packed values: everything from unsigned 8-bit values to 64-bit floats. It should make large-scale data processing feasible within Guile's VM, and it will make native compilation for those operations fairly direct and efficient.

Finally, hackwise, I implemented what Kent Dybvig calls "display closures" for Guile.

Before, all heap-allocated values (values that were captured by other procedures and values that were set!) were allocated in a linear list, and closure creation just mean consing together that list of heap variable state with your program code. You can think of this as a degenerate case of the ribcage strategy.

I guess I should be a little clearer. Consider this function, which should add a common prefix to all strings in a list:

(define (munge-strings list prefix)
  (map (lambda (x)
         (string-append prefix x))
       list))

Semantically, you could identify the variables with numbers and it would be the same:

(define (munge-strings <0,0> <0,1>)
  (map (lambda (<1,0>)
         (string-append <0,1> <1,0>))
       <0,0>))

Here the first index refers to the procedure in which the variable is bound, and the second is the nth variable in that procedure. Well this leads itself to a natural implementation of closures: in the function that is mapped, just capture the environment at that point -- then you can get to prefix just by looking back to the first variable in the 0th frame.

But you can do better than that. A variable that's not referenced in an enclosed lambda can just be allocated on the stack -- so list goes on the stack. prefix stays on the heap, though. And that's where Guile was...

...until I realized, via reading Dybvig's 20-year-old dissertation, that I didn't actually have to have environment structures on the heap at all. Closures could just capture the variables that they need into a vector for their own use.

Shared variables can be copied, there's no problem -- except if those variables are ever set!. So in that case, a condition you can determine lexically, you need to allocate those variables in "boxes". Getting and setting values is indirected through the boxes, but those boxes can live whereever -- on the stack in the function that binds the variables, or in the free variables vectors of closures.

This scheme has the advantage that more values can be allocated on the stack, free variable lookup is O(1), and you don't tie the garbage collector's anthropomorphic hands by holding onto parts of the environment that you don't need.

So that's the novelty for the upcoming 1.9.2 release, slated for 15 August. Then we'll have a 1.9.3 in the following month, and 2.0 in October. Like clockwork :)

like clockwork

Lyn Gerry continues her reading of The Ascent of Humanity on her radio show, Unwelcome Guests. It's fascinating, and challenging.

Charles Eisenstein, the author of The Ascent of Humanity, owes a large debt to Lewis Mumford, a historian of technology -- or "technics", as seems to be his preferred word. Eisenstein quotes Mumford liberally. It is by a happy coincidence that a friend of mine pushed Mumford's Technics and Civilization on me a couple months ago -- in exchange for Expect Resistance -- and it is shaping up to be a great, great work.

Regarding "clockwork", as a phenomenon and as a paradigm, Mumford has this to say:

The clock, moreover, is a piece of power-machinery whose "product" is seconds and minutes: by its essential nature it dissociated time from human events and helped create the belief in an independent world of mathematically measurable sequences: the special world of science. There is relatively little foundation for this belief in common human expreience: throughout the year the days are of uneven duration, and not merely does the relation between day and night steadily change but a slight journey from East to West alters astronomical time by a certain number of minutes. In terms of the human organism itself, mechanical time is even more foreign: while human life has regularities of its own, the beat of the pulse, the breathing of the lungs, these change from hour to hour with mood and action, and in the longer span of days, time is measured not by the calendar but by the events that occupy it. The shepherd measures from the time the ewes lambed; the farmer measures back to the day of sowing or forward to the harvest: if growth has its own duration and regularities, behind it are not simply matter and motion but the facts of development: in short, history.

In Reuleaux's definition, quoted by Mumford, a machine is "a combination of resistant bodies so arranged that by their means the mechanical forces of nature can be compelled to do work accompanied by certain derminant motions." But those bodies need not be mineral in nature; indeed, Mumford identifies the human industrialism necessary for the Great Works of the Pyramids as one of the first steps into the machine age: the reduction of man to the "resistant body" of the machine.

So it's interesting to think about the relationship of timekeeping to the mechanization of the human. The ringing of the bells, whether via water-clock or the dawn's early light on the crier's face, introduced discrete time to humanity, and so human activity began to be fit to those times -- cutting off the legs to to fit the bed, so to speak. Mumford continues:

Abstract time became the new medium of existence. Organic functions themselves were regulated by it: one ate, not upon feeling hungry but when prompted by the clock: one slept, not when one was tired, but when the clock sanctioned it. A generalized time-consciouesness accompanied the wider use of clocks: dissociating time from organic sequences, it became easier for the men of the Renascence to indulge the fantasy of reviving the classic past or of reliving the splendors of antique Roman civilization: the cult of history, appearing first in daily ritual, finally abstracted iself as a special discipline.

I've been having lots of dreams about Namibia recently. A common time reference where I lived there is etango peni: "sun where", literally. It's usually indicated with an outstretched arm pointing to where the sun should be, as in, we'll meet this afternoon when the sun is there.

I guess my concern is, to what extent is our obedience to the clock and to the calendar a life-affirming concern, and on the other hand, to what extent does it reduce us to "resistant bodies"? Do we exist in time, or do we exist in a use/used relationship -- to time, and to those that mark the time?

To tie it back to the more nargy concerns above, I think that time-based releases do have a positive effect on the Guile machine. And the Guile machine is a liberatory one -- in whatever trade, programming or otherwise, we should not grind our grist at the lord's mill.

But the greater questions that Mumford and Eisenstein raise make me wonder further about Guile work, not just relative to other systems, or relative to my desire to hack, but relative to the story of humanity -- Ascent or otherwise -- what does furthering this technology really do for life?

Unfortunately, I have no answers for that one. I'll let the tubes know if I find out. Until then, or likely sooner, happy hacking, for Life!

Syndicated 2009-07-26 21:48:06 from wingolog

guadec ho!

Does anyone have the address of the Mr and Mrs Vengaboy? I have a patch for them.

--- /tmp/were-going-to-ibiza.txt	2009-07-02 11:41:09.000000000 +0200
+++ /tmp/were-going-to-gran-canaria.txt	2009-07-02 11:40:53.000000000 +0200
@@ -1,8 +1,8 @@
 Whoa!
-We're going to Ibiza!
+We're going to Gran Canaria!
 Whoa!
 Back to the island!
 Whoa!
 We're going to have a party!
 Whoa!
-In the Mediterranean Sea!
+In the Atlantic Sea!

Anyone? Perhaps they have a Bugzilla somewhere.

* * *

I wrote to Federico earlier to let him know I was down for hippietime, saying I'd be at GUADEC from Saturday evening to Thursday at midday. He was surprised I was leaving early, which made me realize: why was I being so miserly with my time?

I think my thought was that somehow I couldn't afford to be away for so long, that maybe I should make it back and work the Friday. Ridiculous. I changed my flights so I'm leaving on Sunday instead. See you there, GNOME kin!

Syndicated 2009-07-02 09:42:50 from wingolog

the chosen one

Today I met up with an old friend I hadn't seen in a while, at the bar that he runs. Conversation was lovely. But that's not what I want to talk about.

On my way home, I rode on roads I hadn't been on in a while. I'm used to riding in the normal lanes, taking up the space of a vehicle, but they recently put in new protected bike lanes on these roads, so I decided to give them a try.

Most of Barcelona is laid out on a grid, with truncated corners. Like this:

   /------\ ^ ^  /------\
  /        \. " /        \
  |        |. " |        |
  |        |. " |        |
  \        /. " \        /
   \------/.  "  \------/
crossing *.   "
   /------\.  "  /------\
  /        \. " /        \
  |        |. " |        |
  |        |. " |        |
  \        /. " \        /
   \------/ . "  \------/
            . ^<- cars
            ^ <- bike lane

Streets are mostly one-way, alternating by block, and there are some larger arteries. The bike lanes that they put in are two-way, on the left of the cars. This means that every other block, cars will be turning into the bike lane -- a sure point of danger.

To compensate for this, the bike path designers made the bike lanes turn in at those dangerous crossings, and cross alongside the pedestrians. Cars are stopped at a light, in theory.

I suppose I appreciate the theory. In practice, it's a bit irritating to have to go the extra distance at the dangerous crossings. It slows you down, the curves present a danger of their own, and you make fewer lights. Sometimes there are times you could have caught the intersection if you were in a car lane, but the bike lane's light is red. Etc.

So when I came to about my tenth turnout, I looked around to see if there were cars, and seeing none, I decided to cut straight to the other side of the bike lane. I lined up my wheel with the rubber dividers separating the bike lane from the road, looked under my shoulder at speed, and accelerated across the intersection---

    ---into the air---

         ---to one of those brief moments of false clarity, the silent "shit!", the grasping rationality, the approaching pavement---

             ---the bounding up to look for cars---

                 ---the joke about it, ashamed of course, with the nearby parked scooter...

Apparently I didn't line up right with those damn rubber things. They're there to keep scooters out of the bike lane, but they have other effects.

My bike appears to be fine. Amusingly, the only lasting effect is that the left side of my handlebar has been bent back by about 15 degrees, which is one of the only parts that I haven't yet had to replace.

I would like to believe that in that brief aerial instant, that I executed some clever and graceful landing, informed by Aikido, but no, the evidence points elsewhere -- a skinned knee and elbow, a pedal-bitten calf, and two stigmata on the palms: perhaps a divine warning against hubris. The Lord does work in mysterious ways.

Syndicated 2009-06-16 20:53:01 from wingolog

in the beginning was the word

shamanic rites

You see, magico-religious thinking normally works. Whether it is a shamanic rite, the signing of an appropriations bill, or the posting of an account balance, when a ritual is embedded in a story that people believe, they act accordingly, playing out the roles the story assigns to them, and responding to the reality the story establishes. In former times, when a shamanic rite was seen to have failed, everyone knew this was a momentous event, signaling the End of the World, a shift in what was real and what was not, the end of the old Story of the People and the beginning, perhaps, of a new one. What, from this perspective, is the significance of the accelerating failure of the rites of finance?

We like to scoff at primitive cave-dwellers who imagined that their representations of animals on cave walls could magically affect the hunt. Yet today we produce our own talismans, our own systems of magic symbology, and indeed affect physical reality through them. A few numbers change here and there, and thousands of workers erect a skyscraper. Some other numbers change, and a venerable business shuts its doors. The foreign debt of a Third-World country, again mere numbers in a computer, consigns its people to endless enslavement producing commodity goods that are shipped abroad. College students, ridden with anxiety, deny their dreams and hurry into the workforce to pay off their student loans, their very will subject to a piece of paper with magical symbols ("Account Statement") sent to them once every moon, like some magical chit in a voodoo cult. These slips of paper that we call money, these electronic blips, bear a potent magic indeed!

How does magic work? Rituals and talismans affirm and perpetuate the consensus stories we all participate in, stories which form our reality, coordinate our labor, and organize our lives. Only in exceptional times do they stop working: the times of a breakdown in the story of the people. We are entering such times today. That is why none of the economic measures enacted so far to contain the crisis have worked, and why the current stimulus package won't work either. None go deep enough. The only reform that can possibly be effective will be one that embodies, affirms, and perpetuates a new story of the people (if we can agree on one)...

This from Money and the Turning of the Age, by Charles Eisenstein. I prefer the audio version while doing the dishes: harness the desire to scrub out capitalism!

Lyn Gerry has been doing readings from Eisenstein's book on her radio show, and it's really quite a compelling story. I like the episodic audio delivery of the book, but if that's not how you roll, the whole text is available online as well: The Ascent of Humanity.

There's something about Eisenstein's perspective that really feels right. To me, his work has the quality without a name.

fringe languages in barcelona

The other day Jao and I had lunch with another Schemer in the area, Jos Koot, and we decided it's well past time to have a fringe languages group here in Barcelona.

The name comes from a blatant rip-off of what the charismatic Conrad Barski does in DC. Here's what he has to say about FringeDC:

It is commonly believed...

...that most programming languages languages are essentially identical. However, anyone who has spent any significant time studying languages such as Lisp, Haskell, or Prolog knows that some of these uncommonly used languages not only are fundamentally different from more popular languages but can actually give you a glimpse into the future of mainstream programming!

If you think ideas such as Aspect Oriented Programming or Microsoft's new LINQ system in C# 3.0 or Declarative XML programming in .NET or C++ Template Metaprogramming are entirely revolutionary new ideas, you are mistaken: They are all innovative but also evolutions from ideas developed long ago in Lisp, ML and other older fringe languages...

There's a fine line between being on the leading edge and being in the lunatic fringe.
-- Frank Armstrong

So it's in that spirit that I'd like to invite all in the geographical vicinity to our first meeting on this Wednesday, 19 June. Jao has more details as to the first meeting, but in any case check out the new evil empire Google Group, Flibug.

Jao is on deck to talk about Factor and FUEL, Jos to talk about PLT Scheme's Redex operational semantics debugger, and we'll go out for beers later. Good times!

Syndicated 2009-06-14 12:28:31 from wingolog

hospitalized for approaching perfection

My god, June, June must be the most amazing month of the year. Things are green, and the awareness is palpable that summertime is here, in the street, at the bars, at the beach -- this is the time that is not the other time.

June is when strange and wonderful things happen. My sister, who lives in DC, called the other day to say she'd be here in Barcelona this weekend. Just on Sunday I was walking to the park and ran into an old friend I hadn't seen since 2000. June is the month of picnics: of picnics on the Seine, of picnics in the park, of picnics on the beach, of barbecues on terraces. June is for bare feet and open windows. June is for fireworks and music in the street.

hack

And yet, I hack, so much. I'm growing a little concerned, to be honest -- but now more than ever I feel like I'm doing my best work, and so I continue. It might be an illness.

In case you're new here, I've been hacking on Guile, an implementation of Scheme. Since my last dispatch, I landed a branch to Guile master that brings psyntax to the heart of Guile, as the default expander.

This was actually quite a feat, given the module hygiene work I wrote about earlier -- because how do you have an expander that understands modules and hygiene, before modules themselves have booted up? Anyway, it works now :)

For users, the practical implication of this is that syntax-rules and syntax-case are available, all the time. This is a lovely, lovely thing.

However, running the expander works against the most important performance hack of Guile 1.8: the memoizer. When you load a module, Guile 1.8 reads everything, but only does the minimum amount of work. For example, once it sees a procedure, it doesn't process the body of the procedure until the procedure is called. This reflects the reality that only a fraction of code is ever called, and was a big win for Guile 1.8.

But in Guile 1.9 / 2.0, we lose this advantage, as the expander does traverse all code. Of course, if your code is compiled already, it needs no expansion so loading is very very fast, but Guile has a lot of users and existing code out there, and I don't think they'd be particularly pleased if an upgraded touted to speed up their programs actually slowed them down.

So, for that reason, I hacked in some automatic compilation support, and turned it on by default. The upshot is that if Guile sees a file for which it can't find a corresponding compiled version, or the compiled version is out of date, it will compile it then and there -- and stash away the result, so it will be found the next time.

Of course, figuring out how to find the compiled files, and where to put the cache, but how to keep supporting shared installed architecture-specific compiled files, and how to cope with lack of permissions to write the compiled files, or errors in compilation -- you know, it's like Steve's legalizing marijuana. The devil's in the details. Hopefully I have things ironed out now, though. After all, if Python can do it...

Historically, expanding Guile Scheme with psyntax has had a couple more problems, though: the original variable names would be lost, due to the alpha renaming I discussed before; and, you lose source location information, so you don't know where backtraces come from. Through a stroke of luck and wine-induced hubris (thanks Ángel!), I did manage to plumb that information through, which is really pleasing.

(If you're still with me, I understand you are a programming languages enthusiast. Well to you I say: be wary of the verb "plumb". It suggests something shitty either about software of the process of making it. But I am willing to describe my interactions with psyntax as, indeed, shitty.)

(Continuing the parenthesis though -- are there not those that have a Freudian delight in shit? Whenever I hack psyntax I do feel better afterwards. It's a strange powerful relieved feeling.)

...

Perhaps the most relevant update from the last month in Guile is that we fixed a 2.0 release date, on the 15th of October; and we'll be releasing monthly until then, starting on the 19th of this month.

Also, Guile is finally joining the Unicode-speaking world, thanks to Ludovic Courtès and Mike Gran. We're using the little-known libunistring to do the heavy lifting; if there are packagers out in the audience, let this be my call to you to package this for your distros. It's by Bruno Haible, really well-done, and has been in Gnulib for a while now. It's time for it to go to distros.

Anyway, enough blathering for this Monday night. I was prompted into this by a fit of despair, looking again at the Waddell/Dybvig inlining algorithm. Perhaps after a more composed encounter with that paper, I'll have some novelties for the ether. Until then, happy hacking!

Syndicated 2009-06-08 21:30:05 from wingolog

307 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!