<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
    <title>Olifante's Lair</title>
    
    <link rel="hub" href="http://hubbub.api.typepad.com/" />
    <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/" />
    <id>tag:typepad.com,2003:weblog-16557</id>
    <updated>2009-05-27T22:13:33+01:00</updated>
    <subtitle>Bits and snacks for hungry minds</subtitle>
    <generator uri="http://www.typepad.com/">TypePad</generator>
    <link rel="self" href="http://feeds.feedburner.com/olifanteslair" type="application/atom+xml" /><feedburner:browserFriendly></feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
        <title>Transcript of Rich Hickey interview</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2009/05/transcript-of-rich-hickey-interview.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2009/05/transcript-of-rich-hickey-interview.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-67340159</id>
        <published>2009-05-27T22:13:33+01:00</published>
        <updated>2009-05-27T22:13:33+01:00</updated>
        <summary>InfoQ have recently published a video of a very interesting interview with Rich Hickey, creator of the Clojure programming language. Conveniently, they also offer a transcript of the entire interview, but as is costumary with their transcripts, it is placed...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>InfoQ have recently published a video of a very interesting <a href="http://www.infoq.com/interviews/hickey-clojure">interview with Rich Hickey</a>, creator of the <a href="http://clojure.org/rationale">Clojure</a> programming language. Conveniently, they also offer a transcript of the entire interview, but as is costumary with their transcripts, it is placed inside a very small text field, making for very awkward reading. Here's a copy of that transcript:        </p><blockquote><p>Q: We are here at QCon London 2009, with Rich Hickey. Rich, who are you?</p><p>A: I'm the author of Clojure. I'm an independent developer, contractor, consultant and, basically, a practitioner. I'm not a researcher.</p><p>Q: What brought you to create a Lisp? Do you go out in the morning and say "Hey, I'm bored! Let's create the Lisp!"? What's the intention behind it?</p><p>A: I don't think I necessarily set out to create a Lisp specifically. I set out to create a language to only deal with the problems I was contending with in Java and C# for the kinds of applications that write, which are broadcast automation and scheduling and elections systems and things like that, where there is a lot of concurrency. I found just object oriented programming and their approaches to concurrency of those languages is just not good enough for those kinds of problems - they are too hard. I'm a big fan of Lisp and the other functional languages and what I want to do is solve those problems, make a practical language, not to have to program in Java anymore.</p><p>Q: It sounds like a good idea. You mentioned a thing you had a problem with: object oriented programming. Is that the right way to say that?</p><p>A: Yes. Not with the idea behind it, but the realization of object oriented programming in the pragmatic languages that are used today have some problems definitely for concurrency because the way objects are done encourages mutable state and that's just - I think - in direct conflict with the solutions we need for concurrency.</p><p>Q: Are you more interested in object oriented model that is closer to what Erlang does, sort of an actor style, or like Common Lisp, or what would you be interested in? Would you say you use object oriented programming?</p><p>A: I have, sure. A lot of Clojures abstractions are defined with Java interfaces, so I think interfaces are a neat thing and one of the better parts of Java and of object orientation. I haven't thought a lot about how I would do objects in Clojure or immutable objects, but it's possible, for instance right now, in Clojure to define Java objects that are, in fact, only mutable inside transactions. It's possible to bridge the 2 worlds, but the big problem is less with objects than it is with mutability. Even if you set concurrency aside, when you build a large program with objects, you end up with this giant graph of interconnected mutable things and that's just a very hard thing to understand and maintain - that's what I want to get away from.</p><p>Q: You mentioned transactions, which brings us to STM - Software Transactional Memory. What's your elevator pitch for STM?</p><p>A: I don't know that I have one. I don't actually want to be an evangelist for STM. I think one of the problems we have today in talking about STM is that we say "STM" and presume that means something in particular, but there are many flavors of STM, there are many different objectives in STM designs. I think there is a fair amount of research oriented at making STMs that allow you to essentially program the way you do today and magically put transaction, start and end around it and everything will be OK. I don't have high hopes for those approaches. Then, I think there are language specific approaches, like that in Haskell, that are really nice and elegant. Clojure is quite different from both of those. I don't think STM labels anything other than the general approach of trying to say "We are going to contain mutation inside some sort of a scope." What does that mean? That's not an elevator pitch, is it?</p><p>Q: What's your elevator explanation of STM? What's would be a short explanation of what goes on in your STM implementation? What happens?</p><p>A: Good things happen. Essentially, what STM allows you to do is to have the language provide a construct that handles the hard parts of coordinating change. Fundamentally, transactions are about the harder class of changes. It's pretty easy to make language features that deal with atomic change. We change this one thing and it doesn't have to be coordinated with anything else, but when you have coordinated change, you want to say "I want to move this object from one collection to another and not have it appear in both and not have it disappear from both", you need to coordinate that change into 2 things within a single logical unit of work. Typically, in the absence of something like transactions, the management of that falls on the programmer, with locks or some technique like that. I guess the short pitch for STM is it allows you to do coordinated change without the complexity of locking.</p><p>Q: Can STM throw threads or should it be on the same thread all the time?</p><p>A: Transaction happens in one thread, but multiple transactions can be occurring on multiple threads.</p><p>Q: Is it possible to implement it on several threads because it could solve some problems in the web? We have several requests and, if we could span transactions to several threads, it could solve some problems when we have partial states on several requests coming from the web. Do you think it could be possible to span several threads with the transaction?</p><p>A: A single transaction? You could always take some of your work in a transaction and parallelize it - that's possible right now -, but the other threads are not coordinated with the transactional data. You can calculate your answer in multiple threads and then use the transactional thread to commit it.</p><p>Q: About STM again: is there any label for your STM? Is there any keywords that describe the STM? I saw you had the acronym MVCC.</p><p>A: There are a couple of things that I think distinguish Clojure STM. The first is it's not designed to solve the problem of "Let me do what I've always been doing, which is I've designed an object and it has 6 fields in it and I'm going to independently access those fields at different times." In STM transactions it's going to encapsulate any access to those pieces and make a single unit of work. Instead, the Clojure model is definitely oriented towards programming with values, so it's a functional style model. What we'd like to do is say that what would have been an object is going to be an immutable value and instead the STM cell is merely a reference to an immutable value. Once you do that, you can do a couple of things. First of all, that's a more coarse-grained STM and Clojure is definitely more coarse-grained. The other thing is once you start working with immutable data structures that are persistent it's because they are persistent. Making is inexpensive and keeping all the versions around is also inexpensive. What multi-version concurrency control does is it will actually keep older versions of some references around in order to satisfy read-transactions and allow write-transactions to progress. That multi-version concurrency control served a database technique is used by databases where they would keep records around in order to satisfy longer running transactions and allow new writes to continue.</p><p>The advantages of multi-version concurrency control are you don't need to do read-tracking, so you don't need to keep a record in the transaction of what was read, you only need to keep a record of what was written. The other thing is that writers don't impede readers, so there is actually a lot more concurrency, I think, in multi-version concurrency control. That's what distinguishes Clojures, because your references are the persistent data structures. It's inexpensive for me to keep older revisions and I determine how many to keep dynamically; therefore, you get a lot more concurrency.</p><p>Q: You talked about readers not impeding writers. Does that mean if I read from a reference, which is the STM construct you use, there is no locking? Is that right?</p><p>A: No, there is locking inside the implementation. What there isn't is a sequencing. It isn't like a reader has to wait for a writer or a reading transaction is going to have to really start to the activity of a writer. That will only happen if there is insufficient history and as that happens, the history grows to accommodate that read pattern.</p><p>Q: You already mentioned persistent data structures. Maybe you could give a short explanation?</p><p>A: They are immutable. Generally you talk about them as collections, so you consider it an immutable collection, where making copies is inexpensive, so, instead of changing the collection in place, they are going to produce a new collection, so it's functional, but there are a couple of characteristics that have to be guaranteed by that. First is that the old version still has to be accessible after you've made a changed version. The others, that both the old and the new version meet the performance guarantees you would expect from that data structure. There can't be full copying going on because that would violate the performance guarantees of log(n) or whatever your expectation was for that data structure. Most functional data structures are persistent in that way, but you could make a naïve one that was just copy on write - that wouldn't be persistent.</p><p>Q: You offer persistent Data structures for vectors?</p><p>A: Vectors and HashMaps and Sets and all the good stuff.</p><p>Q: Do they have the same access characteristics as the Java collections?</p><p>A: They have similar access characteristics. I mean, technically, a Java collection HashMap or ArrayList is going to have constant time access and Clojure access is not technically constant time, but the trees that are used are extremely shallow. You can say "OK, technically it's O( log n), but if it's never more than three hops from my huge data structure, maybe I don't care anymore about that." In other words, constant factors matter.</p><p>Q: You mentioned in your talk yesterday about Clojure that you had agents and references and atoms. What would you call them? Concurrency primitives?</p><p>A: They are all called the reference types in Clojure but they are essentially all the boxes that refer to an immutable thing. Each has a different way of managing time and how things are shared.</p><p>Q: You said you had 4 right now and you were going to add a 5th? Could we have the exclusive information: what's the 5th one?</p><p>A: The 5th will probably be some flavor of a Safe Mutex. Right now the way atoms work is they work a little bit like transactions and that you are going to have atomic access to an individual thing, so you are going to maybe get to run some work and attempt to put the results of that work back in the atom, but you may not succeed because someone has intervened. Your work will get re-done. There are cases in which that's fine. It's actually very fast to do, but there are other cases in which you really only want that work to ever happen once, which means that you not only have to encapsulate the change to the cell, but encapsulate the work within some sort of a boundary.</p><p>That's what locks are traditionally used for, but the problem with locks is they can nest and then you have lock order acquisition problems. I have a few ideas for doing mutexes. The simplest of which would be just to disallow a subsequent acquisition, so non-nestable Mutex - it's a handy primitive thing. It just keeps you from making that mistake. Other possible flavors of that kind of reference cell would be once where you have declared order. The API could enforce lock acquisition order. I haven't really thought about the more involved Deadlock detecting ones, but that is also a possible thing to make a primitive that would have Deadlock detection.</p><p>Q: One of your constructs is agents. What's a short explanation for agents? What do you use them for?</p><p>A: Agents are similar to actors, some more to the actor model. The difference is that they are designed as all the rest of the concurrency primitives for the same process problem. In not being distributable, you have one additional feature you can add to actors, which is direct access to the state, without sending and waiting for a message cycle. I think that's an important facility to have in process, because otherwise you are competing with concurrency primitives that allow that kind of access.</p><p>I don't think readers should have to wait for writers as a general rule, I like constructs that don't enforce that. An agent is something that is asynchronous. You say it manages its own state, it's completely independent; you can't coordinate change amongst agents. Like the other constructs, you make a change by sending it a function and maybe some arguments and that function is going to be applied to the state of the agent and become the new state of the agent. The thing about agents is that they are asynchronous. You ask for this change to be made and you return right away; at some point in the future, the change will be made in a thread pool.</p><p>Q: So agents are reactive?</p><p>A: You can build systems that appear like reactive systems. You can use them for event style programming - things like that. Once you embrace concurrency and asynchrony, this is a nice model to have, where things are genuinely independent.</p><p>Q: I saw a thing on the news group or your mailing list that some people are working on the implementation of cells, which is - I think - a GUI framework using data flow methods?</p><p>A: Cells is like program spread sheet reactive programming data flow thing from common Lisp. That kind of programming is really easy to do in Clojure. The traditional models have been highly synchronous - make change to data once you flow through a network. What I'm excited about is the potential for concurrent designs for those kind of things, but the infrastructure is in place so that you can attach a notification function to any of the reference types and be told when they change - that sort of low level plumbing that you can use for any number of different reactive programming techniques because you can find out about change. In addition, it allows you to make orthogonal decisions about the management of something. Then, who cares about that? They don't need to know about each other.</p><p>Q: You said "concurrent implementation of cells or of these features". What do you mean by that?</p><p>A: What I mean is being amendable to the fact that multiple threads of control could be modifying the network of cells at the same time.</p><p>Q: Let's move on to some other language features in Clojure. I saw a very interesting feature called metadata. What do you do with it? How do you use it?</p><p>A: Clojure uses it specifically for type hints and for communicating to the compiler. The general problem it solves is this: Clojure programs are represented as data structures. You write those data structures in a file, potentially, and that gets read by the reader and the data structure is presented to the compiler. That model is really nice, but there are often other things you would like to communicate. For instance, it would be nice to communicate the line numbers from that file, which would have to have some place to go on those data structures, but they are not part of the data, they are really about the data.</p><p>I got this data structure from line 27. So that begs the question for metadata, so automatically Clojure needs metadata. It ends up being a really handy way to extend the way the programmer can communicate about the program without really changing the syntax of the language. For instance, they can also use metadata to adorn some symbols in their code to provide type hints to the compiler, which can be used to optimize calls to Java to make sure they are not reflective. What I did is, instead of just making their language syntax for annotations talk to the compiler something very specific, I made a general way to put metadata on data. Now you can use it for line number, you can use it to communicate with the compiler and it's generally available to programmers to use for whatever they invent. The use of metadata is open, it's not dictated by a language and there are lots of interesting things you can do because you always have metadata. I got this piece of information from the Internet, from a trusted source, from an untrusted source. It's not going to be valid after the state. Those are all things about data that are not the data itself, now they have a place to live.</p><p>Q: That's an interesting feature, because the language is like Perl or Ruby who have the "tainted" feature. If you get a string or data from the net, its marked as "tainted" It's a special feature in String or wherever it's defined, so you could do that with metadata.</p><p>A: Right! Not for strings, though.</p><p>Q: Do you currently support metadata on symbols?</p><p>A: Symbols and Clojure collection types.</p><p>Q: Did you plan to add it more constructs or will that be limited?</p><p>A: I guess you do have metadata on the reference types and you also have metadata on name spaces, so I've added it to a couple of things. I can't edit the things I can't control. String would be one of those things.</p><p>Q: Because string is the native string type in Java.</p><p>A: Yes, it's the native string from Java. I don't own it.</p><p>Q: Would that be the same for numbers?</p><p>A: Correct - the same thing for numbers.</p><p>Q: Metadata is always just data, it never directly influences the evaluation of the code, at least for Clojure?</p><p>A: Like I said, you can use metadata to communicate with the compiler if you adorn your original source forms with metadata, but during the running program, right now, the metadata is not used. There actually is a new library function that uses some metadata if it's available. A lot of people are using metadata as a convention to tag things with what would have been types in other languages. There is some library support for finding out those types and if there are other common usages of metadata, they may work their way into libraries, but no, generally it's transparent and it's certainly transparent to the operational semantics of the value types themselves. In other words, metadata does not participate in value comparisons - equality, for instance.</p><p>Q: Moving on to another feature that brings polymorphism to Clojure, multimethods - to an object oriented programmer, how would you explain multimethods?</p><p>A: When you think about polymorphism, generally you are thinking about some Runtime dispatch. Something different happens at Runtime, depending on some characteristic of the object. It ends up that in object oriented programming languages like Java and C#, there is only one thing that can be a criteria for something different happening and that's the class or type of the object. A general way of thinking about that is saying you have a method call and it involves an object and some arguments and the actual dispatch is going to differ, depending on the type of this.</p><p>You can generalize that and that was done in common Lisp to say it might be interesting to have things be polymorphic based upon more than just the first arguments. So, we are no longer considering the first arguments to be special and we'll allow you to take some call and look at all the arguments and do something based upon all the arguments. There too, though, there are some things that are hardwired, for instance, in common Lisp you can only dispatch on either the type of arguments or their values. You can say "If it's equal to this or if it's of this type do this", but you can do it for any or all the arguments. Again, we are talking about dispatch based upon some function of the arguments.</p><p>Clojure multimethods are just another level of that same logic, in fact they are a realization of the last sentence I just said. They are dispatch based upon an arbitrary function of the arguments. You define a multimethod and you say "Here is a function of the arguments I'd like you to use" You could look at the first argument, you could look at the 5th, you could look at all of them, you could look inside them, some member of an argument, it could look at the types or not or the values. Now, you could look at relationships between arguments, you have dispatch based upon an arbitrary function of the arguments and you have a vastly wider set of polymorphic possibilities than you had before and it's quite powerful. In particular, it allows you to do Runtime dispatch on Runtime attributes. You don't usually represent something like being hungry as part of something's type, it's some attribute that it acquires while the program is running or being outdated or things like that. Now you can access those things and you can do things polymorphically based upon that and take a lot of switch statements out of your code.</p><p>Q: How does the dispatch function work? What does it return? Does it find a function to execute or how does it work?</p><p>A: It does not go directly. There is a dual dispatch. The dispatch function is determined at the time you write a multimethod you say "This is the function that will be applied to the arguments" Its value, the return value of that function gets mapped to the function that it will actually execute. The dispatch function gets called on the arguments, it returns a dipatch value and when people make different instances of the multimethod - actual methods - they say "When a dispatch function returns this value, here is the code to call" That's generally how it works.</p><p>The only additional feature that's in there, which is that the dispatch values are not matched with plain equality, instead they are matched with a sort of a generic hierarchical isa? test, which gives you also the hierarchical capabilities that you expect with polymorphism. Instead of just saying "Is the dispatch value this exact value" you can say "Is the dispatch value of this type of value?" Then Clojure has an a la carte hierarchy system where you can define hierarchies of names essentially. The thing here is, as it's typical of Clojure, lots of nice features bundled together in languages. You have object systems that do hierarchy and do dispatch and it's all munched together and you can't get polymorphism independent of types and hierarchy Clojure delivers polymorphism a la carte, hierarchy a la carte. You can put them together how you like.</p><p>Q: You mentioned this isa? function, which is basically for checking equality between these symbols?</p><p>A: It's a hierarchical test. For instance, when used with Java classes, it does the typical test for the class relationships. If they're derived from another. Because you have these a la carte hierarchies, you can just compose arbitrary hierarchies of names and say "Fred is a plumber". Then, if you say "You do this when I get a plumber", it actually is of Fred, he'll do the plumber job. It's effectively just hierarchical classification. Because it's not bound to types you can have as many taxonomies as you like - different taxonomies for different class libaries and situations.</p><p>Q: Can I modify this isa? too or is that hard coded for these hierarchies and Java classes?</p><p>A: It's hard coded for the hierarchies and the Java classes right now.</p><p>Q: What kind of hierarchies can you define? Can you define multi-inheritance?</p><p>A: Yes.</p><p>Q: Can you define graphs, too or just trees?</p><p>A: No cycles.</p><p>Q: Dispatching on several parameters of the function when you call it and you have hierarchies and you get more chances to find more than one candidate for the call, how do you reason about which one to choose and what to do with it?</p><p>A: If it can't be resolved, then nothing will be chosen, but the programmer has a way to say "Prefer this to that". If you create relationships that inherently have non-resolvability and then you call with this set of parameters that can't be resolved - I can't tell it will be this situation or that situation, neither dominates the other - the programmer can say "Prefer this situation to that. Given these 2, this is preferred." and, therefore, it answers explicitly what happens in that situation and that becomes part of the dispatch logic. You say it once and it remembers that.</p><p>Q: Can the dispatch functions see all the dispatch values that have been defined for multimethod so it can build a more efficient way of lookup?</p><p>A: That's premature optimization because, hopefully, I'm doing a good job of caching the results of lookup and you wouldn't need to do that, but there are reflective mechanisms to look at the contents of the dispatch table. I don't know if it would be a good idea to do that inside the dispatch function, but it would be possible.</p><p>Q: Clojure works currently on the JVM, but I think there are other implementations for Clojures or ports?</p><p>A: Yes, there are a couple of ports inside the Clojure community, which is approved and being nurtured. One is a port to Java Script, it's called Clojure Script, it was done by a contributor and that essentially compiles Clojure to Java Script. He's done a really nice job. It actually compiles Clojures core bootstrap library directly and the support for some or most of the persistent data structures in Java Script implementations - not all of them, but your source code can run there. The only thing that's not there is obviously the concurrency because there is no threads. In the others, a port to the Java core underpinnings to C#, which then lets Clojure run on the CLR.</p><p>Q: The Java core or the Clojure core?</p><p>A: The Java part of that underlies Clojure and needs to be ported in order to run on a different platform, so that's been ported to C#, but directly from my sources. That's a good port and it's called ClojureCLR and it's still early days there, but the guy who's working on that has got some impressive results - he's got the ant concurrency demo running on .NET in Windows form, so that's pretty neat.</p><p>Q: Is Clojure written in Clojure or in Java source code?</p><p>A: Both. There is a set of the collection classes and some of the interfaces and the compiler itself written in Java and that was used to bootstrap the language and the language is primarily defined in terms of itself from there. Like any Lisp there are 7 primitives and everything else is built with macros and other functions on top of those primitives. That's the current architecture. Maybe, in some parallel universe, where I have more hours on a day, I'll go back and reimplement the parts that are in Java in Clojure to make it easier to do ports and easier to change. Obviously, the Java side is kind of hard to work with, but the advantage of the Java stuff being in Java is a lot of Clojure's - very accessible. If you never end up programming in Clojure, the data structures and the STM and the reference types are all accessible from Java and there are Java interfaces for everything so there are a lot of advantages to do that. Even if I re-did it in Clojure, I'd make sure the accessibility of those things from Java was as good.</p><p>Q: You have ahead of time compilation - AOT - with Clojure. What happens if AOT compile something? Do you still need a Clojure Runtime for that or are the class files that it creates self-contained?</p><p>A: In most Lisps, the whole notion of a Runtime is intimately there. Right now, Clojure's packaged in a single jar and you would need that jar any place you delivered Clojure. What you would not need if you had a time compile is the compiler - right now, there isn't a way to extract the compiler. The other thing you wouldn't need is the dynamic class loader. What ends up happening is they sit there, but you don't use them. The advantage of not using them is in environments where you can't use them. For instance, if you want to run on android, you don't really have a bytecode loading there of Java bytecode or if you want to run in an app where you are not allowed to if you are not signed. You can't get to both of those targets, but there is not much to take out the parts that you wouldn't need yet.</p><p>Q: What kind of capabilities do you need for implementing Clojure? If you have things like STM, do you need special concurrency features, do you need some kind of atomic instructions or anything like that?</p><p>A: If you wanted to move Clojure to another platform, other than Java or .NET, you would need some substantially similar capabilities to Java. Clojure certainly relies on some threads, it uses java.util.concurrent.Atomic quite a bit and locks, of course. You need the basics there. It's nice to have a memory model or something that determines what happens; is there a notion of volatile, is there a notion of final? - some equivalents to those things to get full Clojure.</p><p>Q: Currently, at the time of this recording, Clojure is not 1.0 yet. What would be the features that would make it 1.0? what are you going to add, what are you going to modify to go to 1.0? When do you declare it 1.0, to put it this way?</p><p>A: I'm still working on making 1.0 mean something other than making people happy to see 1.0. Generally, Clojure is pretty stable between releases and I think I've gotten into a set of changes that would be breaking behind me. Now, that we are going to enter a long period of stability, it might be worth labeling what happens now as 1.0, but it doesn't have a very stepped growth pattern. It's a very round growth pattern, so I expect that to continue. One of the nice things about Lisp and about Clojure is that you don't really go back to the compiler and change things substantially, you change just syntax and you don't need to be there. Most of the changes and most of the enhancements come from library and most of them take the forms of just additions. Today you have something new that you didn't have yesterday, but it doesn't break anything that you are already doing. I am interested in labeling 1.0 sooner rather than later to help out. There is a book coming out that Stuart Halloway is writing, which refers to Clojure 1.0.</p><p>Q: You were recently doing some work on redefining the way laziness works, streams work. What's the current status of that? What the current idea of laziness in Clojure?</p><p>A: Clojure is not generally lazy, and the only thing that it has is a sequence model that supports sequences being defined that are lazy. It ended up that that model came from an abstraction of Lisp's list model, the cons cell model, saying just first an rest, just kind of nice model and you can define very many things on top of those two. But it ends up that in Lisp, rest is eager because it returns nil if there's no more stuff, which means it doesn't return a logical list, it returns a concrete thing. That's my first implementation worked that way, which meant that, while you could make the ultimate production of the entire list lazy, in other words, overall in aggregate you're not going to produce more than you need, you do produce at least one cell in order to know whether or not you are empty. That ends up making some things awkward, so is a big trade off though for Lisp because the ability to know there is nothing, that's testable on the conditionals, so you can write some really elegant and succinct code by using that - it's called nil punning.</p><p>It ends up there as just a hard trade off: you either can have nil punning or you can make lists and sequences fully lazy. In other words, I have something, may be there is a first item, maybe there isn't, and I won't force the issue about that until I examine it. After a year of experience and some feedback, I decided to go for fully lazy and essentially lose nil panning in a lot of contexts. The advantage of that is it becomes a lot easier to reason about things and you can concatenate things and not worry about being one ahead of yourself. Essentially, the only enhancement was that, now, that can be fully lazy. You need not consume any resources that you don't desire.</p><p>Q: I think you previously mentioned type hints on functions. I think I saw something about Clojure being able to do fast math or compile to fast math in Java - how does that work? How fast can you get?</p><p>A: Inside a function, so not across a function call boundary, you can get exactly as fast as Java. Essentially, the functions called boundaries in Clojure are object based, so anything that crosses a function called boundary is going to be boxed and there are no optimizations around that currently. Within a function, you can declare that a local variable is an int or a long and it will have the Java representation of int or long. The one advantage is you move to and all the arithmetic that you use within that will now use the primitive operations. The one enhancement to that is that by default, declaring it primitive does not give you bad arithmetic. In other words, the math is still checked, so overflow checks are there. Then finally, if you want to go pedal to the metal you can explicitly call big ugly unchecked add function, which will do a wrapping, a call, but you get substantial speed even with the overflow checking in because it is still primitive in there. That's very fast and can be exactly fast as Java if you use unchecked it's just the same bytecode.</p><p>Q: I say some variable is an int, 32 bit in, but you still do you the overflow check. Do you have a number tower in Lisp? Does it expand the width of the type or do you just have type int?</p><p>A: Normally yes, there is automatic growth to the next size. If you overflow ints you normally get long, if you overflow long you normally get BigInteger and you don't do anything. That's the normal way arithmetic works in Clojure. So in this case, when you saying "I want an int", what happens is I can't represent an int and a BigInteger in the same type in Java. It now is an int, but if you do an operation that would overflow, it throws an exception instead of promoting it. If you are going to say "I want to use ints" you have to make sure you don't overflow but you'll get an exception by default instead of bad numbers. There are three different flavors: automatic growth, checking and Java free for all math.</p><p>Q: What do you use to implement Clojure? What kind of tools do you use?</p><p>A: Nothing very fancy. I'm a big fan of IntelliJ and that's what I use for all the Java parts. Then, for Clojure code editing right now I'm still using Aquamacs, Emacs. There is a nice Clojure mode for that; I don't use SLIME or any of the fancier things that people have. And that's basically it. I'm looking at both the plug-ins for IntelliJ and NetBeans and both are growing rapidly, and I think they are really neat and will quickly pass Aquamacs in terms of being able to integrate with the Java part of the job. For instance, both have completion that does Java completion in addition to Clojure completion in the same space. That's an absolute "when". As soon as they have that stuff working, that's going to be a better place to write Clojure code.</p></blockquote></div>
</content>


    </entry>
    <entry>
        <title>Gaza Gazebo</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2009/01/gaza-gazebo.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2009/01/gaza-gazebo.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-61902532</id>
        <published>2009-01-26T04:00:08+00:00</published>
        <updated>2009-01-26T04:00:08+00:00</updated>
        <summary>Uploaded a new (very short) piano piece to Alonetone, called Gaza Gazebo. This piece is dedicated to the victims of the 23 day assault on Gaza. This piano piece is Copyright © 2009 Tiago Castro Henriques, some rights reserved Gaza...</summary>
        <author>
            <name>olifante</name>
        </author>
        
        
<content type="html" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;Uploaded a new (very short) piano piece to Alonetone, called &lt;a href="http://alonetone.com/olifante/tracks/gaza-gazebo" title="Piano piece by Olifante"&gt;Gaza Gazebo&lt;/a&gt;. This piece is dedicated to the victims of the 23 day assault on Gaza.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-size: 10px; font-family: 'Trebuchet MS';"&gt;This piano piece is Copyright © 2009 Tiago Castro Henriques, &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license"&gt;some rights reserved&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.flickr.com/photos/rwhitlock/3207753926/" title="photo sharing"&gt;&lt;img  src="http://farm4.static.flickr.com/3125/3207753926_0fd27ddac7_m.jpg" alt="" style="border: solid 2px #000000;"&gt;&lt;/a&gt;&lt;br&gt;&lt;span style="font-size: 10px; font-family: 'Trebuchet MS'; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/rwhitlock/3207753926/"&gt;Gaza Funeral Procession Sylvester Park Gazebo&lt;/a&gt; &lt;br&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/rwhitlock/"&gt;Berd Whitlock&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
</content>


    </entry>
    <entry>
        <title>Teatime at the Jockey Club</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2009/01/teatime-at-the-jockey-club.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2009/01/teatime-at-the-jockey-club.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-61562810</id>
        <published>2009-01-19T01:43:09+00:00</published>
        <updated>2009-01-19T01:43:09+00:00</updated>
        <summary>Uploaded a freshly composed piano piece to Alonetone, called Teatime at the Jockey Club. My other piano pieces are also available there. Copyright © 2009 Tiago Castro Henriques, some rights reserved</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Music" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Uploaded a freshly composed piano piece to Alonetone, called <a href="http://alonetone.com/olifante/tracks/teatime-at-the-jockey-club" title="Piano piece by Olifante">Teatime at the Jockey Club</a>. My other piano pieces are also available there.</p>

<br />
<embed allowfullscreen="true" allowscriptaccess="always" flashvars="&amp;file=http://alonetone.com/users/olifante.xml&amp;height=140&amp;width=400&amp;frontcolor=0x3C3C3C&amp;backcolor=0xf3f3f3&amp;lightcolor=0xFF944B&amp;screencolor=0xFF944B&amp;displaywidth=120&amp;showdigits=false&amp;showdownload=true" height="140" src="http://alonetone.com/flash/alonetone_player.swf" width="400" />

<p><span style="font-size: 10px; font-family: 'Trebuchet MS';">Copyright © 2009 Tiago Castro Henriques, <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license">some rights reserved</a></span></p></div>
</content>


    </entry>
    <entry>
        <title>Support Wikipedia</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/12/support-wikipedia.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/12/support-wikipedia.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-60408942</id>
        <published>2008-12-24T17:34:52+00:00</published>
        <updated>2008-12-24T17:34:52+00:00</updated>
        <summary>Donated $30 to Wikipedia, a pitiful sum compared to how much I get out of it. "Imagine a world in which every single person on the planet is given free access to the sum of all human knowledge." — Jimmy...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Donated $30 to Wikipedia, a pitiful sum compared to how much I get out of it.</p>
<p>
<a href="http://wikimediafoundation.org/wiki/Donate/en"><img border="0" alt="Wikipedia Affiliate Button" src="http://upload.wikimedia.org/wikipedia/foundation/3/36/2008_fundraiser_square_button-en.png" /></a>
</p>
<p>"Imagine a world in which every single person on the planet is given free access to the sum of all human knowledge."<br />— Jimmy Wales, Founder of Wikipedia</p>


</div>
</content>


    </entry>
    <entry>
        <title>Fidec</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/09/fidec.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/09/fidec.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-56051728</id>
        <published>2008-09-24T01:03:55+01:00</published>
        <updated>2008-09-24T01:03:55+01:00</updated>
        <summary>Fidec, a piano piece by Olifante</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Music" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Here's a new piano piece, dedicated to no one in particular.</p>

<p><a href="http://www.flickr.com/photos/olifante/2883776450/" title="Fidec"><img src="http://farm4.static.flickr.com/3241/2883776450_52a44ed0c8_m.jpg" width="240" height="240" alt="Fidec" /></a></p>

<script src="http://mediaplayer.yahoo.com/js" type="text/javascript" />

<p><a href="http://olifante.blogs.com/covil/files/Fidec.mp3">Fidec</a></p>

<p><span style="font-size: 10px; font-family: 'Trebuchet MS';">Copyright © 2008 Tiago Castro Henriques, <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license">some rights reserved</a></span></p>
</div>
</content>

        <link rel="enclosure" type="audio/mpeg" href="http://olifante.blogs.com/covil/files/Fidec.mp3" length="unknown" />

    </entry>
    <entry>
        <title>TweetDeck vs. Twhirl</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/09/tweetdeck-vs-twhirl.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/09/tweetdeck-vs-twhirl.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-55981372</id>
        <published>2008-09-22T18:40:53+01:00</published>
        <updated>2008-09-22T18:40:53+01:00</updated>
        <summary>Comparison of TweetDeck and Twhirl, two Twitter clients for OS X</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p><strong>(scroll to bottom for Iain's reply to my nits with TweetDeck)</strong></p>

<p>Earlier today I <a href="http://twitter.com/olifante/statuses/930416745">lamented on Twitter</a> that I get an error whenever I try to favorite a tweet using <a href="http://www.twhirl.org/">Twhirl</a> or <a href="http://www.tweetdeck.com/">TweetDeck</a>, my favorite and 2nd favorite Twitter clients for OS X. Shortly after, a Iain Dodsworth replied, pointing out that TweetDeck hasn't yet added the ability to favorite tweets, so might I not be a tad mistaken?</p>

<p>Well, Iain turns out to be the TweetDeck creator, who apparently pays close attention whenever the word TweetDeck is tweeted. So sorry, Iain, I am indeed mistaken: while Twhirl gives me a "limit exceeded" error whenever I try to favorite a tweet, TweetDeck doesn't yet have that functionality. It does have a button labeled F which is currently greyed out but which will presumably allow you to set favorites at some point. So for the moment, I use Twitterrific on my iPhone whenever I really want to favorite something.</p>

<p>Since I caught Iain's attention, I profitted from the occasion to send him a message outlining some of the reasons why, much as I like some of TweetDeck's functionality, I still prefer Twhirl. Here's the list of my nits to pick with TweetDeck:</p>

<ol>
<li><p>Twhirl is more compact. In TweetDeck, all tweets take the same vertical space, regardless of whether they're one-liners or five-liners. This means I can see more Tweets in one Twhirl column than in TweetDeck. One simple way to regain vertical space would be to move the Reply/D/R/F buttons from below the pictures to the left or right of the pictures. Each tweet would now only be as high as the user's pics.</p></li>
<li><p>Re-ordering groups with the move left/right buttons is cumbersome. Either implement drag-and-drop for column re-ordering or add a pop-up menu where you can drag the column names up and down to their desired positions, instead of having to move them one step at a time.</p></li>
<li><p>The "All Tweets" column becomes less useful when you have created your own groups. Whenever I add someone to a group, I now see their tweets in two places. This might be the intended result for some people, but not for me. I don't have everyone I follow added to a group, only the ones I pay more attention to (friends, acquaintances, gurus). This means I have to filter the tweets I've already read when I scan the All Tweets columns for lower priority tweets. A simple workaround for this problem would be to create an "Ungrouped" column and allow me to use that instead of the "All Tweets" column.</p></li>
<li><p>Allow me to fit more than one group in one column. I don't have TweetDeck running all the time, so some columns are empty or mostly empty much of the time, such as the "Direct Messages" one.</p></li>
<li><p>Allow me to resize the width of each column, so I can fit more on the screen at the same time.</p></li>
<li><p>When I click on one of the fast access buttons (Replies/Direct/Twitscoop/12seconds), do not add a duplicate column if one already exists.</p></li>
<li><p>Allow me to mark a tweet as a favorite ;-)</p></li>
</ol>

<p>Notwithstanding these nits, TweetDeck has several appealing features, such as:</p>

<ol>
<li><p>Being able to place the people you're following to different groups and display each group in its own column.</p></li>
<li><p>Built-in search, including the ability to create a self-updating search column (I presume this is how Iain found my tweet).</p></li>
<li><p>Built-in URL shortening, with the ability to choose your favorite service (currently I mostly use http://is.gd).</p></li>
<li><p>Built-in support for <a href="http://www.twitscoop.com">TwitScoop</a>, letting you see what are the "hottest" words being tweeted in the twittosphere.</p></li>
<li><p>Built-in support for <a href="http://12seconds.tv">12seconds.tv</a>, a cross between twitter and seesmic, where instead of posting 140 character status updates you post 12 second videos. Haven't tried it out yet, though.</p></li>
<li><p><strong>Update:</strong> I forgot to mention one of TweetDeck's conveniences, which is the nifty Twitter API status indicator in the lower right-hand corner. This is useful whenever there's trouble in the twittosphere.</p></li>
</ol>

<p>On the other hand, Twhirl has a few tricks of its own up its sleeve:</p>

<ol>
<li><p>Support for <a href="http://www.seesmic.com/">Seesmic</a>, which is currently the dominant video micro blogging platform. Nevertheless, I've tried Seesmic and found it a bit boring, with too many rambling monologues. Perhaps the 12 second limitation could prove as liberating as the Twitter 140 character limit.</p></li>
<li><p>Support for <a href="http://friendfeed.com/olifante">friendfeed</a>, Paul Bucheit's wonderful life feed aggregator.</p></li>
<li><p>Ability to crosspost to <a href="http://pownce.com/olifante/">Pownce</a> and <a href="http://www.jaiku">Jaiku</a>. <br />
<strong>Update:</strong> I just checked out my Pownce account, and it seems like only some of the tweets sent using Twhirl are reaching Pownce, so this feature is only half-working (and I'm not talking about tweets sent via other clients, which of course won't be automatically crossposted to Pownce). I can't confirm whether the same happens with Jaiku, since I don't have an account there.</p></li>
</ol>

<p>I really enjoy these last two features, so for the moment Twhirl has my heart.</p>

<h3>2008-09-22 Update -- Iain's reply</h3>

<p>Iain replied via email 10 minutes after I sent him an email, but I was busy writing this post so I didn't notice it. Here's his answers to my nits:</p>

<ol>
<li><p>Twhirl is more compact <br />
<em>Iain: removal of tweet buttons implemented in next version</em></p></li>
<li><p>Re-ordering is cumbersome <br />
<em>Iain: due to be implemented in a near future version</em></p></li>
<li><p>"Ungrouped" column <br />
<em>Iain: All Tweets column is removable in the next version, good idea on the ungrouped column - I'll get that implemented</em></p></li>
<li><p>More than one group in same column <br />
<em>Iain: unused columns are removed from view in the next version</em></p></li>
<li><p>Resizable columns <br />
<em>Iain: working on this - BUT I have to be careful to not ruin the look of TweetDeck, I've tried different height tweets and they completely ruin the feel</em></p></li>
<li><p>Buttons add duplicate columns <br />
(this nit was missing from my first email to Iain, so no answer from him yet)</p></li>
<li><p>Favorite tweets <br />
<em>Iain: implemented in next version</em></p></li>
</ol>
</div>
</content>


    </entry>
    <entry>
        <title>På Marken</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/08/p%C3%A5-marken.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/08/p%C3%A5-marken.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-54520152</id>
        <published>2008-08-21T19:39:54+01:00</published>
        <updated>2008-08-21T19:39:54+01:00</updated>
        <summary>A new piano piece, dedicated to my good friend Hans Verner Poulsen.</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Music" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>A new piano piece, dedicated to my good friend Hans Verner Poulsen.</p>

<p><a href="http://www.flickr.com/photos/96171112@N00/2785008132/"><img alt="Hans" height="240" src="http://farm4.static.flickr.com/3230/2785008132_d124e960c8_m.jpg" width="197" /></a></p>

<script src="http://mediaplayer.yahoo.com/js" type="text/javascript" />

<p><a href="http://olifante.blogs.com/covil/files/paa_marken.mp3">På Marken</a></p>

<p><span style="font-size: 10px; font-family: 'Trebuchet MS';">Copyright © 2008 Tiago Castro Henriques, <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license">some rights reserved</a></span></p>
</div>
</content>

        <link rel="enclosure" type="audio/mpeg" href="http://olifante.blogs.com/covil/files/paa_marken.mp3" length="unknown" />

    </entry>
    <entry>
        <title>Using Automator to move all Opera tabs to Firefox</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/08/using-automator-to-move-all-opera-tabs-to-firefox.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/08/using-automator-to-move-all-opera-tabs-to-firefox.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-54484514</id>
        <published>2008-08-21T01:04:51+01:00</published>
        <updated>2008-08-21T01:04:51+01:00</updated>
        <summary>How to create a simple Automator workflow to move all open Opera tabs to Firefox on Mac OS X.</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Although I was interested when Automator.app was announced as one of the new features in Tiger, for some reason I never got around to trying it out. I guess I feared it would be more complicated than it actually is. You just need to learn a couple of new words: Action and Workflow.</p>

<p>An Action is an indivisible task, such as "New Folder", "Play DVD", "Get Current Webpage from Safari", "Set iTunes Volume". Automator comes loaded out of the box with hundreds of actions for most of the applications bundled with Mac OS X, such as Finder, iTunes or Safari. Actions may accept input and produce output: For instance, "Text to Audio Files" expects a text string and returns a file. Many Actions do not expect input or produce any output.</p>

<p>A Workflow is just a sequence of Actions, where the output of one Action is passed as input to the next action.</p>

<p>Having grasped these profound concepts, I then tried to figure out how to automate a repetitive task that I perform regularly. I often want to transfer all open tabs from Safari and Opera to Firefox, which is were I like to consolidate my tabs and save them for later reference with "Bookmark All Tabs".</p>

<p>Unfortunately, none of Automator's bundled Safari Actions let you handle tabs, and there aren't any Actions for 3rd party apps such as Firefox or Opera.</p>

<p>Luckily, there's a very handy Action called "Watch Me Do", which lets you record a sequence of Events (i.e. mouse clicks and keyboard presses) and thus replay your interactions with any application, regardless of whether it is supported by an Automator Action. This is what the resulting Workflow looks like:</p>

<div class="thumbnail"><a href="http://skitch.com/olifante/u55e/move-tabs-from-opera-to-firefox"><img alt="Move tabs from Opera to Firefox" src="http://img.skitch.com/20080820-tg3im8cfk5skdtc6ax4xef9jb2.preview.jpg" /></a><br /><span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080">Uploaded with <a href="http://plasq.com/">plasq</a>'s <a href="http://skitch.com">Skitch</a>!</span></div>

<p>Only the shortcuts might require some explaining, although they're pretty basic:</p>

<ul>
<li>⌘L focuses the location bar and selects the current URL (works in most browsers)</li>
<li>⌘C copies the selected text</li>
<li>⌘W closes the current tab</li>
<li>⌘T opens a new tab</li>
<li>⌘V pastes text from the clipboard</li>
</ul>

<p>The penultimate Event is recorded as "Type ' " for some reason, but actually stands for pressing Return on the keyboard, which opens the URL in the newly created tab. The rest is pretty self-explanatory.</p>

<p>The last Event is needed to return focus to Automator, allowing me to interact with the dialog box which is opened by the next Action in my Workflow, "Loop", which allows you to repeat the first Action of a Workflow any number of times. I don't want it to go on forever, so after moving one tab from Opera to Firefox it asks me if I want to continue. Fortunately, since focus has returned to Automator, this is as simple as pressing Return on the keyboard.</p>

<p>This is just skimming the surface of Automator. Actions are actually small programs written in AppleScript, so you can create your own Actions to automate your applications. Some non-Apple applications are very AppleScriptable, while others are not (Opera and especially Firefox, I'm looking at you). To investigate the AppleScript Dictionary of an application, just fire up "/Applications/AppleScript/Script Editor.app" and open that application with "Open Dictionary".</p>

<p>You can also download new Actions from several sites, such as <a href="http://www.apple.com/downloads/macosx/automator/index_abc.html">Apple Automator Actions</a>, <a href="http://automatorworld.com/">Automator World</a>, <a href="http://www.automator.us/downloads.html">automator.us</a> and <a href="http://automatoractions.com/">Automator Actions</a>.</p>

<p>If you're not a big fan of AppleScript or are just plain lazy (a.k.a. healthy), fear not. Unix mavens can use the "Run Shell Script" to do all kinds of unix hackery to their heart's content, while Python fans such as myself can download the "<a href="http://www.apple.com/downloads/macosx/automator/runpythonscript.html">Run Python Script</a>" from Apple itself.</p>
</div>
</content>


    </entry>
    <entry>
        <title>For Anders</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/08/for-anders.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/08/for-anders.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-54452310</id>
        <published>2008-08-20T12:59:55+01:00</published>
        <updated>2008-08-20T12:59:55+01:00</updated>
        <summary>Piano piece by Olifante dedicated to Anders Bech.</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Music" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>I'm publishing another piano piece, this time dedicated to my friend Anders Bech, who acted as a mentor when I started playing the piano 20 years ago in Denmark. Here's Anders having fun with a Keith Jarrett piece (from the Köln Concert, if I'm not mistaken):</p>

<p><a href="http://www.flickr.com/photos/96171112@N00/2779657484/"><img alt="Anders" height="225" src="http://farm4.static.flickr.com/3089/2779657484_ff1a2b3aba_m.jpg" width="240" /></a></p>

<p>Anders introduced me to several easy piano pieces which I came to enjoy a lot, including my first modern piano pieces (by composers such as Paul Hindemith, Harald Genzmer, Aram Khatchaturian and Igor Stravinsky) and my first jazz piano pieces.</p>

<script src="http://mediaplayer.yahoo.com/js" type="text/javascript" />

<p><a href="http://olifante.blogs.com/covil/files/for_anders.mp3">For Anders</a></p>

<p><span style="font-size: 10px; font-family: 'Trebuchet MS';">Copyright © 2008 Tiago Castro Henriques, <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license">some rights reserved</a></span></p>

<p><object align="middle" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" height="500" id="doc_372290338370593" name="doc_372290338370593" width="350"> <param name="movie" value="http://documents.scribd.com/ScribdViewer.swf?document_id=4909719&amp;access_key=key-2khq4ecjii3fk4vmr90j&amp;page=1&amp;version=1" /> <param name="quality" value="high" /> <param name="play" value="true" /> <param name="loop" value="true" /> <param name="scale" value="showall" /> <param name="wmode" value="opaque" /> <param name="devicefont" value="false" /> <param name="bgcolor" value="#ffffff" /> <param name="menu" value="true" /> <param name="allowFullScreen" value="true" /> <param name="allowScriptAccess" value="always" /> <param name="salign" value="" /> <param name="mode" value="list" /> <embed align="middle" allowfullscreen="true" allowscriptaccess="always" bgcolor="#ffffff" devicefont="false" height="500" loop="true" menu="true" mode="list" name="doc_372290338370593_object" play="true" pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" salign="" scale="showall" src="http://documents.scribd.com/ScribdViewer.swf?document_id=4909719&amp;access_key=key-2khq4ecjii3fk4vmr90j&amp;page=1&amp;version=1" type="application/x-shockwave-flash" width="350" wmode="opaque" /> </object><div style="font-size: 10px; text-align: center;"><a href="http://www.scribd.com/doc/4909719/For-Anders">For Anders</a> - <a href="http://www.scribd.com/upload">Upload a Document to Scribd</a></div><div style="display: none;"> Read this document on Scribd: <a href="http://www.scribd.com/doc/4909719/For-Anders">For Anders</a> </div> </p>

<p>Like "<a href="http://olifante.blogs.com/covil/2008/08/sorrow-for-sara.html">Sorrow for Sara</a>", "For Anders" was typeset with <a href="http://lilypond.org/web/">LilyPond 2.10.33-1</a>, assisted by <a href="http://lilypondtool.organum.hu/">LilyPond Tool for jEdit</a>.</p>
</div>
</content>

        <link rel="enclosure" type="audio/mpeg" href="http://olifante.blogs.com/covil/files/for_anders.mp3" length="unknown" />

    </entry>
    <entry>
        <title>Sorrow for Sara</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/08/sorrow-for-sara.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/08/sorrow-for-sara.html" thr:count="1" thr:updated="2008-12-09T22:23:07+00:00" />
        <id>tag:typepad.com,2003:post-54190870</id>
        <published>2008-08-14T20:51:15+01:00</published>
        <updated>2008-08-14T20:51:15+01:00</updated>
        <summary>In Memoriam Sara Custódio, 1990-2008: Sorrow for Sara Copyright © 2008 Tiago Castro Henriques, some rights reserved Sorrow for Sara - Upload a Document to Scribd Read this document on Scribd: Sorrow for Sara</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Music" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><script src="http://mediaplayer.yahoo.com/js" type="text/javascript" />
<p>In Memoriam Sara Custódio, 1990-2008:</p><p><a href="http://olifante.blogs.com/covil/files/sorrow_for_sara.mp3">Sorrow for Sara</a></p><p><span style="font-size: 10px; font-family: 'Trebuchet MS';">Copyright © 2008 Tiago Castro Henriques, <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/" title="Creative Commons by-nc-sa license">some rights reserved</a></span></p>
<p><object align="middle" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" height="500" id="doc_487691772821640" name="doc_487691772821640" width="350"> <param name="movie" value="http://documents.scribd.com/ScribdViewer.swf?document_id=4792679&amp;access_key=key-hynqj36ibcaomml1eev&amp;page=1&amp;version=1" /> <param name="quality" value="high" /> <param name="play" value="true" /> <param name="loop" value="true" /> <param name="scale" value="showall" /> <param name="wmode" value="opaque" /> <param name="devicefont" value="false" /> <param name="bgcolor" value="#ffffff" /> <param name="menu" value="true" /> <param name="allowFullScreen" value="true" /> <param name="allowScriptAccess" value="always" /> <param name="salign" value="" /> <param name="mode" value="list" /> <embed align="middle" allowfullscreen="true" allowscriptaccess="always" bgcolor="#ffffff" devicefont="false" height="500" loop="true" menu="true" mode="list" name="doc_487691772821640_object" play="true" pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" salign="" scale="showall" src="http://documents.scribd.com/ScribdViewer.swf?document_id=4792679&amp;access_key=key-hynqj36ibcaomml1eev&amp;page=1&amp;version=1" type="application/x-shockwave-flash" width="350" wmode="opaque" /> </object></p><div style="font-size: 10px; text-align: center;"><a href="http://www.scribd.com/doc/4792679/Sorrow-for-Sara">Sorrow for Sara</a> - <a href="http://www.scribd.com/upload">Upload a Document to Scribd</a></div><div style="display: none;"> Read this document on Scribd: <a href="http://www.scribd.com/doc/4792679/Sorrow-for-Sara">Sorrow for Sara</a> </div></div>
</content>

        <link rel="enclosure" type="audio/mpeg" href="http://olifante.blogs.com/covil/files/sorrow_for_sara.mp3" length="unknown" />

    </entry>
    <entry>
        <title>Sara Custódio, 1990-2008</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/08/sara-cust%C3%B3dio-1990-2008.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/08/sara-cust%C3%B3dio-1990-2008.html" thr:count="2" thr:updated="2008-09-16T10:27:56+01:00" />
        <id>tag:typepad.com,2003:post-54028038</id>
        <published>2008-08-11T11:32:33+01:00</published>
        <updated>2008-08-11T11:32:33+01:00</updated>
        <summary>Sara Originally uploaded by Olifante. "De tudo o que é novo nasce um novo prazer, mas eu sei que não é boa a jovem morte. Ela fere pelas costas, e não é doce como o açúcar, nem é o como...</summary>
        <author>
            <name>olifante</name>
        </author>
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p><a href="http://www.flickr.com/photos/olifante/54610982/" title="photo sharing"><img alt="" src="http://farm1.static.flickr.com/30/54610982_8402049687_m.jpg" style="border: 2px solid #000000;" /></a><br /><span style="font-size: 0.9em; margin-top: 0px;"><a href="http://www.flickr.com/photos/olifante/54610982/">Sara</a> <br />Originally uploaded by <a href="http://www.flickr.com/people/olifante/">Olifante</a>.</span></p><p>"De tudo o que é novo nasce um novo prazer,<br />mas eu sei que não é boa a jovem morte.<br /><br />Ela fere pelas costas, e não é doce como o açúcar,<br />nem é o como o vinho, nem como o sumo das uvas."<br /><br />Tudo o que é novo é belo, Herberto Hélder.</p></div>
</content>


    </entry>
    <entry>
        <title>Room with a view</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/07/room-with-a-view.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/07/room-with-a-view.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-52605604</id>
        <published>2008-07-13T01:53:21+01:00</published>
        <updated>2008-07-13T01:53:21+01:00</updated>
        <summary>Room with a view Originally uploaded by Olifante. This was the view from our bedroom on the 2nd floor of the summer house. I wish I could have this view at home...</summary>
        <author>
            <name>olifante</name>
        </author>
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p><a href="http://www.flickr.com/photos/olifante/2662775940/" title="photo sharing"><img src="http://farm4.static.flickr.com/3119/2662775940_45bd0b4262_m.jpg" alt="" style="border: solid 2px #000000;" /></a><br /><span style="font-size: 0.9em; margin-top: 0px;"><a href="http://www.flickr.com/photos/olifante/2662775940/">Room with a view</a> <br />Originally uploaded by <a href="http://www.flickr.com/people/olifante/">Olifante</a>.</span><br clear="all" /><p>This was the view from our bedroom on the 2nd floor of the summer house. I wish I could have this view at home...</p></p>
</div>
</content>


    </entry>
    <entry>
        <title>Seaside Desk</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/07/seaside-desk.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/07/seaside-desk.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-52605564</id>
        <published>2008-07-13T01:50:49+01:00</published>
        <updated>2008-07-13T01:50:49+01:00</updated>
        <summary>Seaside Desk Originally uploaded by Olifante. Just got back from a one week vacation in Algarve. The weather was pretty good, but due to my broken toe I couldn't enjoy the beach and had to stay on the balcony, where...</summary>
        <author>
            <name>olifante</name>
        </author>
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p><a href="http://www.flickr.com/photos/olifante/2662771340/" title="photo sharing"><img src="http://farm4.static.flickr.com/3259/2662771340_4487a58066_m.jpg" alt="" style="border: solid 2px #000000;" /></a><br /><span style="font-size: 0.9em; margin-top: 0px;"><a href="http://www.flickr.com/photos/olifante/2662771340/">Seaside Desk</a> <br />Originally uploaded by <a href="http://www.flickr.com/people/olifante/">Olifante</a>.</span><br clear="all" /><p>Just got back from a one week vacation in Algarve. The weather was pretty good, but due to my broken toe I couldn't enjoy the beach and had to stay on the balcony, where I set up a simple but functional work desk. I stayed in the shade all the time and still managed to get mildly sunburned...</p></p>
</div>
</content>


    </entry>
    <entry>
        <title>Wordle-ss</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/06/while-browsing-through-the-google-application-engine-applications-gallery-i-chanced-upon-a-delicious-application-called-word.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/06/while-browsing-through-the-google-application-engine-applications-gallery-i-chanced-upon-a-delicious-application-called-word.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-51751596</id>
        <published>2008-06-23T22:55:37+01:00</published>
        <updated>2008-06-23T22:55:37+01:00</updated>
        <summary>While browsing through the Google Application Engine Applications Gallery, I chanced upon a delicious little application called Wordle - Beautiful World Clouds. You can copy-paste text into a text box and ask Wordle to analyze it and produce a word...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>While browsing through the <a href="http://appgallery.appspot.com/">Google Application Engine Applications Gallery</a>, I chanced upon a delicious little application called <a href="http://wordle.net/">Wordle - Beautiful World Clouds</a>.</p><p>You can copy-paste text into a text box and ask Wordle to analyze it and produce a word cloud, where the size of each word reflects how often it appears in the analyzed text. Alternatively, you can point Wordle to a del.icio.us account and it will produce the corresponding tag cloud. Here's my the tag cloud for my top 100 <a href="http://del.icio.us/olifante">del.icio.us</a> tags:</p><p><a href="http://olifante.blogs.com/.a/6a00d834528cff69e200e55386a7778834-popup" onclick="window.open(this.href,'_blank','scrollbars=no,resizable=yes,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false" style="display: inline;"><img alt="Top100delicious" class="at-xid-6a00d834528cff69e200e55386a7778834 " src="http://olifante.blogs.com/.a/6a00d834528cff69e200e55386a7778834-320pi" style="border: 1px solid black;" title="Top100delicious" /></a> </p><p>Pretty obvious what my favorite tag is... Incidentally, I haven't been using del.icio.us a lot lately. I've been using <a href="http://diigo.com">Diigo</a> instead, which in addition to social bookmarking allows you to highlight and save text clippings from a web page.</p><p>By default Wordle analyzes the 150 most frequent words, but you can
tweak this number to produce sparser or denser word clouds. You can
also choose to ignore capitalization and show only lowercase words,
which eliminates spurious duplicates. </p><p>Wordle conveniently removes frequently used words such as "the" or "is" unless you explicitly request it to show them.</p><p>Wordle randomly chooses a
font and a color scheme, but these can also be changed by the user.
Many of the available fonts are gorgeous, whereas the color scheme
offering could be more varied.</p><p>After del.icio.us, I decide to generate a word cloud for my <a href="http://twitter.com/olifante">Twitter tweets</a>, but I first had to obtain my full set of tweets. Unfortunately I couldn't find a way to download my own tweets from Twitter, which is unfortunate. Twitter, if you're listening, please <a href="http://www.tbray.org/ongoing/When/200x/2006/07/28/Open-Data">set my data free</a> (or correct me if I'm wrong). Google Reader and Gmail do it; Typepad does it; Bloglines does it; so should you.</p><p>Luckily I found <a href="http://bradkellett.com/tweetdumpr/">TweetDumpr</a>, a simple webapp that exports your tweets into a CSV text file. With some simple parsing and cleanup, I got a clean text file with all my tweets, which I copy-pasted into Wordle. Here's my Twitter top 100 word cloud:</p><p><a href="http://olifante.blogs.com/.a/6a00d834528cff69e200e55386b2d08834-popup" onclick="window.open(this.href,'_blank','scrollbars=no,resizable=yes,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false" style="display: inline;"><img alt="Top100twitter" class="at-xid-6a00d834528cff69e200e55386b2d08834 " src="http://olifante.blogs.com/.a/6a00d834528cff69e200e55386b2d08834-320pi" style="border: 1px solid black;" title="Top100twitter" /></a> </p><p>Unfortunately Wordle currently
seems to be down for maintenance, with the following notice: "I am
tinkering with Wordle... Don't fret! We'll be back."</p>
<p /></div>
</content>


    </entry>
    <entry>
        <title>Map of Global Cities</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/04/map-of-global-c.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/04/map-of-global-c.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-47976726</id>
        <published>2008-04-04T20:15:44+01:00</published>
        <updated>2008-04-04T20:15:44+01:00</updated>
        <summary>I found a thought-provoking interactive map of 1st-, 2nd- and 3rd-tier global cities produced by the Globalization and World Cities Study Group of Loughborough University: The GaWC group uses the term World City, but I prefer the term Global City...</summary>
        <author>
            <name>olifante</name>
        </author>
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>I found a thought-provoking interactive map of 1st-, 2nd- and 3rd-tier <a href="http://en.wikipedia.org/wiki/Global_city">global cities</a> produced by the <a href="http://www.lboro.ac.uk/gawc/group.html">Globalization and World Cities Study Group</a> of Loughborough University:
</p>

<p>
<a href="http://www.lboro.ac.uk/gawc/citymap.html" /></p>

<p><a href="http://www.lboro.ac.uk/gawc/citymap.html"><img width="350" height="221" border="0" alt="World" title="Inventory of World Cities" src="http://olifante.blogs.com/covil/images/2008/04/04/world.gif" /></a>
</p>

<p>

The GaWC group uses the term World City, but I prefer the term Global City -- it's less prone to confusion. Besides the list of alpha, beta and gamma global cities, the GaWC group also provides a secondary ranking of <a href="http://www.lboro.ac.uk/gawc/citylist.html">cities possibly on their way to Global City status</a>:</p>

<ul><li><strong>Relatively strong evidence:</strong>
Athens, Auckland, Dublin, Helsinki, Luxembourg, Lyon, Mumbai, New Delhi, Philadelphia, Rio de Janeiro, Tel Aviv, Vienna</li>

<li><strong>Some evidence:</strong>
Abu Dhabi, Almaty, Birmingham, Bogota, Bratislava, Brisbane, Bucharest, Cairo, Cleveland, Cologne, Detroit, Dubai, Ho Chi Minh City, Kiev, Lima, <strong>Lisbon</strong>, Manchester, Montevideo, Oslo, Riyadh, Rotterdam, Seattle, Stuttgart, The Hague, Vancouver</li>

<li><strong>Minimal evidence:</strong>
Adelaide, Antwerp, Arhus, Baltimore, Bangalore, Bologna, Brasilia, Calgary, Cape Town, Colombo, Columbus, Dresden, Edinburgh, Genoa, Glasgow, Gothenburg, Guangzhou, Hanoi, Kansas City, Leeds, Lille, Marseille, Richmond, St Petersburg, Tashkent, Tehran, Tijuana, Turin, Utrecht, Wellington</li></ul>

<p>I find their positioning of Lisbon in the "<strong>Some evidence</strong>" category quite puzzling. Ranking Lisbon at the same global-city level as Oslo, Birmingham and Brisbane seems questionable, to say nothing of bundling it with cities such as Brisbane, Bucharest, Bratislava(!), Montevideo(!!) and Almaty(!!!??).</p>

<p>Lisbon is no Manhattan, but it is not exactly a backwater either. According to Euro Monitor's list of <a href="http://www.euromonitor.com/Top_150_City_Destinations_London_Leads_the_Way">Top 150 City Destinations</a> in the world, Lisbon is placed at a respectable <strong>47th</strong> place, with <strong>1.7 million arrivals per year</strong>, higher than Zurich's 1.4 million and São Paulo's 1.1 million, two cities classified by the GaWC group as beta global cities.</p>

<p>Lisbon is also the <strong>7th</strong> most <a href="http://www.traveldailynews.com/makeof.asp?central_id=1437&amp;permanent_id=17">popular city in Europe for meetings and conventions</a>, according to the International Association Meetings Market 2006
survey of the International Congress &amp; Convention Association:</p>

<ol><li>Vienna - 147 meetings during 2006</li>

<li>Paris - 130</li>

<li>Barcelona - 103</li>

<li>Berlin - 91</li>

<li>Budapest - 86</li>

<li>Prague - 82</li>

<li>Lisbon &amp; Copenhagen - 69 each</li></ol>

<p>Portugal itself ranks <strong>15th</strong> out of 130 in the <a href="http://www.weforum.org/en/initiatives/gcp/TravelandTourismReport/index.htm">Travel &amp; Tourism Competitiveness Index for 2008</a>, and Lisbon must surely be one of the two major travel destinations within the country (the other being the beaches of Algarve).</p>

<p>Of course, tourism and conventions alone do not a Global City make, but I would still expect a stronger correlation. I don't know all the criteria the GaWC group uses for their classification, but it seems to me they need to revisit some of them.</p></div>
</content>


    </entry>
    <entry>
        <title>Firefox 3 beta 5: the SunSpider verdict</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/04/firefox-3-beta.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/04/firefox-3-beta.html" thr:count="1" thr:updated="2008-06-03T04:15:57+01:00" />
        <id>tag:typepad.com,2003:post-47889774</id>
        <published>2008-04-03T01:08:40+01:00</published>
        <updated>2008-04-03T01:08:40+01:00</updated>
        <summary>I just installed the newly released Firefox 3 beta 5, replacing beta 4 in my Macbook Pro's XP partition (a budding addiction to Oblivion has been making me boot into Windows more than I should). The main highlight of this...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Web/Tech" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>I just installed the newly released <a href="http://en-us.www.mozilla.com/en-US/firefox/3.0b5/releasenotes/">Firefox 3 beta 5</a>, replacing beta 4 in my Macbook Pro's XP partition (a budding addiction to <a href="http://en.wikipedia.org/wiki/The_Elder_Scrolls_IV:_Oblivion">Oblivion</a> has been making me boot into Windows more than I should). The main highlight of this released compared to the previous beta 4 is the enhanced Javascript performance.</p>

<p>To see how much of a boost Javascript got, I ran the <a href="http://webkit.org/perf/sunspider-0.9/sunspider.html">SunSpider Javascript Benchmark</a> with several current browsers. Here are the results I got on my machine, with a Core 2 Duo CPU @ 2.40 GHz and 2 GB RAM:</p>

<ul><li>Firefox 3 beta 5: <a href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?{%223d-cube%22:[195,203,206,210,192],%223d-morph%22:[205,180,197,181,176],%223d-raytrace%22:[212,244,219,204,270],%22access-binary-trees%22:[124,127,134,123,118],%22access-fannkuch%22:[296,221,309,214,303],%22access-nbody%22:[261,214,232,219,213],%22access-nsieve%22:[139,148,139,144,155],%22bitops-3bit-bits-in-byte%22:[145,155,155,145,158],%22bitops-bits-in-byte%22:[177,173,135,177,183],%22bitops-bitwise-and%22:[172,159,167,164,163],%22bitops-nsieve-bits%22:[197,179,197,178,178],%22controlflow-recursive%22:[112,115,114,113,116],%22crypto-aes%22:[159,175,173,164,173],%22crypto-md5%22:[146,136,53,133,134],%22crypto-sha1%22:[160,157,66,149,151],%22date-format-tofte%22:[236,238,148,234,226],%22date-format-xparb%22:[172,165,164,166,175],%22math-cordic%22:[260,251,242,254,240],%22math-partial-sums%22:[196,198,204,200,192],%22math-spectral-norm%22:[145,145,147,143,62],%22regexp-dna%22:[317,309,360,316,361],%22string-base64%22:[168,154,152,170,159],%22string-fasta%22:[252,259,245,262,243],%22string-tagcloud%22:[215,198,196,203,189],%22string-unpack-code%22:[321,313,313,322,319],%22string-validate-input%22:[169,175,171,209,177]}">5000.6ms +/- 2.8%</a> </li>

<li>Firefox 3 beta 4: <a href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B230,321,217,226,250%5D,%223d-morph%22:%5B212,161,203,221,201%5D,%223d-raytrace%22:%5B125,238,218,213,218%5D,%22access-binary-trees%22:%5B124,122,123,120,125%5D,%22access-fannkuch%22:%5B360,349,334,348,342%5D,%22access-nbody%22:%5B222,229,242,231,260%5D,%22access-nsieve%22:%5B156,144,124,159,153%5D,%22bitops-3bit-bits-in-byte%22:%5B153,157,155,180,161%5D,%22bitops-bits-in-byte%22:%5B213,202,213,205,215%5D,%22bitops-bitwise-and%22:%5B276,263,263,280,266%5D,%22bitops-nsieve-bits%22:%5B285,230,224,235,239%5D,%22controlflow-recursive%22:%5B112,115,113,112,111%5D,%22crypto-aes%22:%5B164,197,233,170,167%5D,%22crypto-md5%22:%5B162,172,163,178,161%5D,%22crypto-sha1%22:%5B172,172,171,183,181%5D,%22date-format-tofte%22:%5B241,242,259,254,275%5D,%22date-format-xparb%22:%5B174,183,172,180,177%5D,%22math-cordic%22:%5B281,266,270,272,275%5D,%22math-partial-sums%22:%5B289,274,264,265,284%5D,%22math-spectral-norm%22:%5B169,168,155,166,158%5D,%22regexp-dna%22:%5B299,313,295,318,303%5D,%22string-base64%22:%5B163,167,167,183,164%5D,%22string-fasta%22:%5B258,244,253,247,255%5D,%22string-tagcloud%22:%5B188,202,205,198,232%5D,%22string-unpack-code%22:%5B310,308,293,321,300%5D,%22string-validate-input%22:%5B177,177,180,198,193%5D%7D">5593.8ms +/- 1.7%</a> - FF3b5 is 12% faster</li>

<li>Safari 3.1 (525.13): <a href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B234,234,234,266,156%5D,%223d-morph%22:%5B234,219,218,219,219%5D,%223d-raytrace%22:%5B235,234,234,250,218%5D,%22access-binary-trees%22:%5B156,203,172,172,203%5D,%22access-fannkuch%22:%5B407,375,343,344,359%5D,%22access-nbody%22:%5B250,234,250,235,266%5D,%22access-nsieve%22:%5B172,188,156,172,156%5D,%22bitops-3bit-bits-in-byte%22:%5B156,156,156,187,188%5D,%22bitops-bits-in-byte%22:%5B281,219,187,203,187%5D,%22bitops-bitwise-and%22:%5B250,266,281,344,250%5D,%22bitops-nsieve-bits%22:%5B188,218,219,203,203%5D,%22controlflow-recursive%22:%5B188,203,188,203,218%5D,%22crypto-aes%22:%5B203,188,172,187,219%5D,%22crypto-md5%22:%5B172,171,156,218,187%5D,%22crypto-sha1%22:%5B187,172,157,156,172%5D,%22date-format-tofte%22:%5B234,234,219,235,250%5D,%22date-format-xparb%22:%5B344,281,312,281,266%5D,%22math-cordic%22:%5B250,266,266,266,250%5D,%22math-partial-sums%22:%5B282,313,281,282,328%5D,%22math-spectral-norm%22:%5B188,187,187,187,218%5D,%22regexp-dna%22:%5B375,359,375,359,375%5D,%22string-base64%22:%5B234,188,203,187,234%5D,%22string-fasta%22:%5B266,250,266,391,266%5D,%22string-tagcloud%22:%5B219,219,234,219,203%5D,%22string-unpack-code%22:%5B234,218,234,218,282%5D,%22string-validate-input%22:%5B265,235,250,266,250%5D%7D">6111.4ms +/- 2.5%</a> - FF3b5 is 22% faster</li>

<li>Opera 9.50 beta: <a href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B234,250,282,266,265%5D,%223d-morph%22:%5B313,328,312,1203,328%5D,%223d-raytrace%22:%5B266,297,359,266,266%5D,%22access-binary-trees%22:%5B141,157,140,172,141%5D,%22access-fannkuch%22:%5B531,469,469,468,578%5D,%22access-nbody%22:%5B266,282,281,328,500%5D,%22access-nsieve%22:%5B250,234,250,282,235%5D,%22bitops-3bit-bits-in-byte%22:%5B156,187,171,171,203%5D,%22bitops-bits-in-byte%22:%5B187,109,234,203,235%5D,%22bitops-bitwise-and%22:%5B547,438,562,687,578%5D,%22bitops-nsieve-bits%22:%5B313,313,344,313,406%5D,%22controlflow-recursive%22:%5B157,156,156,172,141%5D,%22crypto-aes%22:%5B250,235,281,250,250%5D,%22crypto-md5%22:%5B172,187,172,235,188%5D,%22crypto-sha1%22:%5B156,171,187,187,172%5D,%22date-format-tofte%22:%5B328,265,344,375,375%5D,%22date-format-xparb%22:%5B563,578,625,562,563%5D,%22math-cordic%22:%5B281,297,359,281,282%5D,%22math-partial-sums%22:%5B265,171,265,265,265%5D,%22math-spectral-norm%22:%5B187,172,188,281,94%5D,%22regexp-dna%22:%5B750,828,953,860,859%5D,%22string-base64%22:%5B281,235,218,234,218%5D,%22string-fasta%22:%5B484,578,469,484,532%5D,%22string-tagcloud%22:%5B453,516,469,1312,765%5D,%22string-unpack-code%22:%5B1219,1250,1172,1219,2813%5D,%22string-validate-input%22:%5B250,281,266,250,1172%5D%7D">10252.4ms +/- 18.8%</a> - FF3b5 is 105% faster</li>

<li>Internet Explorer 7.0.5730.13: <a href="http://webkit.org/perf/sunspider-0.9/sunspider-results.html?%7B%223d-cube%22:%5B454,421,422,421,421%5D,%223d-morph%22:%5B531,500,562,469,515%5D,%223d-raytrace%22:%5B547,546,579,593,625%5D,%22access-binary-trees%22:%5B562,484,515,500,500%5D,%22access-fannkuch%22:%5B766,750,766,750,766%5D,%22access-nbody%22:%5B500,422,546,438,438%5D,%22access-nsieve%22:%5B375,359,360,359,437%5D,%22bitops-3bit-bits-in-byte%22:%5B468,469,515,468,468%5D,%22bitops-bits-in-byte%22:%5B469,484,500,500,515%5D,%22bitops-bitwise-and%22:%5B515,547,531,515,547%5D,%22bitops-nsieve-bits%22:%5B437,438,438,422,516%5D,%22controlflow-recursive%22:%5B531,531,578,531,547%5D,%22crypto-aes%22:%5B453,500,485,422,438%5D,%22crypto-md5%22:%5B375,437,437,390,421%5D,%22crypto-sha1%22:%5B406,375,375,406,375%5D,%22date-format-tofte%22:%5B485,516,484,469,484%5D,%22date-format-xparb%22:%5B484,484,578,469,500%5D,%22math-cordic%22:%5B531,547,532,563,563%5D,%22math-partial-sums%22:%5B375,375,453,391,375%5D,%22math-spectral-norm%22:%5B485,547,437,500,422%5D,%22regexp-dna%22:%5B438,406,500,422,422%5D,%22string-base64%22:%5B9125,9125,9172,17875,9687%5D,%22string-fasta%22:%5B593,547,516,422,625%5D,%22string-tagcloud%22:%5B1797,1672,1688,1672,1812%5D,%22string-unpack-code%22:%5B531,578,578,547,516%5D,%22string-validate-input%22:%5B5625,5656,5734,5688,6188%5D%7D">29836.0ms +/- 15.0%</a> - FF3b5 is a whopping 497% faster (I had no idea IE had fallen so far behind in the Javascript race).</li></ul>



<p>To test the Javascript abilities of you browser, here's a couple of jewels from the past reimplemented in Javascript: <a href="http://www.ellosnuncaloharian.com/online/mm/manicminer.html">Manic Miner</a> and <a href="http://www.smashcat.org/arcade/dkong/">Donkey Kong</a>. Both are surprisingly hard -- where's all my muscle memory gone?</p></div>
</content>


    </entry>
    <entry>
        <title>Fable of Bulgarian Riches</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/03/bulgarian-riche.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/03/bulgarian-riche.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-46622926</id>
        <published>2008-03-05T18:39:40+00:00</published>
        <updated>2008-03-05T18:39:40+00:00</updated>
        <summary>Keeping in topic with my last post, I've been browsing through the UBS Price and Earnings report for 2006, the latest available. There's lots of interesting rankings and figures, but not many surprises regarding Portugal. We seem to float around...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Current Affairs" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Keeping in topic with my last post, I've been browsing through the <a href="http://www.ubs.com/1/ShowMedia/ubs_ch/wealth_mgmt_ch/research?contentId=103982&amp;name=eng.pdf">UBS Price and Earnings report for 2006</a>, the latest available. There's lots of interesting rankings and figures, but not many surprises regarding Portugal. We seem to float around the middle for most rankings. The report has an elegant design, with a few unexpected typos here and there. More importantly, the report could have benefitted from some proof-reading by someone who actually knows a thing or two about European countries. Witness the following passage:</p><blockquote><p>Sofia, Bulgaria, is typical of many cities in our survey. An elementary school teacher there earns just under USD 2100 per month, while a secretary in the private sector takes home almost double that amount. At just under USD 7700 a product manager in the Bulgarian capital earns substantially more – due mainly to the fact that this job profile is in demand, particularly among international or large domestic companies.</p></blockquote><p>This struck me as highly surprising. I've never been to Sofia or Bulgaria, but these values seemed much too high for a developing ex-communist country that just recently joined the EU. A couple of tables in the appendix tell a different story:</p>

<ul><li>Gross incomes of primary school teachers in Sofia: USD 2100 per year</li>

<li>Gross incomes of product managers in Sofia: USD 7700 per year</li></ul>

<p>These values are more compatible with my intuition and with several other figures for Sofia presented in the report. You might then say it was a simple typo: someone wrote "USD 2100 per month" when they meant per year. The problem is that the real yearly salaries are far from typical, as is stated in the above quote - they fall at the very bottom of the table for the surveyed cities. I am left with the impression that the person who wrote this passage really thought these were monthly salaries, and consequently knew close to nothing about Bulgaria.</p></div>
</content>


    </entry>
    <entry>
        <title>World in my pocket</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/03/world-in-my-poc.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/03/world-in-my-poc.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-46591562</id>
        <published>2008-03-05T02:05:25+00:00</published>
        <updated>2008-03-05T02:05:25+00:00</updated>
        <summary>Yesterday I got a small unexpected gift in the mail: The Economist sent me a copy of their Pocket World in Figures 2008, a small book filled with facts, statistics and economic information about 183 countries. I got the book...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Current Affairs" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Yesterday I got a small unexpected gift in the mail: The Economist sent me a copy of their Pocket World in Figures 2008, a small book filled with facts, statistics and economic information about 183 countries.</p>

<p>I got the book as a complementary gift after filling in a long online questionnaire. I guess I'm still on their mailing list, although I let my subscription expire last month. They publish a lot of interesting and very detailed articles, but eventually I got tired of their smug tone and their relentless agenda of promoting anglo-saxon supremacy and teaching the world to accept the gift of anglo-saxon leadership.</p>

<p>I guess the tipping point for me was when the Sep 13th issue arrived. The cover sported a picture of an American soldier in Iraq and the following headline: "Iraq: Why They Should Stay". That's when The Economist lost all credibility to me as a source of serious analysis of foreign affairs.</p>

<p>Anyway, the booklet is pretty interesting, if you're the kind of person who likes reading page after page of rankings and figures. Alas, I guess I am such a person.</p>

<h3>Ranking Portugal</h3>

<p>Possessed of a patriotic fever, I grabbed a pencil and underlined every single figure relating to Portugal. Here's a highlight of what struck me as noteworthy:</p>

<ul>
<li><p>33rd biggest economy: 183$bn (US: 12,417$bn)</p></li>
<li><p>43rd highest purchasing power: 48.7 (US: 100)</p></li>
<li><p>28th highest human development index: 90.4 (US: 94.8)</p></li>
</ul>

<p>I guess money's not everything.</p>

<ul>
<li>20th lowest economic growth, 1995-2005</li>
</ul>

<p>Bummer. We need to start importing Paul Grahams.</p>

<ul>
<li>10th largest deficit: -17$bn</li>
</ul>

<p>Not good.</p>

<ul>
<li>30th largest deficit as % of GDP</li>
</ul>

<p>Doesn't look as bad as the absolute value, does it? Actually it's much worse. We're the developed country with the largest percentage deficit. The US doesn't even show up on first 40 positions, which makes the much talked about American deficit seem relatively harmless, considering how many more assets the US has than we do.</p>

<ul>
<li>22nd largest donor in percentage of GDP, 25th largest in absolute numbers</li>
</ul>

<p>We're nice guys.</p>

<ul>
<li>7th lowest growth in industrial output, 2000-2005</li>
</ul>

<p>Doubleplus ungood.</p>

<ul>
<li>11th highest net energy importer</li>
</ul>

<p>On balance, we import 85% of our energetic needs. Better start building those nuclear power plants to take advantage of all that uranium. If it's good for Lovelock, it's good for me!</p>

<ul>
<li>11th highest percentage of population in labour force: 52.4%</li>
</ul>

<p>We're not lazy, just inefficient.</p>

<ul>
<li>39th most competitive nation overall, 24th most competitive government, 32nd most competitive infrastructure</li>
</ul>

<p>It seems we can't even blame our government. They're more competitive than the rest of the country, so let's hope they don't try competing with it.</p>

<ul>
<li>19th highest number of patents in force per 100,000 people</li>
</ul>

<p>I was patently surprised by this.</p>

<ul>
<li><p>19th most crowded road networks</p></li>
<li><p>12th highest number of cars per 1000 people</p></li>
</ul>

<p>Not a surprise to anyone who knows Portuguese people and our love affair with our cars.</p>

<ul>
<li><p>18th most tourist arrivals</p></li>
<li><p>11th highest health spending</p></li>
<li><p>17th highest child well-being, but 2nd highest in terms of child relationship with family and friends</p></li>
</ul>

<p>We're nice to kids.</p>

<ul>
<li>13th highest number of colour TVs per 100 households</li>
</ul>

<p>Colour me surprised - not!</p>

<ul>
<li>10th highest number of mobile phones per 100 people: 109.1</li>
</ul>

<p>One mobile phone is not enough.</p>

<ul>
<li>15th highest percentage of organic cropland</li>
</ul>

<p>Economy circling the drain, but at least we eat healthy produce.</p>

<h3>Last but not least, La pièce de résistance:</h3>

<ul>
<li>1st wine drinking nation in the world</li>
</ul>

<p>We left once notorious France behind at a paltry 4th place. Sapristi, Tonnerre de Brest!</p>

<ul>
<li>16th highest alcohol sales</li>
</ul>

<p>It seems that we're not the world's greatest drunkards after all. We just like our wine more than most.</p>

<p>If we look at how most of the 183 surveyed nations are doing, we don't fare too bad. Unfortunately, people are usually not very interested in the grand perspective, and care rather more about how they're doing today compared to yesterday. When you do that, the situation isn't so rosy. Our economy has stagnated for the last 10 years, and we'll have to endure some hard changes and economic hardship in order to get back on track.</p>

<p>Fortunately for me, if there is one sector where I feel the Portuguese economy is dynamic and continues to innovate and create employment, it's my industry: IT.</p>
</div>
</content>


    </entry>
    <entry>
        <title>Bluebirds and blackbirds</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/02/bluebirds-and-b.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/02/bluebirds-and-b.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-45842390</id>
        <published>2008-02-19T19:57:00+00:00</published>
        <updated>2008-02-19T19:57:00+00:00</updated>
        <summary>Another great puzzle: A collection of bluebirds and blackbirds sit on a wire. 1. There is at least one bird of each type. 2. Each pair of birds with 15 or 20 birds between them are the same color. What...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Science" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Another great puzzle:</p>

<p>A collection of bluebirds and blackbirds sit on a wire. <br />
1. There is at least one bird of each type. <br />
2. Each pair of birds with 15 or 20 birds between them are the same color.  </p>

<p>What is the largest number of birds that could be sitting on the wire?</p>
</div>
</content>


    </entry>
    <entry>
        <title>How many rings?</title>
        <link rel="alternate" type="text/html" href="http://olifante.blogs.com/covil/2008/02/how-many-rings.html" />
        <link rel="replies" type="text/html" href="http://olifante.blogs.com/covil/2008/02/how-many-rings.html" thr:count="0" />
        <id>tag:typepad.com,2003:post-45800912</id>
        <published>2008-02-19T01:02:30+00:00</published>
        <updated>2008-02-19T01:02:30+00:00</updated>
        <summary>While digging through some old papers, I found a copy of what is probably my favorite puzzle. I googled it but couldn't find any references, so I'm posting it. If anyone knows who authored it, let me know. ------ There...</summary>
        <author>
            <name>olifante</name>
        </author>
        <category scheme="http://www.sixapart.com/ns/types#category" term="Science" />
        
        
<content type="xhtml" xml:lang="en-US" xml:base="http://olifante.blogs.com/covil/">
<div xmlns="http://www.w3.org/1999/xhtml"><p>While digging through some old papers, I found a copy of what is probably my favorite puzzle. I googled it but couldn't find any references, so I'm posting it. If anyone knows who authored it, let me know.</p>

<hr />

<p>There are 31 people around a table, each with a square of a given colour on the forehead. Each one must find out what his own colour is, without communicating in any way with the others.</p>

<p>Successive rings are sounded, and each person must leave the table on finding out what his colour is.</p>

<ul>
<li>On the first ring, four persons left.</li>
<li>On the second, everybody in red left.</li>
<li>On the third, no one got up.</li>
<li>On the fourth, at least one person got up.</li>
</ul>

<p>How many rings were sounded after that one?</p>

<p>Remember that everybody passed the test.</p>

<p>Additionally, the leader and his sister left before the last ring (the one that empties the table) and wore different colours.</p>
</div>
</content>


    </entry>
 
</feed><!-- ph=1 --><!-- nhm:dynamic-ssi -->
