Skip to content

Instantly share code, notes, and snippets.

@pyrmont
Created January 22, 2020 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pyrmont/eeca4bd867d1bc93647f1fbb49ea7c8b to your computer and use it in GitHub Desktop.
Save pyrmont/eeca4bd867d1bc93647f1fbb49ea7c8b to your computer and use it in GitHub Desktop.
blog.danieljanus.pl Atom Feed
<?xml version="1.0" encoding="UTF-8"?>
<a:feed xmlns:a="http://www.w3.org/2005/Atom">
<a:id>tag:blog.danieljanus.pl,2019:feed</a:id>
<a:title>code · words · emotions: Daniel Janus’s blog</a:title>
<a:link href="http://blog.danieljanus.pl"/>
<a:updated>2020-01-21T00:00:00Z</a:updated>
<a:author>
<a:name>Daniel Janus</a:name>
<a:uri>http://danieljanus.pl</a:uri>
<a:email>dj@danieljanus.pl</a:email>
</a:author>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2020-01-21:post:middleware</a:id>
<a:title>Careful with that middleware, Eugene</a:title>
<a:link href="http://blog.danieljanus.pl/2020/01/21/middleware/"/>
<a:updated>2020-01-21T00:00:00Z</a:updated>
<a:content type="html">&lt;h2&gt;Prologue&lt;/h2&gt;&lt;p&gt;I’ll be releasing version 0.3 of &lt;a href='https://github.com/nathell/skyscraper'&gt;Skyscraper&lt;/a&gt;, my Clojure framework for scraping entire sites, in a&amp;nbsp;few days.&lt;/p&gt;&lt;p&gt;More than three years have passed since its last release. During that time, I’ve made a&amp;nbsp;number of attempts at redesigning it to&amp;nbsp;be more robust, more usable, and faster; the last one, resulting in an almost complete rewrite, is now almost ready for public use as I’m ironing out the rough edges, documenting it, and adding tests.&lt;/p&gt;&lt;p&gt;It’s been a&amp;nbsp;long journey and I’ll blog about it someday; but today, I’d like to&amp;nbsp;tell another story: one of a&amp;nbsp;nasty bug I&amp;nbsp;had encountered.&lt;/p&gt;&lt;h2&gt;Part One: Wrap, wrap, wrap, wrap&lt;/h2&gt;&lt;p&gt;While updating the code of one of my old scrapers to&amp;nbsp;use the API of Skyscraper 0.3, I&amp;nbsp;noticed an odd thing: some of the output records contained scrambled text. Apparently, the character encoding was not recognised properly.&lt;/p&gt;&lt;p&gt;“Weird,” I&amp;nbsp;thought. Skyscraper should be extra careful about honoring the encoding of pages being scraped (declared either in the headers, or the &lt;code&gt;&amp;lt;meta http-equiv&amp;gt;&lt;/code&gt; tag). In fact, I&amp;nbsp;remembered having seen it working. What was wrong?&lt;/p&gt;&lt;p&gt;For every page that it downloads, Skyscraper 0.3 caches the HTTP response body along with the headers so that it doesn’t have to&amp;nbsp;be downloaded again; the headers are needed to&amp;nbsp;ensure proper encoding when parsing a&amp;nbsp;cached page. The headers are lower-cased, so that Skyscraper can then call &lt;code&gt;&amp;#40;get all-headers &amp;quot;content-type&amp;quot;&amp;#41;&lt;/code&gt; to&amp;nbsp;get the encoding declared in headers. If this step is missed, and the server returns the encoding in a&amp;nbsp;header named &lt;code&gt;Content-Type&lt;/code&gt;, it won’t be matched. Kaboom!&lt;/p&gt;&lt;p&gt;I&amp;nbsp;looked at the cache, and sure enough, the header names in the cache were not lower-cased, even though they should be. But why?&lt;/p&gt;&lt;p&gt;Maybe I&amp;nbsp;was mistaken, and I&amp;nbsp;had forgotten the lower-casing after all? A&amp;nbsp;glance at the code: no. The lower-casing was there, right around the call to&amp;nbsp;the download function.&lt;/p&gt;&lt;p&gt;Digression: Skyscraper uses &lt;a href='https://github.com/dakrone/clj-http'&gt;clj-http&lt;/a&gt; to&amp;nbsp;download pages. clj-http, in turn, uses the &lt;a href='http://clojure-doc.org/articles/cookbooks/middleware.html'&gt;middleware pattern&lt;/a&gt;: there’s a&amp;nbsp;“bare” request function, and then there are wrapper functions that implement things like redirects, OAuth, exception handling, and what have you. I&amp;nbsp;say “wrapper” because they literally wrap the bare function: &lt;code&gt;&amp;#40;wrap-something request&amp;#41;&lt;/code&gt; returns another function that acts just like &lt;code&gt;request&lt;/code&gt;, but with added functionality. And that other function can in turn be wrapped with yet another one, and so on.&lt;/p&gt;&lt;p&gt;There’s a&amp;nbsp;default set of middleware wrappers defined by clj-http, and it also provides a&amp;nbsp;macro, &lt;code&gt;with-additional-middleware&lt;/code&gt;, which allows you to&amp;nbsp;specify additional wrappers. One such wrapper is &lt;code&gt;wrap-lower-case-headers&lt;/code&gt;, which, as the name suggests, causes the response’s header keys to be returned in lower case.&lt;/p&gt;&lt;p&gt;Back to&amp;nbsp;Skyscraper. We’re ready to&amp;nbsp;look at the code now. Can you spot the problem?&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;let &amp;#91;request-fn &amp;#40;or &amp;#40;:request-fn options&amp;#41;
http/request&amp;#41;&amp;#93;
&amp;#40;http/with-additional-middleware &amp;#91;http/wrap-lower-case-headers&amp;#93;
&amp;#40;request-fn req
success-fn
error-fn&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;nbsp;stared at it for several minutes, did some dirty experiments in the REPL, perused the code of clj-http, until it dawned on me.&lt;/p&gt;&lt;p&gt;See that &lt;code&gt;request-fn&lt;/code&gt;? Even though Skyscraper uses &lt;code&gt;http/request&lt;/code&gt; by default, you can override it in the options to&amp;nbsp;supply your own way of doing HTTP. (Some of the tests use it to&amp;nbsp;mock calls to&amp;nbsp;a&amp;nbsp;HTTP server.) In this particular case, it was not overridden, though: the usual &lt;code&gt;http/request&lt;/code&gt; was used. So things looked good: within the body of &lt;code&gt;http/with-additional-middleware&lt;/code&gt;, headers should be lower-cased because &lt;code&gt;request-fn&lt;/code&gt; is &lt;code&gt;http/request&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Or is it?&lt;/p&gt;&lt;p&gt;Let me show you how &lt;code&gt;with-additional-middleware&lt;/code&gt; is implemented. It expands to&amp;nbsp;another macro, &lt;code&gt;with-middleware&lt;/code&gt;, which is defined as follows (docstring redacted):&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defmacro with-middleware
&amp;#91;middleware &amp;amp; body&amp;#93;
`&amp;#40;let &amp;#91;m# &amp;#126;middleware&amp;#93;
&amp;#40;binding &amp;#91;&amp;#42;current-middleware&amp;#42; m#
clj-http.client/request &amp;#40;reduce #&amp;#40;%2 %1&amp;#41;
clj-http.core/request
m#&amp;#41;&amp;#93;
&amp;#126;@body&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That’s right: &lt;code&gt;with-middleware&lt;/code&gt; works by dynamically rebinding &lt;code&gt;http/request&lt;/code&gt;. Which means the &lt;code&gt;request-fn&lt;/code&gt; I&amp;nbsp;was calling is not actually the wrapped version, but the one captured by the outer &lt;code&gt;let&lt;/code&gt;, the one that wasn’t rebound, the one without the additional middleware!&lt;/p&gt;&lt;p&gt;After this light-bulb moment, I&amp;nbsp;moved &lt;code&gt;with-additional-middleware&lt;/code&gt; outside of the &lt;code&gt;let&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;http/with-additional-middleware &amp;#91;http/wrap-lower-case-headers&amp;#93;
&amp;#40;let &amp;#91;request-fn &amp;#40;or &amp;#40;:request-fn options&amp;#41;
http/request&amp;#41;&amp;#93;
&amp;#40;request-fn req
success-fn
error-fn&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, sure enough, it worked.&lt;/p&gt;&lt;h2&gt;Part Two: The tests are screaming loud&lt;/h2&gt;&lt;p&gt;Is it the end of the story? I’m guessing you’re thinking it is. I&amp;nbsp;thought so too. But I&amp;nbsp;wanted to&amp;nbsp;add one last thing: a&amp;nbsp;regression test, so I’d never run into the same problem in the future.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;whipped up a&amp;nbsp;test in which one ISO-8859-2-encoded page was scraped, and a&amp;nbsp;check for the correct string was made. I&amp;nbsp;ran it against the fixed code. It was green. I&amp;nbsp;ran it against the previous, broken version…&lt;/p&gt;&lt;p&gt;It was &lt;i&gt;green&lt;/i&gt;, too.&lt;/p&gt;&lt;p&gt;At this point, I&amp;nbsp;knew I&amp;nbsp;had to&amp;nbsp;get to&amp;nbsp;the bottom of this.&lt;/p&gt;&lt;p&gt;Back to&amp;nbsp;experimenting. After a&amp;nbsp;while, I&amp;nbsp;found out that extracting encoding from a&amp;nbsp;freshly-downloaded page actually worked fine! It only failed when parsing headers fetched from a&amp;nbsp;cache. But the map was the same in both cases! In both cases, the code was effectively doing&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;get {&amp;quot;Content-Type&amp;quot; &amp;quot;text/html; charset=ISO-8859-2&amp;quot;}
&amp;quot;content-type&amp;quot;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This lookup &lt;i&gt;shouldn’t&lt;/i&gt; succeed: in map lookup, string comparison is case-sensitive. And yet, for freshly-downloaded headers, it &lt;i&gt;did&lt;/i&gt; succeed!&lt;/p&gt;&lt;p&gt;I&amp;nbsp;checked the &lt;code&gt;type&lt;/code&gt; of both maps. One of them was a&amp;nbsp;&lt;code&gt;clojure.lang.PersistentHashMap&lt;/code&gt;, as expected. The other one was not. It was actually a&amp;nbsp;&lt;code&gt;clj&amp;#95;http.headers.HeaderMap&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I’ll let the comment of that one speak for itself:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; a map implementation that stores both the original (or canonical) key and value for each key/value pair, but performs lookups and other operations using the normalized &amp;ndash; this allows a value to be looked up by many similar keys, and not just the exact precise key it was originally stored with. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;And so it turned out that the library authors have actually foreseen the need for looking up headers irrespective of case, and provided a&amp;nbsp;helpful means for that. The whole lowercasing business was not needed, after all!&lt;/p&gt;&lt;p&gt;I&amp;nbsp;stripped out the &lt;code&gt;with-additional-middleware&lt;/code&gt; altogether, added some code elsewhere to&amp;nbsp;ensure that the header map is a&amp;nbsp;&lt;code&gt;HeaderMap&lt;/code&gt; regardless of whether it comes from the cache or not, and they lived happily ever after.&lt;/p&gt;&lt;h2&gt;Epilogue&lt;/h2&gt;&lt;p&gt;Moral of the story? It’s twofold.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Dynamic rebinding can be dangerous. Having a&amp;nbsp;public API that is implemented in terms of dynamic rebinding, even more so. I’d prefer if clj-http just allowed the custom middleware to&amp;nbsp;be explicitly specified as an argument, thusly:&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;http/request req
:additional-middleware &amp;#91;http/wrap-lower-case-headers&amp;#93;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Know your dependencies. If you have a&amp;nbsp;problem that might be generically addressed by the library you’re using, look deeper. It might be there already.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Thanks to&amp;nbsp;&lt;a href='https://www.3jane.co.uk'&gt;3Jane&lt;/a&gt; for proofreading this article.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2020-01-03:post:word-champions</a:id>
<a:title>Word Champions</a:title>
<a:link href="http://blog.danieljanus.pl/2020/01/03/word-champions/"/>
<a:updated>2020-01-03T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;This story begins on August 9, 2017, when a&amp;nbsp;friend messaged me on Facebook: “Hey, I’m going to&amp;nbsp;be on a&amp;nbsp;TV talent show this weekend. They’ll be giving me this kind of problems. Any ideas how to&amp;nbsp;prepare?”&lt;/p&gt;&lt;p&gt;He attached a&amp;nbsp;link to&amp;nbsp;this video:&lt;/p&gt;&lt;p&gt;&lt;iframe width="100%" height="500" src="https://www.youtube.com/embed/34AcKyYdNBo" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;Now, we’re both avid Scrabble players, so we&amp;nbsp;explored some ideas about extracting helpful data out of the &lt;a href='http://www.pfs.org.pl/english.php'&gt;Official Polish Scrabble Player’s Dictionary&lt;/a&gt;. I&amp;nbsp;launched a&amp;nbsp;Clojure REPL and wrote some throwaway code to&amp;nbsp;generate sample training problems for Krzysztof. The code used a&amp;nbsp;brute-force algorithm, so it was dog slow, but it was a&amp;nbsp;start. It was Wednesday.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;woke up next morning with the problem still in my head. Clearly, I&amp;nbsp;had found myself in a&amp;nbsp;&lt;a href='https://xkcd.com/356/'&gt;nerd sniping&lt;/a&gt; situation.&lt;/p&gt;&lt;p&gt;&lt;img src="https://imgs.xkcd.com/comics/nerd_sniping.png"&gt;&lt;/p&gt;&lt;p&gt;There was only one obvious way out—to&amp;nbsp;write a&amp;nbsp;full-blown training app so that Krzysztof could practice as if he were in the studio. The clock was ticking: we&amp;nbsp;had two days left.&lt;/p&gt;&lt;p&gt;After work, I&amp;nbsp;started a&amp;nbsp;fresh &lt;a href='https://github.com/day8/re-frame/'&gt;re-frame&lt;/a&gt; project. (I&amp;nbsp;was a&amp;nbsp;recent re-frame convert those days, so I&amp;nbsp;wanted to&amp;nbsp;see how well it could cope with the task at hand.) Late that night, or rather early next morning, the prototype was ready.&lt;/p&gt;&lt;p&gt;It had very messy code. It only worked on Chrome. It failed miserably on mobile. It took ages to&amp;nbsp;load. It had native JS dependencies, notably &lt;a href='https://material-ui.com/'&gt;Material-UI&lt;/a&gt; and &lt;a href='https://react-dnd.github.io/react-dnd/about'&gt;react-dnd&lt;/a&gt;, and for some reason it would not compile with ClojureScript’s advanced optimization turned on; so it weighed in at more than 6 MB, slurping in more than 300 JS files on load.&lt;/p&gt;&lt;p&gt;But it worked.&lt;/p&gt;&lt;p&gt;Krzysztof didn’t win his episode against the other contestants, ending up third, but he completed his challenge successfully. It took him 3 minutes and 42 seconds, out of 5 minutes allotted. The episode aired on 24 October.&lt;/p&gt;&lt;p&gt;&lt;iframe width="100%" height="500" src="https://www.youtube.com/embed/7ec6j31nlAk" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;Krzysztof said that the problem he ended up solving on the show was way easier than the ones generated by the app: had they been more difficult, the wow factor might have been higher.&lt;/p&gt;&lt;p&gt;Several months later, we&amp;nbsp;met at a&amp;nbsp;Scrabble tournament, and I&amp;nbsp;received a&amp;nbsp;present. I&amp;nbsp;wish I&amp;nbsp;had photographed that bottle of wine, so I&amp;nbsp;could show it here, but I&amp;nbsp;hadn’t.&lt;/p&gt;&lt;p&gt;Meanwhile, the code remained messy and low-priority. But I&amp;nbsp;kept returning to&amp;nbsp;it when I&amp;nbsp;felt like it, fixing up things one at a&amp;nbsp;time. I’ve added difficulty levels, so you can have only one diagram, or three. I’ve made it work on Firefox. I’ve done a&amp;nbsp;major rewrite, restructuring the code in a&amp;nbsp;sane way and removing the JS dependencies other than React. I’ve made advanced compilation work, getting the JS down to&amp;nbsp;400K. I’ve made it work on mobile devices. I’ve written a&amp;nbsp;puzzle generator in C, which ended up several orders of magnitude faster than the prototype Clojure version (it’s still brute-force, but uses some dirty C tricks to&amp;nbsp;speed things up; I&amp;nbsp;hope to&amp;nbsp;rewrite it in Rust someday).&lt;/p&gt;&lt;p&gt;And now, 2½ years later, I’ve added an English version, with an accompanying set of puzzles (generated from a&amp;nbsp;wordlist taken from &lt;a href='https://github.com/first20hours/google-10000-english'&gt;this repo&lt;/a&gt;), for the English-speaking world to&amp;nbsp;enjoy.&lt;/p&gt;&lt;p&gt;&lt;a href='http://danieljanus.pl/wladcyslow/'&gt;Play Word Champions now!&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The code is &lt;a href='https://github.com/nathell/wordchampions'&gt;on GitHub&lt;/a&gt; if you’d like to&amp;nbsp;check it out or try hacking on it. It’s small, less than 1KLOC in total, so I&amp;nbsp;think it can be a&amp;nbsp;learning tool for re-frame or ClojureScript.&lt;/p&gt;&lt;p&gt;(This game as featured on the TV shows is called Gridlock. The name “Word Champions” was inspired by the title of Krzysztof’s video on YouTube, literally meaning “Lord of the Words”. There is no pun in the Polish title.)&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2019-10-07:post:web-of-documents</a:id>
<a:title>Web of Documents</a:title>
<a:link href="http://blog.danieljanus.pl/2019/10/07/web-of-documents/"/>
<a:updated>2019-10-07T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;In 1960, Ted Nelson envisioned a&amp;nbsp;web of documents.&lt;/p&gt;&lt;p&gt;It was called &lt;a href='https://en.wikipedia.org/wiki/Project_Xanadu'&gt;Xanadu&lt;/a&gt;. It was a&amp;nbsp;grand, holistic vision: of documents that, once published, are available basically forever; of bidirectional links that could glue together not just documents, but parts thereof; of managing copyright and royalties. It was complex. And it never really came to&amp;nbsp;fruition.&lt;/p&gt;&lt;p&gt;But thirty-one years later, another web of documents took off. A&amp;nbsp;much more modest undertaking than Xanadu, with a&amp;nbsp;simple markup language, simple protocol to&amp;nbsp;retrieve the documents, unidirectional, ever-rotting links, and not much else. The World Wide Web. It was prototyped by one man in a&amp;nbsp;few months. And then its popularity exploded.&lt;/p&gt;&lt;p&gt;As the WWW spread, it grew features. Soon, it was not enough for the documents to&amp;nbsp;contain just text: support for images was added. People wanted to&amp;nbsp;customize the look of the documents, so HTML gained presentational markup abilities, eventually obsoleted by CSS. It was not enough to&amp;nbsp;be able to&amp;nbsp;view the menu of your local pizza store – people wanted to&amp;nbsp;actually order a&amp;nbsp;pizza: the need for sessions yielded cookies and non-idempotent HTTP methods. And people wanted the pages to&amp;nbsp;be interactive, so they became scriptable.&lt;/p&gt;&lt;p&gt;All these features were good. They helped the Web meet actual needs. But having them has a&amp;nbsp;significant consequence, one that is seldom realized:&lt;/p&gt;&lt;p&gt;We&amp;nbsp;don’t have a&amp;nbsp;Web of Documents anymore.&lt;/p&gt;&lt;p&gt;Let me pause at this point. I’ve been using the word “document” intuitively and vaguely so far, so let’s try to&amp;nbsp;pinpoint it. I&amp;nbsp;don’t have a&amp;nbsp;precise definition in mind, but I’ll share some examples. A&amp;nbsp;book is a&amp;nbsp;document, to&amp;nbsp;me. So is a&amp;nbsp;picture, an illustrated text, a&amp;nbsp;scientific paper, a&amp;nbsp;MP3 song, or a&amp;nbsp;video. By contrast, a&amp;nbsp;page that lets you play Tetris isn’t. The essence of this distinction seems to&amp;nbsp;be that documents have well-defined &lt;i&gt;content&lt;/i&gt; that does not change between viewings and does not depend on the state of the outside world. A&amp;nbsp;document is stateless. It exists in and of itself; it is its own microcosm. It may be experienced interactively, but only insofar as it enables the experiencer to&amp;nbsp;focus their attention on the part of their own choosing; the potential state of that interaction is external to&amp;nbsp;the document, not part of itself.&lt;/p&gt;&lt;p&gt;Obviously, this is not very accurate: there are border cases. For example, does a&amp;nbsp;film DVD with a&amp;nbsp;menu qualify as a&amp;nbsp;document? Or how about a&amp;nbsp;choose-your-own-adventure book? Or a&amp;nbsp;HTML page with links to&amp;nbsp;other pages? On the surface, the latter does provide out-of-microcosm interactivity; but viewed from another angle, it is no different than putting a&amp;nbsp;reference in a&amp;nbsp;book. The browser just makes it very easy to&amp;nbsp;go to&amp;nbsp;a&amp;nbsp;shelf and pick another book.&lt;/p&gt;&lt;p&gt;The distinction is there, and it’s important. And with it in mind, let me reiterate:&lt;/p&gt;&lt;p&gt;&lt;i&gt;We&amp;nbsp;don’t have a&amp;nbsp;Web of Documents anymore.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;These days, the WWW is mostly a&amp;nbsp;&lt;i&gt;Web of Applications&lt;/i&gt;. An application is a&amp;nbsp;broader concept: it can display text or images, but also lets you interact not just with itself, but with the world at large. And that’s all well and good, as long as you consciously intend these interactions to&amp;nbsp;happen.&lt;/p&gt;&lt;p&gt;A&amp;nbsp;document is safe. A&amp;nbsp;book is safe: it will not explode in your hands, it will not magically alter its contents tomorrow, and if it happens to&amp;nbsp;be illegal to&amp;nbsp;possess, it will not call the authorities to&amp;nbsp;denounce you. You can implicitly trust a&amp;nbsp;document by virtue of it being one. An application, not so much.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;don’t want to&amp;nbsp;name names, but it’s all too easy these days to&amp;nbsp;follow a&amp;nbsp;link to&amp;nbsp;a&amp;nbsp;news site, expecting an article, only to&amp;nbsp;be greeted with “You have read N articles this month, please register to&amp;nbsp;continue”. Definitely an application-y thing to&amp;nbsp;say, not a&amp;nbsp;document-y one. Now, the purveyors of such sites typically have legitimate economic interest in doing so—but once you sign up, they are able to&amp;nbsp;record your actions, link them with your identity and build your shadow profile. This way, we&amp;nbsp;have applications actively &lt;i&gt;masquerading&lt;/i&gt; as documents, when in reality they &lt;i&gt;do&amp;nbsp;non-documenty things&lt;/i&gt; without telling you.&lt;/p&gt;&lt;p&gt;Legislation such as the EU Cookie Law and the GDPR (insofar as it requires disclosure of data processing) tries to&amp;nbsp;remedy this. But the more I&amp;nbsp;think about it, the more sense it makes to&amp;nbsp;me to&amp;nbsp;attack the problem closer to&amp;nbsp;its root: to&amp;nbsp;decomplect the notions of a&amp;nbsp;document and an application; to&amp;nbsp;keep the Web of Applications as it is, and to&amp;nbsp;recreate a&amp;nbsp;Web of Documents—either parallel to&amp;nbsp;it, or as its sub-web.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;do&amp;nbsp;this, we&amp;nbsp;need to&amp;nbsp;take a&amp;nbsp;step back. (Or do&amp;nbsp;a&amp;nbsp;clean start and invent a&amp;nbsp;whole new technology, but this is unlikely to&amp;nbsp;succeed). Fortunately, we&amp;nbsp;don’t have to&amp;nbsp;travel all the way back to&amp;nbsp;1992, when the WWW was still a&amp;nbsp;Web of Documents. (I&amp;nbsp;still remember table-based layouts and spacer gifs, and the very memory makes me shudder). I&amp;nbsp;think we&amp;nbsp;can base the new Web of Documents on ol’ trusty HTTP (or, better, HTTPS), HTML and CSS as we&amp;nbsp;know them today, with just three restraints:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;i&gt;No methods other than GET&lt;/i&gt; (and perhaps HEAD). POST, PUT, DELETE and friends just have no place in a&amp;nbsp;world of documents. They are not idempotent; they potentially modify the state of the world, which documents should not be able to&amp;nbsp;do. (I&amp;nbsp;was also thinking “no forms”, but with #1 in place, it seems like an unnecessary refinement. After all, forms that translate to&amp;nbsp;GET requests just facilitate creating URLs: a&amp;nbsp;user could just as well have typed the resulting URL by hand.)&lt;/li&gt;&lt;li&gt;&lt;i&gt;No scripts of any kind.&lt;/i&gt; Not JavaScript, not WebAssembly. Not even to&amp;nbsp;enrich a&amp;nbsp;document, such as syntax-highlight the code snippets. This one may seem too stringent, but I&amp;nbsp;think it’s better to&amp;nbsp;err on the safe side, and it’s very easy to&amp;nbsp;enforce.&lt;/li&gt;&lt;li&gt;&lt;i&gt;No cookies.&lt;/i&gt; Cookies by themselves aren’t interactive, but having them makes it all too easy to&amp;nbsp;abuse the semantics of HTTP to&amp;nbsp;recreate sessions, and on top of them reinvent the app-wheel and eventually forfeit the Web of Documents again.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Again, there may be corner cases that may have escaped me. But if a&amp;nbsp;WWW page conforms to&amp;nbsp;these restrictions, I&amp;nbsp;think it may be pretty safe to&amp;nbsp;call it a&amp;nbsp;“document” and make it a&amp;nbsp;part of the Web of Documents.&lt;/p&gt;&lt;p&gt;How do&amp;nbsp;we&amp;nbsp;achieve this? I&amp;nbsp;don’t know, really. I&amp;nbsp;don’t have a&amp;nbsp;concrete proposal. Perhaps we&amp;nbsp;could have dedicated browsers for the WoD; perhaps we&amp;nbsp;could make existing browsers prominently advertise to&amp;nbsp;the user whether they are browsing a&amp;nbsp;document or an application. On top of all the technical decisions to&amp;nbsp;make, there’ll be significant campaigning and lobbying needed if the idea is ever to&amp;nbsp;take off.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;don’t dare dream that it ever will. My intent in this article is to&amp;nbsp;provide food for thought. All I&amp;nbsp;ask from you, my reader, is consideration and attention. And if you got this far, chances are I&amp;nbsp;got them. I’m grateful.&lt;/p&gt;&lt;p&gt;This page is a&amp;nbsp;document. Thank you for reading it.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2019-02-05:post:clj-tvision</a:id>
<a:title>Re-framing text-mode apps</a:title>
<a:link href="http://blog.danieljanus.pl/2019/02/05/clj-tvision/"/>
<a:updated>2019-02-05T00:00:00Z</a:updated>
<a:content type="html">&lt;h2&gt;Intro&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt; “But, you know, many explorers liked to go to places that are unusual. And, it’s only for the fun of it.” – Richard P. Feynman &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;A&amp;nbsp;couple of nights ago, I&amp;nbsp;hacked together a&amp;nbsp;small Clojure program.&lt;/p&gt;&lt;p&gt;All it does is displays a&amp;nbsp;terminal window with a&amp;nbsp;red rectangle in it. You can use your cursor keys to&amp;nbsp;move it around the window, and space bar to&amp;nbsp;change its colour. It’s fun, but it doesn’t sound very useful, does it?&lt;/p&gt;&lt;p&gt;In this post, I’ll try to&amp;nbsp;convince you that there’s more to&amp;nbsp;this little toy than might at first sight appear. You may want to&amp;nbsp;check out &lt;a href='https://github.com/nathell/clj-tvision'&gt;the repo&lt;/a&gt; as you go along.&lt;/p&gt;&lt;h2&gt;In which an unexpected appearance is made&lt;/h2&gt;&lt;p&gt;(I’ve always envied &lt;a href='https://technomancy.us'&gt;Phil Hagelberg&lt;/a&gt; this kind of headlines.)&lt;/p&gt;&lt;p&gt;As you might have guessed from this article’s title, clj-tvision (a&amp;nbsp;working name for the program) is a&amp;nbsp;&lt;a href='https://github.com/Day8/re-frame'&gt;re-frame&lt;/a&gt; app.&lt;/p&gt;&lt;p&gt;For those of you who haven’t heard of re-frame, a&amp;nbsp;word of explanation: it’s a&amp;nbsp;ClojureScripty way of writing React apps, with Redux-like management of application state. If you do&amp;nbsp;know re-frame (shameless plug: we&amp;nbsp;at &lt;a href='https://works-hub.com'&gt;WorksHub&lt;/a&gt; do, and use it a&amp;nbsp;lot: it powers the site you’re looking at right now!), you’ll instantly find yourself at home. However, a&amp;nbsp;few moments later, a&amp;nbsp;thought might dawn upon you, and you might start to&amp;nbsp;feel a&amp;nbsp;little uneasy…&lt;/p&gt;&lt;p&gt;Because I’ve mentioned React and ClojureScript, and yet I’d said earlier that we’re talking a&amp;nbsp;text-mode application here. And I’ve mentioned that it’s written in Clojure. It is, in fact, not using React at all, and it has nothing to&amp;nbsp;do&amp;nbsp;whatsoever with ClojureScript, JavaScript, or the browser.&lt;/p&gt;&lt;p&gt;How is that even possible?&lt;/p&gt;&lt;p&gt;Here’s the catch: re-frame is implemented in &lt;code&gt;.cljc&lt;/code&gt; files. So while it’s mostly used in the ClojureScript frontend, it &lt;i&gt;can&lt;/i&gt; be used from Clojure. You may know this if you’re testing your events or subscriptions on the JVM.&lt;/p&gt;&lt;p&gt;While it’s mostly – if not hitherto exclusively – used for just that, I&amp;nbsp;wanted to&amp;nbsp;explore whether it could be used to&amp;nbsp;manage state in an actual, non-web app. Text-mode is a&amp;nbsp;great playground for this kind of exploration. Rather than picking a&amp;nbsp;GUI toolkit and concern myself with its intricacies, I&amp;nbsp;chose to&amp;nbsp;just put things on a&amp;nbsp;rectangular sheet of text characters.&lt;/p&gt;&lt;p&gt;(But if you are interested in pursuing a&amp;nbsp;React-ish approach for GUIs, check out what Bodil Stokke’s been doing in &lt;a href='https://github.com/bodil/vgtk'&gt;vgtk&lt;/a&gt;.)&lt;/p&gt;&lt;h2&gt;Living without the DOM&lt;/h2&gt;&lt;p&gt;The building blocks of a&amp;nbsp;re-frame app are subscriptions, events, and views. While the first two work in Clojureland pretty much the same way they do&amp;nbsp;in the browser (although there are differences, of which more anon), views are a&amp;nbsp;different beast.&lt;/p&gt;&lt;p&gt;&lt;a href='https://github.com/Day8/re-frame/blob/master/docs/SubscriptionFlow.md'&gt;re-frame’s documentation&lt;/a&gt; says that views are “data in, Hiccup out. Hiccup is ClojureScript data structures which represent DOM.” But outside of the browser realm, there’s no DOM. So let’s rephrase that more generally: re-frame views should produce &lt;i&gt;data structures which declaratively describe the component’s appearance to&amp;nbsp;the user&lt;/i&gt;. In web apps, those structures correspond to&amp;nbsp;the DOM. What they will look like outside is up to&amp;nbsp;us. We’ll be growing our own DOM-like model, piecemeal, as needs arise.&lt;/p&gt;&lt;p&gt;For clj-tvision, I’ve opted for a&amp;nbsp;very simple thing. Let’s start with a&amp;nbsp;concrete example. Here’s a&amp;nbsp;view:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn view &amp;#91;&amp;#93;
&amp;#91;{:type :rectangle, :x1 10, :y1 5, :x2 20, :y2 10, :color :red}&amp;#93;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unlike in the DOM, in this model the UI state isn’t a&amp;nbsp;tree. It’s a&amp;nbsp;flat sequence of maps that each represent individual “primitive elements”. We&amp;nbsp;could come up with a&amp;nbsp;fancy buzzword-compliant name and call it Component List Model, or CLiM for short, in homage to&amp;nbsp;&lt;a href='https://en.wikipedia.org/wiki/Common_Lisp_Interface_Manager'&gt;the venerable GUI toolkit&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Like normal re-frame views, CLiM views can include subviews. An example follows:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn square &amp;#91;left top size color&amp;#93;
&amp;#91;{:type :rectangle,
:x1 left,
:y1 top,
:x2 &amp;#40;+ left size -1&amp;#41;,
:y2 &amp;#40;+ top size -1&amp;#41;,
:color color}&amp;#93;&amp;#41;
&amp;#40;defn view &amp;#91;&amp;#93;
&amp;#91;&amp;#91;square 1 1 5 :red&amp;#93;
&amp;#91;square 9 9 5 :blue&amp;#93;&amp;#93;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How to&amp;nbsp;render a&amp;nbsp;view? Simple. First, flatten the list, performing funcalls on subviews so that you get a&amp;nbsp;sequence containing only primitives. Then, draw each of them in order. (If there is an overlap, the trailers will obscure the leaders. Almost biblical.)&lt;/p&gt;&lt;p&gt;I’ve defined a&amp;nbsp;multimethod, &lt;code&gt;render-primitive&lt;/code&gt;, dispatching on &lt;code&gt;:type&lt;/code&gt;. Its methods draw the corresponding primitive to&amp;nbsp;a&amp;nbsp;Lanterna screen.&lt;/p&gt;&lt;p&gt;Oh, didn’t I&amp;nbsp;mention &lt;a href='https://github.com/mabe02/lanterna'&gt;Lanterna&lt;/a&gt;? It’s a&amp;nbsp;Java library for terminals. Either real ones or emulated in Swing (easier to&amp;nbsp;work with when you’re in a&amp;nbsp;CIDER REPL). Plus, it sports virtual screens which can be blitted to&amp;nbsp;a&amp;nbsp;real terminal. This gives us a&amp;nbsp;rough poor man’s equivalent of React’s VDOM. And it has a&amp;nbsp;&lt;a href='https://github.com/AvramRobert/clojure-lanterna'&gt;Clojure wrapper&lt;/a&gt;!&lt;/p&gt;&lt;h2&gt;Events at eventide&lt;/h2&gt;&lt;p&gt;So now we&amp;nbsp;know how to&amp;nbsp;draw our UI. But an app isn’t made up of just drawing. It has a&amp;nbsp;main loop: it listens to&amp;nbsp;events, which cause the app state to&amp;nbsp;change and the corresponding components to&amp;nbsp;redraw.&lt;/p&gt;&lt;p&gt;re-frame does provide an event mechanism, but it doesn’t &lt;i&gt;define&lt;/i&gt; any events per se. So we&amp;nbsp;need to&amp;nbsp;ask ourselves: who calls &lt;i&gt;dispatch&lt;/i&gt;? How do&amp;nbsp;events originate? How to&amp;nbsp;write the main loop?&lt;/p&gt;&lt;p&gt;clj-tvision is a&amp;nbsp;proof-of-concept, so it doesn’t concern itself with mouse support. There’s only one way a&amp;nbsp;user can interact with the app: via the keyboard. So keystrokes will be the only “source events”, as it were, for the app; and so writing the event loop should be simple. Sketching pseudocode:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;loop &amp;#91;&amp;#93;
&amp;#40;render-app&amp;#41;
&amp;#40;let &amp;#91;keystroke &amp;#40;wait-for-key&amp;#41;&amp;#93; ;; blocking!
&amp;#40;dispatch &amp;#91;:key-pressed keystroke&amp;#93;&amp;#41;
&amp;#40;recur&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Simple as that, should work, right?&lt;/p&gt;&lt;p&gt;Wrong.&lt;/p&gt;&lt;p&gt;If you actually try that, it’ll &lt;i&gt;somewhat&lt;/i&gt; work. Hit right arrow to&amp;nbsp;move the rectangle, nothing happens! Hit right arrow again, it moves. Hit left, it moves right. Hit right, it moves left. Not what you want.&lt;/p&gt;&lt;p&gt;You see, there’s a&amp;nbsp;complication stemming from the fact that re-frame’s events are asynchronous by default. (Hence the &lt;code&gt;dispatch&lt;/code&gt; vs. &lt;code&gt;dispatch-sync&lt;/code&gt; dichotomy.) They don’t get dispatched immediately; rather, re-frame places them on a&amp;nbsp;queue and processes them asynchronously, so that they don’t hog the browser. The Clojure version of re-frame handles that using a&amp;nbsp;single-threaded executor with a&amp;nbsp;dedicated thread.&lt;/p&gt;&lt;p&gt;We&amp;nbsp;&lt;i&gt;almost&lt;/i&gt; could use &lt;code&gt;dispatch-sync&lt;/code&gt; everywhere, but for re-frame that’s a&amp;nbsp;no-no: once within a&amp;nbsp;&lt;code&gt;dispatch-sync&lt;/code&gt; handler, you cannot dispatch other events. If you try anyway, re-frame will detect it and politely point its dragon-scaly head at you, explaining it doesn’t like it. (It is a&amp;nbsp;benevolent dragon, you know.)&lt;/p&gt;&lt;p&gt;So we&amp;nbsp;need to&amp;nbsp;hook into that “next-tick” machinery of re-frame’s somehow. There are probably better ways of doing this, but I&amp;nbsp;opted to&amp;nbsp;blatantly redefine &lt;code&gt;re-frame.interop/next-tick&lt;/code&gt; to&amp;nbsp;tell the main loop: “hey, events have been handled and we&amp;nbsp;have a&amp;nbsp;new state, dispatch an event so we&amp;nbsp;can redraw.” This is one of the rare cases where monkey-patching third-party code with &lt;code&gt;alter-var-root&lt;/code&gt; saves you the hassle of forking that entire codebase.&lt;/p&gt;&lt;p&gt;So now we&amp;nbsp;have &lt;i&gt;two&lt;/i&gt; sources of events: keystrokes, and &lt;code&gt;next-tick&lt;/code&gt;. To&amp;nbsp;multiplex them, I’ve whipped up a&amp;nbsp;channel with core.async. Feels hacky, but allows to&amp;nbsp;add mouse support in the future. Or time-based events that will be fired periodically every so often.&lt;/p&gt;&lt;p&gt;For completeness, I&amp;nbsp;should also add that Clojure-side re-frame doesn’t have the luxury of having reactive atoms provided by Reagent. Its ratoms are ordinary Clojure atoms. Unlike in ClojureScript, any time the app state changes, &lt;i&gt;every&lt;/i&gt; subscription in the signal graph will be recomputed. It may well be possible to&amp;nbsp;port Reagent’s ratoms to&amp;nbsp;Clojure, but it is a&amp;nbsp;far more advanced exercise. For simple apps, what re-frame provides on its own might just be enough.&lt;/p&gt;&lt;p&gt;And with that final bit, we&amp;nbsp;can swipe all that hackitude under the carpet… or, should I&amp;nbsp;say, tuck it into an internal ns that hopefully no-one will ever look into. And we’re left with shiny, declarative, re-framey, beautiful UI code on the surface. &lt;a href='https://github.com/nathell/clj-tvision/blob/master/src/tvision/core.clj'&gt;Just look&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Closing thoughts&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt; “Within C++, there is a much smaller and cleaner language struggling to get out.” – Bjarne Stroustrup &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;If you’ve ever encountered legacy C++ code, this will ring true. Come to&amp;nbsp;think of it, Stroustrup’s words are true of every system that has grown organically over its lifetime, with features being added to&amp;nbsp;it but hardly ever removed.&lt;/p&gt;&lt;p&gt;And modern webapps may well be the epitome of that kind of system. We&amp;nbsp;now have desktop apps that are fully self-contained on a&amp;nbsp;single machine, yet use an overwhelmingly complex and vast machinery grown out of a&amp;nbsp;simple system originally devised to&amp;nbsp;&lt;a href='http://info.cern.ch/hypertext/WWW/TheProject.html'&gt;view static documents over the Internet&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For all that complexity, we&amp;nbsp;continue to&amp;nbsp;use it. Partly owing to&amp;nbsp;its ubiquity, partly for convenience. In my experience, the abstractions provided by re-frame allow you to&amp;nbsp;wrap your head around large apps and reason about them much more easily than, say, object-oriented approaches. It just feels right. Conversely, writing an app in, say, GTK+ would now feel like a&amp;nbsp;setback by some twenty years.&lt;/p&gt;&lt;p&gt;So this toy, this movable rectangle on a&amp;nbsp;black screen, is not so much an app as it is a&amp;nbsp;philosophical exercise. It is what my typing fingers produced while I&amp;nbsp;pondered, weak and weary: “can we&amp;nbsp;throw away most of that cruft, while still enjoying the abstractions that make life so much easier?”&lt;/p&gt;&lt;p&gt;Can we?&lt;/p&gt;&lt;p&gt;This post was originally published on &lt;a href='https://functional.works-hub.com/learn/re-framing-text-mode-apps-fd5cf'&gt;Functional Works&lt;/a&gt;.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2014-09-13:post:happy-programmers-day</a:id>
<a:title>Happy Programmers’ Day!</a:title>
<a:link href="http://blog.danieljanus.pl/2014/09/13/happy-programmers-day/"/>
<a:updated>2014-09-13T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Happy &lt;a href='https://en.wikipedia.org/wiki/Programmers'_Day'&gt;Programmers’ Day&lt;/a&gt;, everyone!&lt;/p&gt;&lt;p&gt;A&amp;nbsp;feast isn’t a&amp;nbsp;feast, though, until it has a&amp;nbsp;proper way of celebrating it. The &lt;a href='https://en.wikipedia.org/wiki/Pi_Day'&gt;Pi Day&lt;/a&gt;, for instance, has one: you eat a&amp;nbsp;pie (preferably exactly at 1:59:26.535am), but I&amp;nbsp;haven’t heard of any way of celebrating the Programmers’ Day, so I&amp;nbsp;had to&amp;nbsp;invent one. An obvious way would be to&amp;nbsp;write a&amp;nbsp;program, preferably a&amp;nbsp;non-trivial one, but that requires time and dedication, which not everyone is able to&amp;nbsp;readily spare.&lt;/p&gt;&lt;p&gt;So here’s my idea: on Programmers’ Day, dust off a&amp;nbsp;program that you wrote some time ago — something that is just lying around in some far corner of your hard disk, that you haven’t looked at in years, but that you had fun writing — and put it on &lt;a href='https://github.com/'&gt;GitHub&lt;/a&gt; for all the world to&amp;nbsp;see, to&amp;nbsp;share the joy of programming.&lt;/p&gt;&lt;p&gt;Let me initialize the new tradition by doing this myself. Here’s &lt;a href='https://github.com/nathell/haze'&gt;HAZE&lt;/a&gt;, the Haskellish Abominable Z-machine Emulator. It was my final assignment for a&amp;nbsp;course in Advanced Functional Programming, in my fourth year at the Uni, way back in 2004. It is an emulator for an ancient kind of virtual machine, the &lt;a href='https://en.wikipedia.org/wiki/Z-machine'&gt;Z-machine&lt;/a&gt;, written from scratch in Haskell. It allows you to&amp;nbsp;play text adventure games, such as &lt;a href='https://en.wikipedia.org/wiki/Zork'&gt;Zork&lt;/a&gt;, much in the vein of &lt;a href='https://davidgriffith.gitlab.io/frotz/'&gt;Frotz&lt;/a&gt;. It’s not very complete, and supports versions of the Z-machine up to&amp;nbsp;3 only, so newer games won’t run on it as it stands, but Zork is playable.&lt;/p&gt;&lt;p&gt;It probably won’t even compile in modern Haskell systems: it was originally written for GHC version 6.2.1, and extensively uses the FiniteMap data type, which was obsoleted shortly after and is no longer found in modern systems. I&amp;nbsp;should have Linux and Windows binaries lying around (yes, I&amp;nbsp;had compiled it under Windows, using MinGW/PDCurses); I’ll put them on GitHub once I&amp;nbsp;find them.&lt;/p&gt;&lt;p&gt;My mind now wanders ten years back in time, to&amp;nbsp;the days when I&amp;nbsp;was writing it. It took me about three summer weeks to&amp;nbsp;write HAZE from scratch, most of that time on a&amp;nbsp;slow laptop where it took quite a&amp;nbsp;lot of seconds to&amp;nbsp;get GHC to&amp;nbsp;compile even a&amp;nbsp;simple thing. I&amp;nbsp;would do&amp;nbsp;some of it differently if I&amp;nbsp;were doing it now — for one, the state of a&amp;nbsp;&lt;code&gt;ZMachine&lt;/code&gt; is a&amp;nbsp;central datatype to&amp;nbsp;HAZE, and you’ll find a&amp;nbsp;lot of functions that take and return ZMachines, so a&amp;nbsp;state monad is an obvious choice; I&amp;nbsp;didn’t understand monads well enough back then. But I&amp;nbsp;still remember how I&amp;nbsp;had the framework in place already and I&amp;nbsp;was adding implementations of Z-code opcodes, one by one, to&amp;nbsp;&lt;code&gt;ZMachine/ZCode/Impl.hs&lt;/code&gt;, recompiling, rerunning, getting messages about unimplemented opcodes, when all of a&amp;nbsp;sudden I&amp;nbsp;got the familiar message about a&amp;nbsp;white house and a&amp;nbsp;small mailbox. Freude!&lt;/p&gt;&lt;p&gt;I&amp;nbsp;hope you enjoy looking at it at least half as much as I&amp;nbsp;had enjoyed writing it.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2014-05-20:post:you-already-use-lisp-syntax</a:id>
<a:title>You already use Lisp syntax</a:title>
<a:link href="http://blog.danieljanus.pl/2014/05/20/you-already-use-lisp-syntax/"/>
<a:updated>2014-05-20T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;&lt;strong&gt;Unix Developer:&lt;/strong&gt; I’m not going to&amp;nbsp;touch Lisp. It’s horrible!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Why so?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; The syntax! This illegible prefix-RPN syntax that nobody else uses. And just look at all these parens!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Well, many people find it perfectly legible, although most agree that it takes some time to&amp;nbsp;get accustomed to. But I&amp;nbsp;think you’re mistaken. Lots of people are using Lisp syntax on a&amp;nbsp;daily basis…&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; I&amp;nbsp;happen to&amp;nbsp;know no one doing this.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; …without actually realizing this. In fact, I&amp;nbsp;think &lt;i&gt;you&lt;/i&gt; yourself are using it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; Wait, &lt;i&gt;what&lt;/i&gt;?!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; And the particular variant of Lisp syntax you’re using is called Bourne shell.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; Now I&amp;nbsp;don’t understand. What on earth does the shell have to&amp;nbsp;do&amp;nbsp;with Lisp?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Just look: in the shell, you put the name of the program first, followed by the arguments, separated by spaces. In Lisp it’s exactly the same, except that you put an opening paren at the beginning and a&amp;nbsp;closing paren at the end.&lt;/p&gt;&lt;p&gt;Shell: &lt;code&gt;run-something arg1 arg2 arg3&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Lisp: &lt;code&gt;&amp;#40;run-something arg1 arg2 arg3&amp;#41;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; I&amp;nbsp;still don’t get the analogy.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Then you need a&amp;nbsp;mechanism for expression composition — putting the output of one expression as an input to&amp;nbsp;another. In Lisp, you just nest the lists. And in the shell?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; Backticks.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; That’s right. Or &lt;code&gt;$&amp;#40;&amp;#41;&lt;/code&gt;, which has the advantage of being more easily nestable. Let’s try arithmetic. How do&amp;nbsp;you do&amp;nbsp;arithmetic in the shell?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; &lt;code&gt;expr&lt;/code&gt;. Or the Bash builtin &lt;code&gt;let&lt;/code&gt;. For example,&lt;/p&gt;&lt;pre&gt;&lt;code class="bash"&gt;$ let x='2&amp;#42;&amp;#40;&amp;#40;10+4&amp;#41;/7&amp;#41;'; echo $x
4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Now wouldn’t it be in line with the spirit of Unix — to&amp;nbsp;have programs do&amp;nbsp;just one thing — if we&amp;nbsp;had one program to&amp;nbsp;do&amp;nbsp;addition, and another to&amp;nbsp;do&amp;nbsp;subtraction, and yet another to&amp;nbsp;do&amp;nbsp;multiplication and division?&lt;/p&gt;&lt;p&gt;It’s trivial to&amp;nbsp;write it in C:&lt;/p&gt;&lt;pre&gt;&lt;code class="c"&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
int main&amp;#40;int argc, char &amp;#42;&amp;#42;argv&amp;#41; {
int mode = -1, cnt = argc - 1, val, i;
char &amp;#42;&amp;#42;args = argv + 1;
switch &amp;#40;argv&amp;#91;0&amp;#93;&amp;#91;strlen&amp;#40;argv&amp;#91;0&amp;#93;&amp;#41; - 1&amp;#93;&amp;#41; {
case '+': mode = 0; break;
case '-': mode = 1; break;
case 'x': mode = 2; break;
case 'd': mode = 3; break;
}
if &amp;#40;mode == -1&amp;#41; {
fprintf&amp;#40;stderr, &amp;quot;invalid math operation\n&amp;quot;&amp;#41;;
return 1;
}
if &amp;#40;&amp;#40;mode == 1 || mode == 3&amp;#41; &amp;amp;&amp;amp; !cnt&amp;#41; {
fprintf&amp;#40;stderr, &amp;quot;%s requires at least one arg\n&amp;quot;, argv&amp;#91;0&amp;#93;&amp;#41;;
return 1;
}
switch &amp;#40;mode&amp;#41; {
case 0: val = 0; break;
case 2: val = 1; break;
default: val = atoi&amp;#40;&amp;#42;args++&amp;#41;; cnt--; break;
}
while &amp;#40;cnt--&amp;#41; {
switch &amp;#40;mode&amp;#41; {
case 0: val += atoi&amp;#40;&amp;#42;args++&amp;#41;; break;
case 1: val -= atoi&amp;#40;&amp;#42;args++&amp;#41;; break;
case 2: val &amp;#42;= atoi&amp;#40;&amp;#42;args++&amp;#41;; break;
case 3: val /= atoi&amp;#40;&amp;#42;args++&amp;#41;; break;
}
}
printf&amp;#40;&amp;quot;%d\n&amp;quot;, val&amp;#41;;
return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This dispatches on the last character of its name, so it can be symlinked to&amp;nbsp;&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt; (I&amp;nbsp;picked unusual names for multiplication and division to&amp;nbsp;make them legal and avoid escaping).&lt;/p&gt;&lt;p&gt;Now behold:&lt;/p&gt;&lt;pre&gt;&lt;code class="bash"&gt;$ x 2 $&amp;#40;d $&amp;#40;+ 10 4&amp;#41; 7&amp;#41;
4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; Wow, this sure looks a&amp;nbsp;lot like Lisp!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; And yet it’s the shell. Our two basic rules — program-name-first and &lt;code&gt;$&amp;#40;&amp;#41;&lt;/code&gt;-for-composition — allowed us to&amp;nbsp;explicitly specify the order of evaluation, so there was no need to&amp;nbsp;do&amp;nbsp;any fancy parsing beyond what the shell already provides.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UD:&lt;/strong&gt; So is the shell a&amp;nbsp;Lisp?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Me:&lt;/strong&gt; Not really. The shell is &lt;a href='http://blog.codinghorror.com/new-programming-jargon/'&gt;stringly typed&lt;/a&gt;: a&amp;nbsp;program takes textual parameters and produces textual output. To&amp;nbsp;qualify as a&amp;nbsp;Lisp, it would have to&amp;nbsp;have a&amp;nbsp;composite type: a&amp;nbsp;list or a&amp;nbsp;cons cell to&amp;nbsp;build lists on top of. Then, you’d be able to&amp;nbsp;represent code as this data structure, and write programs to&amp;nbsp;transform code to&amp;nbsp;other code.&lt;/p&gt;&lt;p&gt;But the Tao of Lisp lingers in the shell syntax.&lt;/p&gt;&lt;p&gt;&lt;hr&gt;&lt;/p&gt;&lt;p&gt;I&amp;nbsp;know I’ve glossed over many details here, like the shell syntax for redirection, globbing, subprocesses, the fact that programs have standard input in addition to&amp;nbsp;command-line arguments, pipes, etc. — all these make the analogy rather weak. But I&amp;nbsp;think it’s an interesting way to&amp;nbsp;teach Lisp syntax to&amp;nbsp;people.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2014-04-06:post:dos-debugging-quirk</a:id>
<a:title>DOS debugging quirk</a:title>
<a:link href="http://blog.danieljanus.pl/2014/04/06/dos-debugging-quirk/"/>
<a:updated>2014-04-06T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;While hacking on Lithium, I’ve noticed an interesting thing. Here’s a&amp;nbsp;sample DOS program in assembly (TASM syntax):&lt;/p&gt;&lt;pre&gt;&lt;code class="asm"&gt;.model tiny
.code
org 100h
N equ 2
start:
mov bp,sp
mov ax,100
mov &amp;#91;bp-N&amp;#93;,ax
mov cx,&amp;#91;bp-N&amp;#93;
cmp cx,ax
jne wrong
mov dx,offset msg
jmp disp
wrong:
mov dx,offset msg2
disp:
mov ah,9
int 21h
mov ax,4c00h
int 21h
msg db &amp;quot;ok$&amp;quot;
msg2 db &amp;quot;wrong$&amp;quot;
end start
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you assemble, link and then execute it normally, typing &lt;code&gt;prog&lt;/code&gt; in the DOS command line, it will output the string “ok”. But if you trace through the program in a&amp;nbsp;debugger instead, it will say “wrong”! What’s wrong?&lt;/p&gt;&lt;p&gt;The problem is in lines 10-11 (instructions 3-4). Here’s what happens when you trace through this program in DOS 6.22’s &lt;code&gt;DEBUG.EXE&lt;/code&gt;:&lt;/p&gt;&lt;p&gt;&lt;img src="/img/blog/debug.png"&gt;&lt;/p&gt;&lt;p&gt;Note how in instruction 3 (actually displayed as the second above) we&amp;nbsp;set the word &lt;code&gt;SS:0xFFFC&lt;/code&gt; to&amp;nbsp;&lt;code&gt;100&lt;/code&gt;. When about to&amp;nbsp;execute the following instruction, we&amp;nbsp;would expect that word to&amp;nbsp;continue to&amp;nbsp;hold the value &lt;code&gt;100&lt;/code&gt;, because nothing which could have changed that value has happened in between. Instead, the debugger still reports it as &lt;code&gt;0x0D8A&lt;/code&gt;, as if instruction 3 had not been executed at all — and, interestingly, after actually executing this instruction, &lt;code&gt;CX&lt;/code&gt; gets yet another value of &lt;code&gt;0x7302&lt;/code&gt;!&lt;/p&gt;&lt;p&gt;Normally, thinking of DOS &lt;code&gt;.COM&lt;/code&gt; programs, you assume a&amp;nbsp;64KB-long chunk of memory that the program has all to&amp;nbsp;itself: the code starts at &lt;code&gt;0x100&lt;/code&gt;, the stack grows from &lt;code&gt;0xFFFE&lt;/code&gt; downwards (at any given time, the region from &lt;code&gt;SP&lt;/code&gt; to&amp;nbsp;&lt;code&gt;0xFFFE&lt;/code&gt; contains data currently on the stack), and all memory in between is free for the program to&amp;nbsp;use however it deems fit. It turns out that, when debugging, it is not the case: the debuggers need to&amp;nbsp;manipulate the region just underneath the program’s stack in order to&amp;nbsp;handle the tracing/breakpoint interrupt traps.&lt;/p&gt;&lt;p&gt;I’ve verified that both DOS’s DEBUG and Borland’s Turbo Debugger 5 do&amp;nbsp;this. The unsafe-to-touch amount of space below SP that they need, however, varies. Manipulating the N constant in the original program, I’ve determined that DEBUG only needs 8 bytes below SP, whereas for TD it is a&amp;nbsp;whopping 18 bytes.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2014-04-02:post:2048</a:id>
<a:title>2048: A close look at the source</a:title>
<a:link href="http://blog.danieljanus.pl/2014/04/02/2048/"/>
<a:updated>2014-04-02T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Dust has now mostly settled down on &lt;a href='https://gabrielecirulli.github.io/2048/'&gt;2048&lt;/a&gt;. Yet, in all the deluge of variants and clones that has swept through &lt;a href='https://news.ycombinator.com/'&gt;Hacker News&lt;/a&gt;, little has been written about the experience of modifying the game. As I&amp;nbsp;too have jumped on the 2048-modding bandwagon, it’s time to&amp;nbsp;fill that gap, because, as we&amp;nbsp;shall see, the code more than deserves a&amp;nbsp;close look.&lt;/p&gt;&lt;p&gt;I’ll start with briefly describing my variant. It’s called &lt;a href='http://danieljanus.pl/wosg'&gt;“words oh so great”&lt;/a&gt; (a&amp;nbsp;rather miserable attempt at a&amp;nbsp;pun on “two-oh-four-eight”) and is a&amp;nbsp;consequence of a&amp;nbsp;thought I&amp;nbsp;had, being an avid Scrabble player, after seeing the &lt;a href='http://joppi.github.io/2048-3D/'&gt;3D&lt;/a&gt; and &lt;a href='http://huonw.github.io/2048-4D/'&gt;4D&lt;/a&gt; versions: “what if we&amp;nbsp;mashed 2048 and Scrabble together?” The answer just lended itself automatically.&lt;/p&gt;&lt;p&gt;Letters instead of number tiles, that was obvious. And you use them to&amp;nbsp;form words. It is unclear how merging tiles should work: merging two identical tiles, as in the original, just wouldn’t make sense here, so drop the concept of merging and make the tiles disappear instead when you form a&amp;nbsp;word. In Scrabble, the minimum length of a&amp;nbsp;word is two, but allowing two-letter words here would mean too many words formed accidentally, so make it at least three. And 16 squares sounds like too tight a&amp;nbsp;space, so increase it to&amp;nbsp;5x5. And there you have the modified rules.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;&lt;a href='https://github.com/nathell/wosg'&gt;cloned&lt;/a&gt; the Git repo, downloaded an English word list (&lt;a href='http://dreamsteep.com/projects/the-english-open-word-list.html'&gt;EOWL&lt;/a&gt;), and set out to&amp;nbsp;work. It took me just over three hours from the initial idea to&amp;nbsp;putting the modified version online and submitting a&amp;nbsp;link to&amp;nbsp;HN. I&amp;nbsp;think three hours is not bad, considering that I’ve significantly changed the game mechanics. And, in my opinion, this is a&amp;nbsp;testimony to&amp;nbsp;the quality of Gabriele Cirulli’s code.&lt;/p&gt;&lt;p&gt;The code follows the MVC pattern, despite not relying on any frameworks or libraries. The model is comprised of the &lt;code&gt;Tile&lt;/code&gt; and &lt;code&gt;Grid&lt;/code&gt; classes, laying out the universe for the game as well as some basic rules governing it, and the &lt;code&gt;GameManager&lt;/code&gt; that implements the game mechanics: how tiles move around, when they can merge together, when the game ends, and so on. It also uses a&amp;nbsp;helper class called &lt;code&gt;LocalStorageManager&lt;/code&gt; to&amp;nbsp;keep the score and save it in the browser’s local storage.&lt;/p&gt;&lt;p&gt;The view part is called an “actuator” in 2048 parlance. The &lt;code&gt;HTMLActuator&lt;/code&gt; takes the game state and updates the DOM tree accordingly. It also uses a&amp;nbsp;micro-framework for animations. The controller takes the form of a&amp;nbsp;&lt;code&gt;KeyboardInputManager&lt;/code&gt;, whose job is to&amp;nbsp;receive keyboard events and translate them to&amp;nbsp;changes of the model.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;GameManager&lt;/code&gt; also contains some code to&amp;nbsp;tie it all together — not really a&amp;nbsp;part of the model as in MVC. Despite this slight inconsistency, the separation of concerns is very neatly executed in 2048’s code; I&amp;nbsp;would even go so far as to&amp;nbsp;say that it could be used as a&amp;nbsp;demonstration in teaching MVC to&amp;nbsp;people.&lt;/p&gt;&lt;p&gt;The only gripe I&amp;nbsp;had with the code is that it violates the DRY principle in several places. Specifically, to&amp;nbsp;change the board size to&amp;nbsp;5x5, I&amp;nbsp;had to&amp;nbsp;modify as many as three places: the HTML (it contains the initial definition for the DOM, including 16 empty divs making up the grid, which is unfortunate — I’d change it to&amp;nbsp;set up the DOM at runtime during initialization); the model (instantiation of &lt;code&gt;GameManager&lt;/code&gt;); and the &lt;code&gt;.scss&lt;/code&gt; file from which the CSS is generated.&lt;/p&gt;&lt;p&gt;While on this topic, let me add that 2048’s usage of SASS is a&amp;nbsp;prime example of its capabilities. It is very instructive to&amp;nbsp;see how the sizing and positioning of the grid, and also styling for the tiles down to&amp;nbsp;the glow, is done programmatically. I&amp;nbsp;was aware of the existence of SASS before, but never got around to&amp;nbsp;explore it. Now, I’m sold on it.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;sum up: 2048 rocks. And it’s fun to&amp;nbsp;modify. Go try it.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2013-05-26:post:lithium-revisited</a:id>
<a:title>Lithium revisited: A 16-bit kernel (well, sort of) written in Clojure (well, sort of)</a:title>
<a:link href="http://blog.danieljanus.pl/2013/05/26/lithium-revisited/"/>
<a:updated>2013-05-26T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Remember &lt;a href='http://blog.danieljanus.pl/blog/2012/05/14/lithium/'&gt;Lithium&lt;/a&gt;? The x86 assembler written in Clojure, and a&amp;nbsp;simple stripes effect written in it? Well, here’s another take on that effect:&lt;/p&gt;&lt;p&gt;&lt;img src="/img/blog/stripes2.png"&gt;&lt;/p&gt;&lt;p&gt;And here is the source code:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;do &amp;#40;init-graph&amp;#41;
&amp;#40;loop &amp;#91;x 0 y 0&amp;#93;
&amp;#40;put-pixel x y &amp;#40;let &amp;#91;z &amp;#40;mod &amp;#40;+ &amp;#40;- 319 x&amp;#41; y&amp;#41; 32&amp;#41;&amp;#93;
&amp;#40;if &amp;#40;&amp;lt; z 16&amp;#41; &amp;#40;+ 16 z&amp;#41; &amp;#40;+ 16 &amp;#40;- 31 z&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;if &amp;#40;= y 200&amp;#41;
nil
&amp;#40;if &amp;#40;= x 319&amp;#41;
&amp;#40;recur 0 &amp;#40;inc y&amp;#41;&amp;#41;
&amp;#40;recur &amp;#40;inc x&amp;#41; y&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I’ve implemented this several months ago, pushed it to&amp;nbsp;Github and development has pretty much stalled since then. And after seeing &lt;a href='https://news.ycombinator.com/item?id=5771276'&gt;this recent post&lt;/a&gt; on HN today, I’ve decided to&amp;nbsp;give Lithium a&amp;nbsp;little more publicity, in the hope that it will provide a&amp;nbsp;boost of motivation to&amp;nbsp;me. Because what we&amp;nbsp;have here is pretty similar to&amp;nbsp;Rustboot: it’s a&amp;nbsp;16-bit kernel written in Clojure.&lt;/p&gt;&lt;p&gt;Well, sort of.&lt;/p&gt;&lt;p&gt;After writing a&amp;nbsp;basic assembler capable of building bare binaries of simple x86 real-mode programs, I’ve decided to&amp;nbsp;make it a&amp;nbsp;building block of a&amp;nbsp;larger entity. So I’ve embarked on a&amp;nbsp;project to&amp;nbsp;implement a&amp;nbsp;compiler for a&amp;nbsp;toy Lisp-like language following the paper &lt;a href='http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf'&gt;“An Incremental Approach to&amp;nbsp;Compiler Construction”&lt;/a&gt;, doing it in Clojure and making the implemented language similar to&amp;nbsp;Clojure rather than to&amp;nbsp;Scheme.&lt;/p&gt;&lt;p&gt;(Whether it actually can be called Clojure is debatable. It’s unclear what the definition of Clojure the language is. Is running on JVM a&amp;nbsp;part of what makes Clojure Clojure? Or running on any host platform? Is ClojureScript Clojure? What about ClojureCLR, or clojure-py?)&lt;/p&gt;&lt;p&gt;So far I’ve only gotten to&amp;nbsp;step 7 of 24 or so, but that’s already enough to&amp;nbsp;have a&amp;nbsp;working &lt;code&gt;loop/recur&lt;/code&gt; implementation, and it was trivial to&amp;nbsp;throw in some graphical mode 13h primitives to&amp;nbsp;be able to&amp;nbsp;implement this effect.&lt;/p&gt;&lt;p&gt;By default I’m running Lithium programs as DOS .COM binaries under DOSBox, but technically, the code doesn’t depend on DOS in any way (it doesn’t ever invoke interrupt 21h) and so it can be combined with a&amp;nbsp;simple bootloader into a&amp;nbsp;kernel runnable on the bare metal.&lt;/p&gt;&lt;p&gt;The obligatory HOWTO on reproducing the effect: install DOSBox and Leiningen, checkout &lt;a href=''&gt;the code&lt;/a&gt;, launch a&amp;nbsp;REPL with &lt;code&gt;lein repl&lt;/code&gt;, execute the following forms, and enjoy the slowness with which individual pixels are painted:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;require 'lithium.compiler&amp;#41;
&amp;#40;in-ns 'lithium.compiler&amp;#41;
&amp;#40;run! &amp;#40;compile-program &amp;quot;/path/to/lithium/examples/stripes-grey.clj&amp;quot;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2012-09-13:post:my-top-three-ios-apps-for-mapping</a:id>
<a:title>My top three iOS apps for mapping</a:title>
<a:link href="http://blog.danieljanus.pl/2012/09/13/my-top-three-ios-apps-for-mapping/"/>
<a:updated>2012-09-13T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Living in London means that I&amp;nbsp;now have a&amp;nbsp;whole lot of new area to&amp;nbsp;explore by cycling or walking. I&amp;nbsp;try to&amp;nbsp;take every opportunity to&amp;nbsp;spend a&amp;nbsp;free day or weekend out. One of the most important things when on the move is knowing where you are, where to&amp;nbsp;go, and how to&amp;nbsp;get there — and for that, you need a&amp;nbsp;map. As I&amp;nbsp;soon learned, the maps to&amp;nbsp;use in the UK are the Ordnance Survey ones (either the Landranger/Explorer series, or maps by another publisher, such as AA, based on OS data). However, the Landranger series encompasses over 200 1:50000 maps, standing at some £8 each, and when that level of detail is not enough, there are more than 400 Explorer maps on top of that. Not only does this get pricey after a&amp;nbsp;while, but also the sheer volume of map juggling quickly becomes impractical when you cycle a&amp;nbsp;lot outside of town.&lt;/p&gt;&lt;p&gt;So I’ve turned to&amp;nbsp;my old trusty iPhone 3GS as a&amp;nbsp;mapping device instead, and set out to&amp;nbsp;complete a&amp;nbsp;set of mapping apps that do&amp;nbsp;the job for me. In this post, I’d like to&amp;nbsp;share my list.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;briefly thought of directly using OS maps on the iPhone via the &lt;a href='http://itunes.apple.com/gb/app/outdoors-gb-national-parks/id336150457?mt=8'&gt;Outdoors GPS GB app&lt;/a&gt;; it does meet my requirement of being accessible off-network, but the pricing of individual maps is on par with the paper version, so I&amp;nbsp;ruled it out.&lt;/p&gt;&lt;p&gt;Instead, I&amp;nbsp;am using this trio now:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The official &lt;a href='http://itunes.apple.com/gb/app/the-complete-national-cycle/id436521445?mt=8&amp;amp;ls=1'&gt;National Cycle Network&lt;/a&gt; app by Sustrans. Beside being free, it has an advantage of detailing every numbered national cycle route, as well as most local routes (that often predate NCN or are not yet integrated into the network). At high detail, the data seem to&amp;nbsp;be OS-sourced, which is good.&lt;br&gt;&lt;br&gt; It downloads maps from the Internet on demand, but you can also save a&amp;nbsp;map portion for future use. The app asks you how much detail you want, tells you how large the download will be, then proceeds to&amp;nbsp;get the data. The nuisance here is that you can only download 40 MB in one go, which corresponds to&amp;nbsp;an area stretching for approximately 50-60 km at 1:50000 (and correspondingly smaller at 1:25000), so it takes a&amp;nbsp;lot of tapping and downloading if you’re planning a&amp;nbsp;longer trip.&lt;br&gt;&lt;br&gt; The other downsides are that the app is a&amp;nbsp;little shaky at times, and GPS positioning sometimes displays your position somewhat misplaced. I&amp;nbsp;mitigate this by using this app in combination with the next one…&lt;br&gt;&lt;br&gt;&lt;/li&gt;&lt;li&gt;…which is &lt;a href='http://www.mapswithme.com/'&gt;MapsWithMe&lt;/a&gt;. The tagline “Offline Mobile Maps” nails it down: it’s just maps, easily downloadable, covering the entire world, and nothing else. This really does one thing well. The map data source is OpenStreetMap, so all the maps are available for free as well; one ‘Download’ tap and you’ve got the whole country covered, once and for all. It also displays GPS position much more reliably than NCN. On the other hand, it can’t offer quite the same level of detail as NCN, and doesn’t know anything about cycle routes, but it’s still highly convenient.&lt;br&gt;&lt;br&gt; My typical flow when cycling in the UK is: check my position with MapsWithMe, then optionally switch to&amp;nbsp;NCN, locate the same position on the map by hand and see where the route goes. I’ve also done one continental three-day trip, from Dunkirk in France to&amp;nbsp;Hoek van Holland in the Netherlands, using just MapsWithMe to&amp;nbsp;navigate, and it worked out very well.&lt;br&gt;&lt;br&gt;&lt;/li&gt;&lt;li&gt;Unlike the other two, the last app I&amp;nbsp;want to&amp;nbsp;point out, &lt;a href='http://www.codeartisans.co.uk/index.html'&gt;GPS2OS&lt;/a&gt;, is paid. And it’s more than worth its meager price, despite being next to&amp;nbsp;useless when cycling. But when hiking, especially in remote mountainous areas, it can literally be a&amp;nbsp;lifesaver. Here’s the catch: my basic navigation tools in harsh conditions are a&amp;nbsp;compass and a&amp;nbsp;plain ol’ paper map, and the iPhone is treated only as a&amp;nbsp;supplementary aid (you never know when the battery goes out). However, instead of indicating the latitude and longitude in degrees/minutes/seconds, OS maps use &lt;a href='http://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid'&gt;their own grid&lt;/a&gt;. So you cannot use the default Compass app, which tells you your position in degrees, directly with them, and you need a&amp;nbsp;tool just like this one to&amp;nbsp;do&amp;nbsp;the coordinate translation. Works very well; it helped me find my way in dense mist down from the summit of Ben Macdui during my recent holiday in Scotland.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;One final tip: when you want to&amp;nbsp;conserve battery as much as possible, airplane mode is a&amp;nbsp;real saver. However, GPS doesn’t seem to&amp;nbsp;work when airplane mode is on. So the next best thing is to&amp;nbsp;remove the SIM card (you can then reinsert it, just don’t enter the PIN), so that the phone doesn’t keep trying to&amp;nbsp;connect to&amp;nbsp;cellular networks. And keep it warm in a&amp;nbsp;pocket beside your body: cold devices discharge much faster.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2012-05-14:post:lithium</a:id>
<a:title>Lithium: an x86 assembler for Clojure</a:title>
<a:link href="http://blog.danieljanus.pl/2012/05/14/lithium/"/>
<a:updated>2012-05-14T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Ah, the golden days of childhood’s hackage. Don’t you have fond memories of them?&lt;/p&gt;&lt;p&gt;I&amp;nbsp;got my first PC when I&amp;nbsp;was 10. It was a&amp;nbsp;486DX2/66 with 4 megs of RAM and a&amp;nbsp;170 meg HDD; it ran DOS and had lots of things installed on it, notably Turbo Pascal 6. I&amp;nbsp;hacked a&amp;nbsp;lot in it. These were pre-internet days when knowledge was hard to&amp;nbsp;come by, especially for someone living in a&amp;nbsp;&lt;a href='http://en.wikipedia.org/wiki/W%C4%85chock'&gt;small town in Poland&lt;/a&gt;; my main sources were the software I&amp;nbsp;had (TP’s online help was of excellent quality), a&amp;nbsp;couple of books, and a&amp;nbsp;&lt;a href='http://www.cpcwiki.eu/index.php/Bajtek'&gt;popular computing magazine&lt;/a&gt; that published articles on programming. From the latter, I&amp;nbsp;learned how to&amp;nbsp;program the VGA: how to&amp;nbsp;enter mode 13h, draw pixels on screen, wait for vertical retrace, manipulate the palette and how to&amp;nbsp;combine these things into neat effects. One of the very first thing I&amp;nbsp;discovered was when you plot every pixel using sum of its coordinates modulo 40 as color, you get a&amp;nbsp;nice-looking diagonal stripes effect. Because of the initially incomprehensible inline assembly snippets appearing all over the place, I&amp;nbsp;eventually learned x86 assembly, too.&lt;/p&gt;&lt;p&gt;&lt;img src="/img/blog/stripes.png"&gt;&lt;/p&gt;&lt;p&gt;Back to&amp;nbsp;2012: I’ve long been wanting to&amp;nbsp;hack on something just for pure fun, a&amp;nbsp;side pet project. Writing code for the bare metal is fun because it’s just about as close as you can get to&amp;nbsp;wielding the ultimate power. And yet, since Clojure is so much fun too, I&amp;nbsp;wanted the project to&amp;nbsp;have something to&amp;nbsp;do&amp;nbsp;with Clojure.&lt;/p&gt;&lt;p&gt;So here’s &lt;a href='http://github.com/nathell/lithium'&gt;Lithium&lt;/a&gt;, an x86 16-bit assembler written in pure Clojure and capable of assembling a&amp;nbsp;binary version of the stripes effect.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;try it, clone the git repo to&amp;nbsp;your Linux or OS X machine, install DOSBox, launch a&amp;nbsp;REPL with Leiningen, change to&amp;nbsp;the &lt;code&gt;lithium&lt;/code&gt; namespace and say:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;run! &amp;quot;/home/you/lithium/src/stripes.li.clj&amp;quot;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;FAQ&lt;/h3&gt;&lt;p&gt;(Well, this is not really a&amp;nbsp;FAQ since nobody actually asked me any questions about Lithium yet. This is more in anticipation of questions that may arise.)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;What’s the importance of this?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href='http://www.physics.ohio-state.edu/~kilcup/262/feynman.html'&gt;None whatsoever&lt;/a&gt;. It’s just for fun.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;How complete is it?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Very incomplete. To&amp;nbsp;even call it pre-pre-alpha would be an exaggeration. It’s currently little more than pure minimum required to&amp;nbsp;assemble &lt;code&gt;stripes.li.clj&lt;/code&gt;. Output format wise, it only produces bare binaries (similar to&amp;nbsp;DOS .COMs), and that’s unlikely to&amp;nbsp;change anytime soon.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Do&amp;nbsp;you intend to&amp;nbsp;continue developing it?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Absolutely. I&amp;nbsp;will try to&amp;nbsp;make it more complete, add 32- and possibly 64-bit modes, see how to&amp;nbsp;add a&amp;nbsp;macro system (since the input is s-expressions, it should be easy to&amp;nbsp;produce Clojure macros to&amp;nbsp;write assembly), write something nontrivial in it, and see how it can be used as a&amp;nbsp;backend for some higher-level language compiler (I’m not sure yet which language that will turn out to&amp;nbsp;be).&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2012-04-25:post:how-to-call-a-private-function-in-clojure</a:id>
<a:title>How to call a private function in Clojure</a:title>
<a:link href="http://blog.danieljanus.pl/2012/04/25/how-to-call-a-private-function-in-clojure/"/>
<a:updated>2012-04-25T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; Don’t do&amp;nbsp;it. If you really have to, use &lt;code&gt;&amp;#40;#'other-library/private-function args&amp;#41;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;hr&gt;&lt;/p&gt;&lt;p&gt;A&amp;nbsp;private function in Clojure is one that has been defined using the &lt;code&gt;defn-&lt;/code&gt; macro, or equivalently by setting the metadata key &lt;code&gt;:private&lt;/code&gt; to&amp;nbsp;&lt;code&gt;true&lt;/code&gt; on the var that holds the function. It is normally not allowed in Clojure to&amp;nbsp;call such functions from outside of the namespace where they have been defined. Trying to&amp;nbsp;do&amp;nbsp;so results in an &lt;code&gt;IllegalStateException&lt;/code&gt; stating that the var is not public.&lt;/p&gt;&lt;p&gt;It is possible to&amp;nbsp;circumvent this and call the private function, but it is not recommended. That the author of the library decided to&amp;nbsp;make a&amp;nbsp;function private probably means that he considers it to&amp;nbsp;be an implementation detail, subject to&amp;nbsp;change at any time, and that you should not rely on it being there. If you think it would be useful to&amp;nbsp;have this functionality available as part of the public API, your best bet is to&amp;nbsp;contact the library author and consult the change, so that it may be included officially in a&amp;nbsp;future version.&lt;/p&gt;&lt;p&gt;Contacting the author, however, is not always feasible: she may not be available or you might be in haste. In this case, several workarounds are available. The simplest is to&amp;nbsp;use &lt;code&gt;&amp;#40;#'other-library/private-function args&amp;#41;&lt;/code&gt;, which works in Clojure 1.2.1 and 1.3.0 (it probably works in other versions of Clojure as well, but I&amp;nbsp;haven’t checked that).&lt;/p&gt;&lt;p&gt;Why does this work? When the Clojure compiler encounters a&amp;nbsp;form &lt;code&gt;&amp;#40;sym args&amp;#41;&lt;/code&gt;, it invokes &lt;code&gt;analyzeSeq&lt;/code&gt; on that form. If its first element is a&amp;nbsp;symbol, it proceeds to&amp;nbsp;analyze that symbol. One of the first operation in that analysis is checking if it names an inline function, by calling &lt;code&gt;isInline&lt;/code&gt;. That function looks into the metadata of the Var named by the symbol in question. If it’s not public, it &lt;a href='https://github.com/clojure/clojure/blob/clojure-1.3.0/src/jvm/clojure/lang/Compiler.java#L6281'&gt;throws an exception&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;On the other hand, &lt;code&gt;#'&lt;/code&gt; is the reader macro for var. So our workaround is equivalent to&amp;nbsp;&lt;code&gt;&amp;#40;&amp;#40;var other-library/private-function&amp;#41; args&amp;#41;&lt;/code&gt;. In this case, the first element of the form is not a&amp;nbsp;symbol, but a&amp;nbsp;form that evaluates to&amp;nbsp;a&amp;nbsp;var. The compiler is not able to&amp;nbsp;check for this so it does not insert a&amp;nbsp;check for privateness. So the code compiles to&amp;nbsp;calling a&amp;nbsp;Var object.&lt;/p&gt;&lt;p&gt;Here’s the catch: Vars are callable, just like functions. They &lt;a href='https://github.com/clojure/clojure/blob/clojure-1.3.0/src/jvm/clojure/lang/Var.java#L18'&gt;implement &lt;code&gt;IFn&lt;/code&gt;&lt;/a&gt;. When a&amp;nbsp;var is called, it delegates the call to&amp;nbsp;the &lt;code&gt;IFn&lt;/code&gt; object it is holding. This has been recently &lt;a href='https://groups.google.com/d/msg/clojure/1Su9o_8JZ8g/uZL-n4uRSiUJ'&gt;discussed on the Clojure group&lt;/a&gt;. Since that delegation does not check for the var’s privateness either, the net effect is that we&amp;nbsp;are able to&amp;nbsp;call a&amp;nbsp;private function this way.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2012-04-12:post:lifehacking-gumtree</a:id>
<a:title>Lifehacking: How to get cheap home equipment using Clojure</a:title>
<a:link href="http://blog.danieljanus.pl/2012/04/12/lifehacking-gumtree/"/>
<a:updated>2012-04-12T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve moved to&amp;nbsp;London last September. Like many new Londoners, I&amp;nbsp;have changed accommodation fairly quickly, being already after one removal and with another looming in a&amp;nbsp;couple of months; my current flat was largely unfurnished when I&amp;nbsp;moved in, so I&amp;nbsp;had to&amp;nbsp;buy some basic homeware. I&amp;nbsp;didn’t want to&amp;nbsp;invest much in it, since it’d be only for a&amp;nbsp;few months. Luckily, it is not hard to&amp;nbsp;do&amp;nbsp;that cheaply: many people are moving out and getting rid of their stuff, so quite often you can search for the desired item on &lt;a href='http://www.gumtree.com/london'&gt;Gumtree&lt;/a&gt; and find there’s a&amp;nbsp;cheap one a&amp;nbsp;short bike ride away.&lt;/p&gt;&lt;p&gt;Except when there isn’t. In this case, it’s worthwhile to&amp;nbsp;check again within a&amp;nbsp;few days as new items are constantly being posted. Being lazy, I’ve decided to&amp;nbsp;automate this. A&amp;nbsp;few hours and a&amp;nbsp;hundred lines of Clojure later, &lt;a href='https://github.com/nathell/gumtree-scraper'&gt;gumtree-scraper&lt;/a&gt; was born.&lt;/p&gt;&lt;p&gt;I’ve packaged it using &lt;code&gt;lein uberjar&lt;/code&gt; into a&amp;nbsp;standalone jar, which, when run, produces a&amp;nbsp;&lt;code&gt;gumtree.rss&lt;/code&gt; that is included in my Google Reader subscriptions. This way, whenever something I’m interested in appears, I&amp;nbsp;get notified within an hour or so.&lt;/p&gt;&lt;p&gt;It’s driven by a&amp;nbsp;Google spreadsheet. I’ve created a&amp;nbsp;sheet that has three columns: item name, minimum price, maximum price; then I’ve made it available to&amp;nbsp;anyone who knows the URL. This way I&amp;nbsp;can edit it pretty much from everywhere without touching the script. Each time the script is run (by cron), it downloads that spreadsheet as a&amp;nbsp;CSV that looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;hand blender,,5
bike rack,,15
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For each row the script queries Gumtree’s category “For Sale” within London given the price range, gets each result and transforms it to&amp;nbsp;a&amp;nbsp;RSS entry.&lt;/p&gt;&lt;p&gt;Gumtree has no API, so I’m using screenscraping to&amp;nbsp;retrieve all the data. Because the structure of the pages is much simpler, I’m actually scraping the &lt;a href='http://m.gumtree.com/'&gt;mobile version&lt;/a&gt;; a&amp;nbsp;technical twist here is that the mobile version is only served to&amp;nbsp;actual browsers so I’m supplying a&amp;nbsp;custom User-Agent, pretending to&amp;nbsp;be Safari. For actual scraping, the code uses &lt;a href='https://github.com/cgrand/enlive'&gt;Enlive&lt;/a&gt;; it works out nicely.&lt;/p&gt;&lt;p&gt;About half of the code is RSS generation — mostly XML emitting. I’d use &lt;code&gt;clojure.xml/emit&lt;/code&gt; but it’s known to&amp;nbsp;&lt;a href='http://clojure-log.n01se.net/date/2012-01-03.html#17:28a'&gt;produce malformed XML&lt;/a&gt; at times, so I&amp;nbsp;include a&amp;nbsp;variant that should work.&lt;/p&gt;&lt;p&gt;In case anyone wants to&amp;nbsp;tries it out, be aware that the location and category are hardcoded in the search URL template; if you want, change the template line in &lt;code&gt;get-page&lt;/code&gt;. The controller spreadsheet URL is not, however, hardcoded; it’s built up using the &lt;code&gt;spreadsheet.key&lt;/code&gt; system property. Here’s the wrapper script I&amp;nbsp;use that is actually run by cron:&lt;/p&gt;&lt;pre&gt;&lt;code class="bash"&gt;#!/bin/bash
if &amp;#91; &amp;quot;`ps ax | grep java | grep gumtree`&amp;quot; &amp;#93;; then
echo &amp;quot;already running, exiting&amp;quot;
exit 0
fi
cd &amp;quot;`dirname $0`&amp;quot;
java -Dspreadsheet.key=MY&amp;#95;SECRET&amp;#95;KEY -jar $HOME/gumtree/gumtree.jar
cp $HOME/gumtree/gumtree.rss $HOME/public&amp;#95;html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let me remove that entry for a&amp;nbsp;blender — I’ve bought one yesterday for £4…&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2012-03-21:post:court-with-an-api</a:id>
<a:title>Ever wanted to programmatically file a lawsuit? In Poland, you can.</a:title>
<a:link href="http://blog.danieljanus.pl/2012/03/21/court-with-an-api/"/>
<a:updated>2012-03-21T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;This has somehow escaped me: just over a&amp;nbsp;year ago, the Sixth Civil Division of the Lublin-West Regional Court in Lublin, Poland, has opened its &lt;a href='https://www.e-sad.gov.pl/'&gt;online branch&lt;/a&gt;. It serves the entire territory of Poland and is competent to&amp;nbsp;recognize lawsuits concerning payment claims. There is &lt;a href='https://www.e-sad.gov.pl/Subpage.aspx?page_id=35'&gt;basic information&lt;/a&gt; available in English. It has proven immensely popular, having processed about two million cases in its first year of operation.&lt;/p&gt;&lt;p&gt;And the really cool thing is, &lt;i&gt;they have an API&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;It’s SOAP-based and has a&amp;nbsp;&lt;a href='https://www.e-sad.gov.pl/Subpage.aspx?page_id=32'&gt;publicly available spec&lt;/a&gt;. (Due to&amp;nbsp;the way their web site is constructed, I&amp;nbsp;cannot link to&amp;nbsp;the spec directly; this last link leads to&amp;nbsp;a&amp;nbsp;collection of files related to&amp;nbsp;the web service. The spec is called &lt;code&gt;EpuWS&amp;#95;ver.1.14.1.pdf&lt;/code&gt;; it’s in Polish only, but it should be easy to&amp;nbsp;run it through Google Translate.) There are a&amp;nbsp;couple of XML schemas as well, plus the spec contains links to&amp;nbsp;a&amp;nbsp;WSDL and some code samples (in C#) at the end.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;actually use the API, you need to&amp;nbsp;get yourself an account of the appropriate type (there are two types corresponding to&amp;nbsp;two groups of methods one can use: that of a&amp;nbsp;bailiff and of a&amp;nbsp;mass plaintiff). You then log on to&amp;nbsp;the system, where you can create an API key that is later used for authentication. They throttle the speed down to&amp;nbsp;1 req/s per user to&amp;nbsp;mitigate DoS attacks.&lt;/p&gt;&lt;p&gt;The methods include &lt;code&gt;FileLawsuits&lt;/code&gt;, &lt;code&gt;FileComplaints&lt;/code&gt;, &lt;code&gt;SupplyDocuments&lt;/code&gt;, &lt;code&gt;GetCaseHistory&lt;/code&gt; and so on (the actual names are in Polish). To&amp;nbsp;give you an example, the &lt;code&gt;FileLawsuits&lt;/code&gt; method returns a&amp;nbsp;structure that consists of, &lt;i&gt;inter alia&lt;/i&gt;, the amount of court fee to&amp;nbsp;pay, the value of the matter of dispute (both broken down into individual lawsuits), and a&amp;nbsp;status code with a&amp;nbsp;description.&lt;/p&gt;&lt;p&gt;iOS app, anyone?&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-12-09:post:combining-virtual-sequences</a:id>
<a:title>Combining virtual sequences&lt;br&gt;or, Sequential Fun with Macros&lt;br&gt;or, How to Implement Clojure-Like Pseudo-Sequences with Poor Man’s Laziness in a Predominantly Imperative Language</a:title>
<a:link href="http://blog.danieljanus.pl/2011/12/09/combining-virtual-sequences/"/>
<a:updated>2011-12-09T00:00:00Z</a:updated>
<a:content type="html">&lt;h2&gt;Sequences and iteration&lt;/h2&gt;&lt;p&gt;There are a&amp;nbsp;number of motivations for this post. One stems from my extensive exposure to&amp;nbsp;Clojure over the past few years: this was, and still is, my primary programming language for everyday work. Soon, I&amp;nbsp;realized that much of the power of Clojure comes from a&amp;nbsp;&lt;i&gt;sequence&lt;/i&gt; abstraction being one of its central concepts, and a&amp;nbsp;standard library that contains many sequence-manipulating functions. It turns out that by combining them it is possible to&amp;nbsp;solve a&amp;nbsp;wide range of problems in a&amp;nbsp;concise, high-level way. In contrast, it pays to&amp;nbsp;think in terms of whole sequences, rather than individual elements.&lt;/p&gt;&lt;p&gt;Another motivation comes from a&amp;nbsp;classical piece of functional programming humour, &lt;a href=''&gt;The Evolution of a&amp;nbsp;Haskell Programmer&lt;/a&gt;. If you don’t know it, go check it out: it consists of several Haskell implementations of factorial, starting out from a&amp;nbsp;straightforward recursive definition, passing through absolutely hilarious versions involving category-theoretical concepts, and finally arriving at this simple version that is considered most idiomatic:&lt;/p&gt;&lt;pre&gt;&lt;code class="haskell"&gt;fac n = product &amp;#91;1..n&amp;#93;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very Clojure-like in that it involves a&amp;nbsp;sequence (a&amp;nbsp;list comprehension). In Clojure, this could be implemented as&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn fac &amp;#91;n&amp;#93;
&amp;#40;reduce &amp;#42; 1 &amp;#40;range 1 &amp;#40;inc n&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, I&amp;nbsp;thought to&amp;nbsp;myself, how would I&amp;nbsp;write factorial in an imperative language? Say, Pascal?&lt;/p&gt;&lt;pre&gt;&lt;code class="pascal"&gt;function fac&amp;#40;n : integer&amp;#41; : integer;
var
i, res : integer;
begin
res := 1;
for i := 1 to n do
res := res &amp;#42; i;
fac := res;
end;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very different from the functional version that works with sequences. It is much more elaborate, introducing an explicit loop. On the other hand, it’s memory efficient: it’s clear that its memory requirements are O(1), whereas a&amp;nbsp;naïve implementation of a&amp;nbsp;sequence would need O(n) to&amp;nbsp;construct it all in memory and then reduce it down to&amp;nbsp;a&amp;nbsp;single value.&lt;/p&gt;&lt;p&gt;Or is it really that different? Think of the changing values of &lt;code&gt;i&lt;/code&gt; in that loop. On first iteration it is 1, on second iteration it’s 2, and so on up to&amp;nbsp;n. Therefore, one can really think of a&amp;nbsp;&lt;code&gt;for&lt;/code&gt; loop as a&amp;nbsp;sequence! I&amp;nbsp;call it a&amp;nbsp;“virtual” sequence, since it is not an actual data structure; it’s just a&amp;nbsp;snippet of code.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;rephrase it as a&amp;nbsp;definition: a&amp;nbsp;virtual sequence is a&amp;nbsp;snippet of code that (presumably repeatedly) &lt;i&gt;yields&lt;/i&gt; the member values.&lt;/p&gt;&lt;h2&gt;Let’s write some code!&lt;/h2&gt;&lt;p&gt;To&amp;nbsp;illustrate it, throughout the remainder of this article I&amp;nbsp;will be using Common Lisp, for the following reasons:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It allows for imperative style, including GOTO-like statements. This will enable us to&amp;nbsp;generate very low-level code.&lt;/li&gt;&lt;li&gt;Thanks to&amp;nbsp;macros, we&amp;nbsp;will be able to&amp;nbsp;obtain interesting transformations.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Okay, so let’s have a&amp;nbsp;look at how to&amp;nbsp;generate a&amp;nbsp;one-element sequence. Simple enough:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro vsingle &amp;#40;x&amp;#41;
`&amp;#40;yield ,x&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The name &lt;code&gt;VSINGLE&lt;/code&gt; stands for “Virtual sequence that just yields a&amp;nbsp;SINGLE element”. (In general, I&amp;nbsp;will try to&amp;nbsp;define virtual sequences named and performing similarly to&amp;nbsp;their Clojure counterparts here; whenever there is a&amp;nbsp;name clash with an already existing CL function, the name will be prefixed with &lt;code&gt;V&lt;/code&gt;.) We&amp;nbsp;will not concern ourselves with the actual definition of &lt;code&gt;YIELD&lt;/code&gt; at the moment; for debugging, we&amp;nbsp;can define it just as printing the value to&amp;nbsp;the standard output.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun yield &amp;#40;x&amp;#41;
&amp;#40;format t &amp;quot;&amp;#126;A&amp;#126;%&amp;quot; x&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;nbsp;can also convert a&amp;nbsp;Lisp list to&amp;nbsp;a&amp;nbsp;virtual sequence which just yields each element of the list in turn:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro vseq &amp;#40;list&amp;#41;
`&amp;#40;loop for x in ,list do &amp;#40;yield x&amp;#41;&amp;#41;&amp;#41;
&amp;#40;defmacro vlist &amp;#40;&amp;amp;rest elems&amp;#41;
`&amp;#40;vseq &amp;#40;list ,@elems&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s try to&amp;nbsp;define &lt;code&gt;RANGE&lt;/code&gt;. We&amp;nbsp;could use &lt;code&gt;loop&lt;/code&gt;, but for the sake of example, let’s pretend that it doesn’t exist and write a&amp;nbsp;macro that expands to&amp;nbsp;low-level GOTO-ridden code. For those of you who are not familiar with Common Lisp, &lt;code&gt;GO&lt;/code&gt; is like GOTO, except it takes a&amp;nbsp;label that should be established within a&amp;nbsp;&lt;code&gt;TAGBODY&lt;/code&gt; container.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro range &amp;#40;start &amp;amp;optional end &amp;#40;step 1&amp;#41;&amp;#41;
&amp;#40;unless end
&amp;#40;setf end start start 0&amp;#41;&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;fv &amp;#40;gensym&amp;#41;&amp;#41;&amp;#41;
`&amp;#40;let &amp;#40;&amp;#40;,fv ,start&amp;#41;&amp;#41;
&amp;#40;tagbody
loop
&amp;#40;when &amp;#40;&amp;gt;= ,fv ,end&amp;#41;
&amp;#40;go out&amp;#41;&amp;#41;
&amp;#40;yield ,fv&amp;#41;
&amp;#40;incf ,fv ,step&amp;#41;
&amp;#40;go loop&amp;#41;
out&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;i&gt;Infinite&lt;/i&gt; virtual sequences are also possible. After all, there’s nothing preventing us from considering a&amp;nbsp;snippet of code that loops infinitely, executing &lt;code&gt;YIELD&lt;/code&gt;, as a&amp;nbsp;virtual sequence! We&amp;nbsp;will define the equivalent of Clojure’s iterate: given a&amp;nbsp;function &lt;code&gt;fun&lt;/code&gt; and initial value &lt;code&gt;val&lt;/code&gt;, it will repeatedly generate &lt;code&gt;val&lt;/code&gt;, &lt;code&gt;&amp;#40;fun val&amp;#41;&lt;/code&gt;, &lt;code&gt;&amp;#40;fun &amp;#40;fun val&amp;#41;&amp;#41;&lt;/code&gt;, etc.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro iterate &amp;#40;fun val&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;fv &amp;#40;gensym&amp;#41;&amp;#41;&amp;#41;
`&amp;#40;let &amp;#40;&amp;#40;,fv ,val&amp;#41;&amp;#41;
&amp;#40;tagbody loop
&amp;#40;yield ,fv&amp;#41;
&amp;#40;setf ,fv &amp;#40;funcall ,fun ,fv&amp;#41;&amp;#41;
&amp;#40;go loop&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far, we&amp;nbsp;have defined a&amp;nbsp;number of ways to&amp;nbsp;create virtual sequences. Now let’s ask ourselves: is there a&amp;nbsp;way, given code for a&amp;nbsp;virtual sequence, to&amp;nbsp;yield only the elements from the original that satisfy a&amp;nbsp;certain predicate? In other words, can we&amp;nbsp;define a&amp;nbsp;&lt;code&gt;filter&lt;/code&gt; for virtual sequences? Sure enough. Just replace every occurrence of &lt;code&gt;yield&lt;/code&gt; with code that checks whether the yielded value satisfies the predicate, and only if it does invokes &lt;code&gt;yield&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;First we&amp;nbsp;write a&amp;nbsp;simple code walker that applies some transformation to&amp;nbsp;every &lt;code&gt;yield&lt;/code&gt; occurrence in a&amp;nbsp;given snippet:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun replace-yield &amp;#40;tree replace&amp;#41;
&amp;#40;if &amp;#40;consp tree&amp;#41;
&amp;#40;if &amp;#40;eql &amp;#40;car tree&amp;#41; 'yield&amp;#41;
&amp;#40;funcall replace &amp;#40;cadr tree&amp;#41;&amp;#41;
&amp;#40;loop for x in tree collect &amp;#40;replace-yield x replace&amp;#41;&amp;#41;&amp;#41;
tree&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;nbsp;can now write &lt;code&gt;filter&lt;/code&gt; like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro filter &amp;#40;pred vseq &amp;amp;environment env&amp;#41;
&amp;#40;replace-yield &amp;#40;macroexpand vseq env&amp;#41;
&amp;#40;lambda &amp;#40;x&amp;#41; `&amp;#40;when &amp;#40;funcall ,pred ,x&amp;#41; &amp;#40;yield ,x&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is important to&amp;nbsp;point out that since &lt;code&gt;filter&lt;/code&gt; is a&amp;nbsp;macro, the arguments are passed to&amp;nbsp;it unevaluated, so if &lt;code&gt;vseq&lt;/code&gt; is a&amp;nbsp;virtual sequence definition like &lt;code&gt;&amp;#40;range 10&amp;#41;&lt;/code&gt;, we&amp;nbsp;need to&amp;nbsp;macroexpand it before replacing &lt;code&gt;yield&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;We&amp;nbsp;can now verify that &lt;code&gt;&amp;#40;filter #'evenp &amp;#40;range 10&amp;#41;&amp;#41;&lt;/code&gt; works. It macroexpands to&amp;nbsp;something similar to&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;LET &amp;#40;&amp;#40;#:G70192 0&amp;#41;&amp;#41;
&amp;#40;TAGBODY
LOOP &amp;#40;IF &amp;#40;&amp;gt;= #:G70192 10&amp;#41;
&amp;#40;PROGN &amp;#40;GO OUT&amp;#41;&amp;#41;&amp;#41;
&amp;#40;IF &amp;#40;FUNCALL #'EVENP #:G70192&amp;#41;
&amp;#40;PROGN &amp;#40;YIELD #:G70192&amp;#41;&amp;#41;&amp;#41;
&amp;#40;SETQ #:G70192 &amp;#40;+ #:G70192 1&amp;#41;&amp;#41;
&amp;#40;GO LOOP&amp;#41;
OUT&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;concat&lt;/code&gt; is extremely simple. To&amp;nbsp;produce all elements of &lt;code&gt;vseq1&lt;/code&gt; followed by all elements of &lt;code&gt;vseq2&lt;/code&gt;, just execute code corresponding to&amp;nbsp;&lt;code&gt;vseq1&lt;/code&gt; and then code corresponding to&amp;nbsp;&lt;code&gt;vseq2&lt;/code&gt;. Or, for multiple sequences:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro concat &amp;#40;&amp;amp;rest vseqs&amp;#41;
`&amp;#40;progn ,@vseqs&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To&amp;nbsp;define &lt;code&gt;take&lt;/code&gt;, we’ll need to&amp;nbsp;wrap the original code in a&amp;nbsp;block that can be escaped from by means of &lt;code&gt;return-from&lt;/code&gt; (which is just another form of &lt;code&gt;goto&lt;/code&gt;). We’ll add a&amp;nbsp;counter that will start from &lt;code&gt;n&lt;/code&gt; and keep decreasing on each &lt;code&gt;yield&lt;/code&gt;; once it reaches zero, we&amp;nbsp;escape the block:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro take &amp;#40;n vseq &amp;amp;environment env&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;x &amp;#40;gensym&amp;#41;&amp;#41;
&amp;#40;b &amp;#40;gensym&amp;#41;&amp;#41;&amp;#41;
`&amp;#40;let &amp;#40;&amp;#40;,x ,n&amp;#41;&amp;#41;
&amp;#40;block ,b
,&amp;#40;replace-yield &amp;#40;macroexpand vseq env&amp;#41;
&amp;#40;lambda &amp;#40;y&amp;#41; `&amp;#40;progn &amp;#40;yield ,y&amp;#41;
&amp;#40;decf ,x&amp;#41;
&amp;#40;when &amp;#40;zerop ,x&amp;#41;
&amp;#40;return-from ,b&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;rest&lt;/code&gt; (or, rather, &lt;code&gt;vrest&lt;/code&gt;, as that name is taken) can be defined similarly:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro vrest &amp;#40;vseq &amp;amp;environment env&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;skipped &amp;#40;gensym&amp;#41;&amp;#41;&amp;#41;
&amp;#40;replace-yield
`&amp;#40;let &amp;#40;&amp;#40;,skipped nil&amp;#41;&amp;#41; ,&amp;#40;macroexpand vseq env&amp;#41;&amp;#41;
&amp;#40;lambda &amp;#40;x&amp;#41; `&amp;#40;if ,skipped &amp;#40;yield ,x&amp;#41; &amp;#40;setf ,skipped t&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;vfirst&lt;/code&gt; is another matter. It should return a&amp;nbsp;value instead of producing a&amp;nbsp;virtual sequence, so we&amp;nbsp;need to&amp;nbsp;actually execute the code — but with &lt;code&gt;yield&lt;/code&gt; bound to&amp;nbsp;something else. We&amp;nbsp;want to&amp;nbsp;establish a&amp;nbsp;block as with &lt;code&gt;take&lt;/code&gt;, but our &lt;code&gt;yield&lt;/code&gt; will immediately return from the block once the first value is yielded:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro vfirst &amp;#40;vseq&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;block-name &amp;#40;gensym&amp;#41;&amp;#41;&amp;#41;
`&amp;#40;block ,block-name
&amp;#40;flet &amp;#40;&amp;#40;yield &amp;#40;x&amp;#41; &amp;#40;return-from ,block-name x&amp;#41;&amp;#41;&amp;#41;
,vseq&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that so far we’ve seen three classes of macros:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;macros that create virtual sequences;&lt;/li&gt;&lt;li&gt;macros that transform virtual sequences to&amp;nbsp;another virtual sequences;&lt;/li&gt;&lt;li&gt;and finally, vfirst is our first example of a&amp;nbsp;macro that produces a&amp;nbsp;result out of a&amp;nbsp;virtual sequence.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Our next logical step is &lt;code&gt;vreduce&lt;/code&gt;. Again, we’ll produce code that rebinds &lt;code&gt;yield&lt;/code&gt;: this time to&amp;nbsp;a&amp;nbsp;function that replaces the value of a&amp;nbsp;variable (the accumulator) by result of calling a&amp;nbsp;function on the accumulator’s old value and the value being yielded.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defmacro vreduce &amp;#40;f val vseq&amp;#41;
`&amp;#40;let &amp;#40;&amp;#40;accu ,val&amp;#41;&amp;#41;
&amp;#40;flet &amp;#40;&amp;#40;yield &amp;#40;x&amp;#41; &amp;#40;setf accu &amp;#40;funcall ,f accu x&amp;#41;&amp;#41;&amp;#41;&amp;#41;
,vseq
accu&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;nbsp;can now build a&amp;nbsp;constructs that executes a&amp;nbsp;virtual sequence and wraps the results up as a&amp;nbsp;Lisp list, in terms of &lt;code&gt;vreduce&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun conj &amp;#40;x y&amp;#41;
&amp;#40;cons y x&amp;#41;&amp;#41;
&amp;#40;defmacro realize &amp;#40;vseq&amp;#41;
`&amp;#40;nreverse &amp;#40;vreduce #'conj nil ,vseq&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s verify that it works:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;CL-USER&amp;gt; &amp;#40;realize &amp;#40;range 10&amp;#41;&amp;#41;
&amp;#40;0 1 2 3 4 5 6 7 8 9&amp;#41;
CL-USER&amp;gt; &amp;#40;realize &amp;#40;take 5 &amp;#40;filter #'oddp &amp;#40;iterate #'1+ 0&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;1 3 5 7 9&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hey! Did we&amp;nbsp;just manipulate an &lt;i&gt;infinite&lt;/i&gt; sequence and got the result in a&amp;nbsp;&lt;i&gt;finite&lt;/i&gt; amount of time? And that without explicit support for laziness in our language? How cool is that?!&lt;/p&gt;&lt;p&gt;Anyway, let’s finally define our factorial:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun fac &amp;#40;n&amp;#41;
&amp;#40;vreduce #'&amp;#42; 1 &amp;#40;range 1 &amp;#40;1+ n&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Benchmarking&lt;/h2&gt;&lt;p&gt;Factorials grow too fast, so for the purpose of benchmarking let’s write a&amp;nbsp;function that adds numbers from 0 below n, in sequence-y style. First using Common Lisp builtins:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun sum-below &amp;#40;n&amp;#41;
&amp;#40;reduce #'+ &amp;#40;loop for i from 0 below n collect i&amp;#41; :initial-value 0&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now with our virtual sequences:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defun sum-below-2 &amp;#40;n&amp;#41;
&amp;#40;vreduce #'+ 0 &amp;#40;range n&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s try to&amp;nbsp;time the two versions. On my Mac running Clozure CL 1.7, this gives:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;CL-USER&amp;gt; &amp;#40;time &amp;#40;sum-below 10000000&amp;#41;&amp;#41;
&amp;#40;SUM-BELOW 10000000&amp;#41; took 8,545,512 microseconds &amp;#40;8.545512 seconds&amp;#41; to run
with 2 available CPU cores.
During that period, 2,367,207 microseconds &amp;#40;2.367207 seconds&amp;#41; were spent in user mode
270,481 microseconds &amp;#40;0.270481 seconds&amp;#41; were spent in system mode
5,906,274 microseconds &amp;#40;5.906274 seconds&amp;#41; was spent in GC.
160,000,016 bytes of memory allocated.
39,479 minor page faults, 1,359 major page faults, 0 swaps.
49999995000000
CL-USER&amp;gt; &amp;#40;time &amp;#40;sum-below-2 10000000&amp;#41;&amp;#41;
&amp;#40;SUM-BELOW-2 10000000&amp;#41; took 123,081 microseconds &amp;#40;0.123081 seconds&amp;#41; to run
with 2 available CPU cores.
During that period, 127,632 microseconds &amp;#40;0.127632 seconds&amp;#41; were spent in user mode
666 microseconds &amp;#40;0.000666 seconds&amp;#41; were spent in system mode
4 minor page faults, 0 major page faults, 0 swaps.
49999995000000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As expected, &lt;code&gt;SUM-BELOW-2&lt;/code&gt; is much faster, causes less page faults and presumably conses less. (Critics will be quick to&amp;nbsp;point out that we&amp;nbsp;could idiomatically write it using &lt;code&gt;LOOP&lt;/code&gt;’s &lt;code&gt;SUM/SUMMING&lt;/code&gt; clause, which would probably be yet faster, and I&amp;nbsp;agree; yet if we&amp;nbsp;were reducing by something other than &lt;code&gt;+&lt;/code&gt; — something that &lt;code&gt;LOOP&lt;/code&gt; has not built in as a&amp;nbsp;clause — this would not be an option.)&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;We&amp;nbsp;have seen how snippets of code can be viewed as sequences and how to&amp;nbsp;combine them to&amp;nbsp;produce other virtual sequences. As we&amp;nbsp;are nearing the end of this article, it is perhaps fitting to&amp;nbsp;ask: what are the limitations and drawbacks of this approach?&lt;/p&gt;&lt;p&gt;Clearly, this kind of sequences is less powerful than “ordinary” sequences such as Clojure’s. The fact that we’ve built them on macros means that once we&amp;nbsp;escape the world of code transformation by invoking some macro of the third class, we&amp;nbsp;can’t manipulate them anymore. In Clojure world, &lt;code&gt;first&lt;/code&gt; and &lt;code&gt;rest&lt;/code&gt; are very similar; in virtual sequences, they are altogether different: they belong to&amp;nbsp;different worlds. The same goes for &lt;code&gt;map&lt;/code&gt; (had we&amp;nbsp;defined one) and &lt;code&gt;reduce&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;But imagine that instead of having just one programming language, we&amp;nbsp;have a&amp;nbsp;high-level language A&amp;nbsp;in which we&amp;nbsp;are writing macros that expand to&amp;nbsp;code in a&amp;nbsp;low-level language B. It is important to&amp;nbsp;point out that the generated code is very low-level. It could almost be assembly: in fact, most of the macros we’ve written don’t even require language B to&amp;nbsp;have composite data-types beyond the type of elements of collections (which could be simple integers)!&lt;/p&gt;&lt;p&gt;Is there a&amp;nbsp;practical side to&amp;nbsp;this? I&amp;nbsp;don’t know: to&amp;nbsp;me it just seems to&amp;nbsp;be something with hack value. Time will tell if I&amp;nbsp;can put it to&amp;nbsp;good use.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-07-11:post:color-your-own-europe</a:id>
<a:title>Color your own Europe with Clojure!</a:title>
<a:link href="http://blog.danieljanus.pl/2011/07/11/color-your-own-europe/"/>
<a:updated>2011-07-11T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;This is a&amp;nbsp;slightly edited translation of &lt;a href='http://plblog.danieljanus.pl/zippery-w-clojure'&gt;an article&lt;/a&gt; I&amp;nbsp;first published on my Polish blog on January 19, 2011. It is meant to&amp;nbsp;target newcomers to&amp;nbsp;Clojure and show how to&amp;nbsp;use Clojure to&amp;nbsp;solve a&amp;nbsp;simple real-life problems.&lt;/p&gt;&lt;h2&gt;The problem&lt;/h2&gt;&lt;p&gt;Some time ago I&amp;nbsp;was asked to&amp;nbsp;prepare a&amp;nbsp;couple of differently-colored maps of Europe. I&amp;nbsp;got some datasets which mapped countries of Europe to&amp;nbsp;numerical values: the greater the value, the darker the corresponding color should be. A&amp;nbsp;sample colored map looked like this:&lt;/p&gt;&lt;p&gt;&lt;img src="/img/blog/europa.png"&gt;&lt;/p&gt;&lt;p&gt;I&amp;nbsp;began by downloading an easily editable &lt;a href='http://commons.wikimedia.org/wiki/File:Blank_map_of_Europe.svg'&gt;map&lt;/a&gt; from Wikipedia Commons, calculated the required color intensities for the first dataset, launched &lt;a href='http://www.inkscape.org'&gt;Inkscape&lt;/a&gt; and started coloring. After half an hour of tedious clicking, I&amp;nbsp;realized that I&amp;nbsp;would be better off writing a&amp;nbsp;simple program in Clojure that would generate the map for me. It turned out to&amp;nbsp;be an easy task: the remainder of this article will be an attempt to&amp;nbsp;reconstruct my steps.&lt;/p&gt;&lt;h2&gt;SVG&lt;/h2&gt;&lt;p&gt;The format of the source image is SVG. I&amp;nbsp;knew it was an XML-based vector graphics format, I’d often encountered images in this format on Wikipedia — but editing it by hand was new to&amp;nbsp;me. Luckily, it turned out that the image has a&amp;nbsp;simple structure. Each country’s envelope curve is described with a&amp;nbsp;&lt;code&gt;path&lt;/code&gt; element that looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="xml"&gt;&amp;lt;path
id=&amp;quot;pl&amp;quot;
class=&amp;quot;eu europe&amp;quot;
d=&amp;quot;a long list of curve node coordinates&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;An important thing to&amp;nbsp;note here is the &lt;code&gt;id&lt;/code&gt; attribute — this is the two-letter ISO-3166-1-ALPHA2 country code. In fact, there is an informative comment right at the beginning of the image that explains the naming conventions used. Having such a&amp;nbsp;splendid input was of great help.&lt;/p&gt;&lt;p&gt;Just like HTML, SVG &lt;a href='http://www.w3.org/TR/SVG/styling.html'&gt;uses CSS stylesheets&lt;/a&gt; to&amp;nbsp;define the look of an element. All that is needed to&amp;nbsp;color Poland red is to&amp;nbsp;style the element with a&amp;nbsp;&lt;code&gt;fill&lt;/code&gt; attribute:&lt;/p&gt;&lt;pre&gt;&lt;code class="xml"&gt;&amp;lt;path
id=&amp;quot;pl&amp;quot;
style=&amp;quot;fill: #ff0000;&amp;quot;
class=&amp;quot;eu europe&amp;quot;
d=&amp;quot;a long list of curve node coordinates&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now that we&amp;nbsp;know all this, let’s start coding!&lt;/p&gt;&lt;h2&gt;XML in Clojure&lt;/h2&gt;&lt;p&gt;The basic way to&amp;nbsp;handle XML in Clojure is to&amp;nbsp;use the &lt;code&gt;clojure.xml&lt;/code&gt; namespace, which contains functions that parse XML (on a&amp;nbsp;DOM basis, i.e., into an in-memory tree structure) and serialize such structures back into XML. Let us launch a&amp;nbsp;REPL and start by reading our map and parsing it:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;use 'clojure.xml&amp;#41;
nil
&amp;gt; &amp;#40;def m &amp;#40;parse &amp;quot;/home/nathell/eur/Blank&amp;#95;map&amp;#95;of&amp;#95;Europe.svg&amp;quot;&amp;#41;&amp;#41;
&amp;#91;...a long while...&amp;#93;
Unexpected end of file from server
&amp;#91;Thrown class java.net.SocketException&amp;#93;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hold on in there! What’s that &lt;code&gt;SocketException&lt;/code&gt; doing here? Firefox displays this map properly, so does Chrome, WTF?! Shouldn’t everything work fine in such a&amp;nbsp;great language as Clojure?&lt;/p&gt;&lt;p&gt;Well, the language is as good as its libraries — and when it comes to&amp;nbsp;Clojure, one can stretch that thought further: Clojure libraries are as good as the Java libraries they use under the hood. In this case, we’ve encountered a&amp;nbsp;feature of the standard Java XML parser (from &lt;code&gt;javax.xml&lt;/code&gt; package). It is restrictive and tries to&amp;nbsp;reject invalid documents (even if they are well-formed). If the file being parsed contains a&amp;nbsp;&lt;code&gt;DOCTYPE&lt;/code&gt; declaration, the Java parser, and hence &lt;code&gt;clojure.xml/parse&lt;/code&gt;, tries to&amp;nbsp;download the DTD schema from the given address and validate the document against that schema. This is unfortunate in many aspects, especially from the point of view of the &lt;a href='http://www.w3.org'&gt;World Wide Web Consortium&lt;/a&gt;, since their servers hold the Web standards. One can easily imagine the volume of network traffic this generates: W3C has a&amp;nbsp;&lt;a href='http://www.w3.org/blog/systeam?cat=68'&gt;blog post&lt;/a&gt; about it. Many Java programmers have encountered this problem at some time. There are a&amp;nbsp;few solutions; we&amp;nbsp;will go the simplest way and just manually remove the offending &lt;code&gt;DOCTYPE&lt;/code&gt; declaration.&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;def m &amp;#40;parse &amp;quot;/home/nathell/eur/bm.svg&amp;quot;&amp;#41;&amp;#41;
#'user/m
&amp;gt; m
&amp;#91;...many screenfuls of numbers...&amp;#93;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This time we&amp;nbsp;managed to&amp;nbsp;parse the image. Viewing the structure is not easy because of its sheer size (as expected: the file weighs in at over 0,5 MB!), but from the very first characters of the REPL’s output we&amp;nbsp;can make out that’s it a&amp;nbsp;Clojure map (no pun intended). Let’s examine its keys:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;keys m&amp;#41;
&amp;#40;:tag :attrs :content&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the map contains three entries with descriptive names. &lt;code&gt;:tag&lt;/code&gt; contains the name of the XML element, &lt;code&gt;:attrs&lt;/code&gt; is a&amp;nbsp;map of attributes for this element, and &lt;code&gt;:content&lt;/code&gt; is a&amp;nbsp;vector of its subelements, each in turn being represented by similarly structured map (or a&amp;nbsp;string if it’s a&amp;nbsp;text node):&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;:tag m&amp;#41;
:svg
&amp;gt; &amp;#40;:attrs m&amp;#41;
{:xmlns &amp;quot;http://www.w3.org/2000/svg&amp;quot;, :width &amp;quot;680&amp;quot;, :height &amp;quot;520&amp;quot;, :viewBox &amp;quot;1754 161 9938 7945&amp;quot;, :version &amp;quot;1.0&amp;quot;, :id &amp;quot;svg2&amp;quot;}
&amp;gt; &amp;#40;count &amp;#40;:content m&amp;#41;&amp;#41;
68
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just for the sake of practice, let’s try to&amp;nbsp;write the serialized representation of the parsed back as XML. The function &lt;code&gt;emit&lt;/code&gt; should be able to&amp;nbsp;do&amp;nbsp;it, but it prints XML to&amp;nbsp;standard output. We&amp;nbsp;can use the &lt;code&gt;with-out-writer&lt;/code&gt; macro from the namespace &lt;code&gt;clojure.contrib.io&lt;/code&gt; to&amp;nbsp;dump the XML to&amp;nbsp;a&amp;nbsp;file:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;use 'clojure.contrib.io&amp;#41;
nil
&amp;gt; &amp;#40;with-out-writer &amp;quot;/tmp/a.svg&amp;quot; &amp;#40;emit m&amp;#41;&amp;#41;
nil
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;nbsp;try to&amp;nbsp;view &lt;code&gt;a.svg&lt;/code&gt; in Firefox and…&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;Error parsing XML: not well-formed
Area: file:///tmp/a.xml
Row 15, column 44: Updated to reflect dissolution of Serbia &amp;amp; Montenegro: http://commons.wikimedia.org/wiki/User:Zirland
-------------------------------------------&amp;#94;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It turns out that using &lt;code&gt;clojure.xml/emit&lt;/code&gt; is not recommended, because it does not handle XML entities in comments correctly; we&amp;nbsp;should use &lt;code&gt;clojure.contrib.lazy-xml&lt;/code&gt; instead. For the sake of example, though, let’s stay with &lt;code&gt;emit&lt;/code&gt; and manually remove the offending line once again (we&amp;nbsp;can safely do&amp;nbsp;it, since that’s just a&amp;nbsp;comment).&lt;/p&gt;&lt;h2&gt;Coloring Poland&lt;/h2&gt;&lt;p&gt;We&amp;nbsp;saw earlier that our main XML node contains 68 subnodes. Let’s see what they are — tag names will suffice:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;map :tag &amp;#40;:content m&amp;#41;&amp;#41;
&amp;#40;:title :desc :defs :rect :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :path :g :path :path :g :path :path :path&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far, so good. Seems that all country descriptions are contained directly in the main node. Let us try to&amp;nbsp;find Poland:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;gt; &amp;#40;count &amp;#40;filter #&amp;#40;and &amp;#40;= &amp;#40;:tag %&amp;#41; :path&amp;#41;
&amp;#40;= &amp;#40;&amp;#40;:attrs %&amp;#41; :id&amp;#41; &amp;quot;pl&amp;quot;&amp;#41;&amp;#41;
&amp;#40;:content m&amp;#41;&amp;#41;&amp;#41;
1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(This snippet of code filters the list of subnodes of &lt;code&gt;m&lt;/code&gt; to&amp;nbsp;pick only those elements whose tag name is &lt;code&gt;path&lt;/code&gt; and value of attribute &lt;code&gt;id&lt;/code&gt; is &lt;code&gt;pl&lt;/code&gt;, and returns the length of such list.) Let’s try to&amp;nbsp;add a&amp;nbsp;&lt;code&gt;style&lt;/code&gt; attribute to&amp;nbsp;that element, according to&amp;nbsp;what we&amp;nbsp;said earlier. Because Clojure data structures are immutable, we&amp;nbsp;have to&amp;nbsp;define a&amp;nbsp;new top-level element which will be the same as &lt;code&gt;m&lt;/code&gt;, except that we&amp;nbsp;will set the style of the appropriate subnode:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;def m2 &amp;#40;assoc m
:content
&amp;#40;map #&amp;#40;if &amp;#40;and &amp;#40;= &amp;#40;:tag %&amp;#41; :path&amp;#41;
&amp;#40;= &amp;#40;&amp;#40;:attrs %&amp;#41; :id&amp;#41; &amp;quot;pl&amp;quot;&amp;#41;&amp;#41;
&amp;#40;assoc % :attrs &amp;#40;assoc &amp;#40;:attrs %&amp;#41; :style &amp;quot;fill: #ff0000;&amp;quot;&amp;#41;&amp;#41;
%&amp;#41;
&amp;#40;:content m&amp;#41;&amp;#41;&amp;#41;&amp;#41;
#'user/m2
&amp;gt; &amp;#40;with-out-writer &amp;quot;/tmp/a.svg&amp;quot; &amp;#40;emit m2&amp;#41;&amp;#41;
nil
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;nbsp;open the created file and see a&amp;nbsp;map with Poland colored red. Yay!&lt;/p&gt;&lt;h2&gt;Generalization&lt;/h2&gt;&lt;p&gt;We&amp;nbsp;will generalize our code a&amp;nbsp;bit. Let us write a&amp;nbsp;function that colors a&amp;nbsp;single state, taking a&amp;nbsp;&lt;code&gt;path&lt;/code&gt; element (subnode of &lt;code&gt;svg&lt;/code&gt;) as an argument:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn color-state
&amp;#91;{:keys &amp;#91;tag attrs&amp;#93; :as element} colorize-fn&amp;#93;
&amp;#40;let &amp;#91;state &amp;#40;:id attrs&amp;#41;&amp;#93;
&amp;#40;if-let &amp;#91;color &amp;#40;colorize-fn state&amp;#41;&amp;#93;
&amp;#40;assoc element :attrs &amp;#40;assoc attrs :style &amp;#40;str &amp;quot;fill:&amp;quot; color&amp;#41;&amp;#41;&amp;#41;
element&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is similar to&amp;nbsp;the anonymous one we&amp;nbsp;used above in the &lt;code&gt;map&lt;/code&gt; call, but differs in some respects. It takes two arguments. As mentioned, the first one is the XML element (destructured into &lt;code&gt;tag&lt;/code&gt; and &lt;code&gt;attrs&lt;/code&gt;: you can read more about destructuring in &lt;a href='http://clojure.org/special_forms'&gt;the appropriate part of Clojure docs&lt;/a&gt;), and the second argument is… a&amp;nbsp;function that should take a&amp;nbsp;two-letter country code and return a&amp;nbsp;HTML color description (or &lt;code&gt;nil&lt;/code&gt;, if that country’s color is not specified — &lt;code&gt;color-state&lt;/code&gt; will cope with this and return the element unchanged).&lt;/p&gt;&lt;p&gt;Now that we&amp;nbsp;have &lt;code&gt;color-state&lt;/code&gt;, we&amp;nbsp;can easily write a&amp;nbsp;higher-level function that processes and writes XML in one step:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn save-color-map
&amp;#91;svg colorize-fn outfile&amp;#93;
&amp;#40;let &amp;#91;colored-map &amp;#40;assoc svg :content &amp;#40;map #&amp;#40;color-state % colorize-fn&amp;#41; &amp;#40;:content svg&amp;#41;&amp;#41;&amp;#41;&amp;#93;
&amp;#40;with-out-writer out
&amp;#40;emit colored-map&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let’s test it:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;save-color-map m {&amp;quot;pl&amp;quot; &amp;quot;#00ff00&amp;quot;} &amp;quot;/tmp/a.svg&amp;quot;&amp;#41;
nil
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This time Poland is green (we&amp;nbsp;used a&amp;nbsp;country→color map as an argument to&amp;nbsp;&lt;code&gt;color-state&lt;/code&gt;, since Clojure maps are callable like functions). Let’s try to&amp;nbsp;add blue Germany:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;save-color-map m {&amp;quot;pl&amp;quot; &amp;quot;#00ff00&amp;quot;, &amp;quot;de&amp;quot; &amp;quot;#0000ff&amp;quot;} &amp;quot;/tmp/a.svg&amp;quot;&amp;#41;
nil
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It works!&lt;/p&gt;&lt;h2&gt;Problem with the UK&lt;/h2&gt;&lt;p&gt;Inspired by our success, we&amp;nbsp;try to&amp;nbsp;color different countries. It mostly works, but the United Kingdom remains gray, regardless of whether we&amp;nbsp;specify its code as “uk” or “gb”. We&amp;nbsp;resort to&amp;nbsp;the source of our image, and the beginning comment once again proves helpful:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Certain countries are further subdivided the United Kingdom has gb-gbn for Great Britain and gb-nir for Northern Ireland. Russia is divided into ru-kgd for the Kaliningrad Oblast and ru-main for the Main body of Russia. There is the additional grouping #xb for the “British Islands” (the UK with its Crown Dependencies – Jersey, Guernsey and the Isle of Man) &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Perhaps we&amp;nbsp;have to&amp;nbsp;specify “gb-gbn” and “gb-nir”, instead of just “gb”? We&amp;nbsp;try that, but still no luck. After a&amp;nbsp;while of thought: oh yes! Our initial assumption that &lt;i&gt;all&lt;/i&gt; the country definitions are &lt;code&gt;path&lt;/code&gt; subnodes of the toplevel &lt;code&gt;svg&lt;/code&gt; node is false. We&amp;nbsp;have to&amp;nbsp;fix that.&lt;/p&gt;&lt;p&gt;So far we&amp;nbsp;have been doing a&amp;nbsp;“flat” transform of the SVG tree: we&amp;nbsp;only changed the subnodes of the toplevel node, but no deeper. We&amp;nbsp;should change all the &lt;code&gt;path&lt;/code&gt; elements (and &lt;code&gt;g&lt;/code&gt;, if we&amp;nbsp;want to&amp;nbsp;color groups of paths like the UK), regardless of how deep they occur in the tree.&lt;/p&gt;&lt;p&gt;We&amp;nbsp;can use a&amp;nbsp;&lt;a href='http://clojure.org/other_libraries'&gt;zipper&lt;/a&gt; to&amp;nbsp;do&amp;nbsp;a&amp;nbsp;depth-first walk of the SVG tree. Let us define a&amp;nbsp;function that takes a&amp;nbsp;zipper, a&amp;nbsp;predicate that tells whether to&amp;nbsp;edit the node in question, and the transformation function to&amp;nbsp;apply to&amp;nbsp;the node if the predicate returns &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn map-zipper &amp;#91;f pred z&amp;#93;
&amp;#40;if &amp;#40;zip/end? z&amp;#41;
&amp;#40;zip/root z&amp;#41;
&amp;#40;recur f pred &amp;#40;-&amp;gt; z &amp;#40;zip/edit #&amp;#40;if &amp;#40;pred %&amp;#41; &amp;#40;f %&amp;#41; %&amp;#41;&amp;#41; zip/next&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we&amp;nbsp;rewrite &lt;code&gt;save-color-map&lt;/code&gt; as:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn save-color-map
&amp;#91;svg colorize-fn outfile&amp;#93;
&amp;#40;let &amp;#91;colored-map &amp;#40;map-zipper #&amp;#40;color-state % colorize-fn&amp;#41; &amp;#40;fn &amp;#91;x&amp;#93; &amp;#40;#{:g :path} &amp;#40;:tag x&amp;#41;&amp;#41;&amp;#41; &amp;#40;zip/xml-zip svg&amp;#41;&amp;#41;&amp;#93;
&amp;#40;with-out-writer out
&amp;#40;emit colored-map&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This time the UK can be colored.&lt;/p&gt;&lt;h2&gt;Colorizers&lt;/h2&gt;&lt;p&gt;We&amp;nbsp;have automated the process of styling countries to&amp;nbsp;make them appear in color, but translating particular numbers to&amp;nbsp;RGB is tedious. In the last part of this article we&amp;nbsp;will see how to&amp;nbsp;ease this: we&amp;nbsp;are going to&amp;nbsp;write a&amp;nbsp;&lt;i&gt;colorizer&lt;/i&gt;, i.e., a&amp;nbsp;function suitable for passing to&amp;nbsp;&lt;code&gt;color-state&lt;/code&gt; and &lt;code&gt;save-color-map&lt;/code&gt; (so far we’ve been using maps for this).&lt;/p&gt;&lt;p&gt;Let’s start by writing a&amp;nbsp;function that translates a&amp;nbsp;triplet of numbers into a&amp;nbsp;HTML RGB notation, because it will be easier for us to&amp;nbsp;work with integers than with strings:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn htmlize-color
&amp;#91;&amp;#91;r g b&amp;#93;&amp;#93;
&amp;#40;format &amp;quot;#%02x%02x%02x&amp;quot; r g b&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we&amp;nbsp;insert a&amp;nbsp;call to&amp;nbsp;&lt;code&gt;htmlize-color&lt;/code&gt; into the appropriate pace in &lt;code&gt;color-state&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn color-state
&amp;#91;{:keys &amp;#91;tag attrs&amp;#93; :as element} colorize-fn&amp;#93;
&amp;#40;let &amp;#91;state &amp;#40;:id attrs&amp;#41;&amp;#93;
&amp;#40;if-let &amp;#91;color &amp;#40;colorize-fn state&amp;#41;&amp;#93;
&amp;#40;assoc element :attrs &amp;#40;assoc attrs :style &amp;#40;str &amp;quot;fill:&amp;quot; &amp;#40;htmlize-color color&amp;#41;&amp;#41;&amp;#41;&amp;#41;
element&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now imagine we&amp;nbsp;have a&amp;nbsp;table with numeric values for states, like this:&lt;/p&gt;&lt;p&gt;&lt;table class="entry"&gt; &lt;tr class="header"&gt;&lt;th&gt;State&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Poland&lt;/td&gt;&lt;td class="center"&gt;20&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Germany&lt;/td&gt;&lt;td class="center"&gt;15&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Netherlands&lt;/td&gt;&lt;td class="center"&gt;30&lt;/td&gt;&lt;/tr&gt; &lt;/table&gt;&lt;/p&gt;&lt;p&gt;We&amp;nbsp;want to&amp;nbsp;have a&amp;nbsp;function that assigns colors to&amp;nbsp;states, such that the intensity of a&amp;nbsp;color should be proportional to&amp;nbsp;the value assigned to&amp;nbsp;a&amp;nbsp;given state. To&amp;nbsp;be more general, assume we&amp;nbsp;have two colors, c1 and c2, and for a&amp;nbsp;given state, for each of the R, G, B components we&amp;nbsp;assign a&amp;nbsp;value proportional to&amp;nbsp;the difference between the state’s value and the smallest value in the dataset, normalized to&amp;nbsp;lie between c1 and c2.&lt;/p&gt;&lt;p&gt;This sounds complex, but I&amp;nbsp;hope an example will clear things up. This is the Clojure implementation of the described algorithm:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defn make-colorizer
&amp;#91;dataset ranges&amp;#93;
&amp;#40;let &amp;#91;minv &amp;#40;apply min &amp;#40;vals dataset&amp;#41;&amp;#41;
maxv &amp;#40;apply max &amp;#40;vals dataset&amp;#41;&amp;#41;
progress &amp;#40;map &amp;#40;fn &amp;#91;&amp;#91;min-col max-col&amp;#93;&amp;#93; &amp;#40;/ &amp;#40;- max-col min-col&amp;#41; &amp;#40;- maxv minv&amp;#41;&amp;#41;&amp;#41; ranges&amp;#41;&amp;#93;
&amp;#40;into {}
&amp;#40;map &amp;#40;fn &amp;#91;&amp;#91;k v&amp;#93;&amp;#93; &amp;#91;&amp;#40;.toLowerCase k&amp;#41; &amp;#40;map &amp;#40;fn &amp;#91;progress &amp;#91;min-color &amp;#95;&amp;#93;&amp;#93; &amp;#40;int &amp;#40;+ min-color &amp;#40;&amp;#42; &amp;#40;- v minv&amp;#41; progress&amp;#41;&amp;#41;&amp;#41;&amp;#41; progress ranges&amp;#41;&amp;#93;&amp;#41;
dataset&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let us see how it works on our sample data:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;gt; &amp;#40;make-colorizer {&amp;quot;pl&amp;quot; 20, &amp;quot;de&amp;quot; 15, &amp;quot;nl&amp;quot; 30} &amp;#91;&amp;#91;0 255&amp;#93; &amp;#91;0 0&amp;#93; &amp;#91;0 0&amp;#93;&amp;#93;&amp;#41;
{&amp;quot;pl&amp;quot; &amp;#40;85 0 0&amp;#41;, &amp;quot;de&amp;quot; &amp;#40;0 0 0&amp;#41;, &amp;quot;nl&amp;quot; &amp;#40;255 0 0&amp;#41;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The second argument means that the red component is to&amp;nbsp;range between 0 and 255, and the green and blue components are to&amp;nbsp;be fixed at 0.&lt;/p&gt;&lt;p&gt;Like we&amp;nbsp;wanted, Germany ends up darkest (because it has the least value), the Netherlands is lightest (because it has the greatest value), and Poland’s intensity is one third that of the Netherlands (because 20 is in one third of the way between 15 and 30).&lt;/p&gt;&lt;h2&gt;Wrapping up&lt;/h2&gt;&lt;p&gt;The application we&amp;nbsp;created can be further developed in many ways. One can, for instance, add a&amp;nbsp;Web interface for it, or write many different colorizers (e.g., discrete colorizer: fixed colours for ranges of input values, or a&amp;nbsp;temperature colorizer transitioning smoothly from blue through white to&amp;nbsp;red — to&amp;nbsp;do&amp;nbsp;this we&amp;nbsp;would have to&amp;nbsp;pass through the HSV color space).&lt;/p&gt;&lt;p&gt;What is your idea to&amp;nbsp;improve on it? For those of you who are tired of pasting snippets of code into the REPL, I’m putting the complete source code with a&amp;nbsp;Leiningen project on &lt;a href='https://github.com/nathell/color-europe'&gt;GitHub&lt;/a&gt;. Forks are welcome.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-07-08:post:meet-my-little-friend-createtree</a:id>
<a:title>Meet my little friend createTree</a:title>
<a:link href="http://blog.danieljanus.pl/2011/07/08/meet-my-little-friend-createtree/"/>
<a:updated>2011-07-08T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve recently been developing an iPhone application in my spare time. I’m not going to&amp;nbsp;tell you what it is just yet (I&amp;nbsp;will post a&amp;nbsp;separate entry once I&amp;nbsp;manage to&amp;nbsp;get it into the App Store); for now, let me just say that I’m writing it in JavaScript and HTML5, using &lt;a href=''&gt;PhoneGap&lt;/a&gt; and &lt;a href=''&gt;jQTouch&lt;/a&gt; to&amp;nbsp;give it a&amp;nbsp;native touch.&lt;/p&gt;&lt;p&gt;After having written some of code, I&amp;nbsp;began testing it on a&amp;nbsp;real device and encountered a&amp;nbsp;nasty issue. It turned out that some of the screens of my app, containing a&amp;nbsp;dynamically-generated content, sometimes would not show up. I&amp;nbsp;tried to&amp;nbsp;chase the problem down, but it seemed totally random. Finally, I&amp;nbsp;googled up &lt;a href=''&gt;this blog post&lt;/a&gt; that gave me a&amp;nbsp;clue.&lt;/p&gt;&lt;p&gt;My code was using jQuery’s &lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt; method (and hence &lt;code&gt;innerHTML&lt;/code&gt; under the hood) to&amp;nbsp;display the dynamic content. It turns out that, on Mobile Safari, using &lt;code&gt;innerHTML&lt;/code&gt; is highly unreliable (at least on iOS 4.3, but this seems to&amp;nbsp;be a&amp;nbsp;long-standing bug). Sometimes, the change just does not happen. I&amp;nbsp;changed one of my screens, to&amp;nbsp;build and insert DOM objects explicitly, and sure enough, it started to&amp;nbsp;work predictably well.&lt;/p&gt;&lt;p&gt;So I&amp;nbsp;had to&amp;nbsp;remove all usages of &lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt; from my app. The downside to&amp;nbsp;it was that explicit DOM-building code is much more verbose than the version that constructs HTML and then sets it up. It’s tedious to&amp;nbsp;write and contains much boilerplate.&lt;/p&gt;&lt;p&gt;To&amp;nbsp;not be forced to&amp;nbsp;change code, the above-quoted article advocates using a&amp;nbsp;pure-JavaScript HTML parser outputting DOM to&amp;nbsp;replace jQuery’s &lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt; method. I&amp;nbsp;considered this for a&amp;nbsp;while, but finally decided against it — I&amp;nbsp;didn’t want to&amp;nbsp;include another big, complex dependency that potentially could misbehave at times (writing HTML parsers is &lt;i&gt;hard&lt;/i&gt;).&lt;/p&gt;&lt;p&gt;Instead, I&amp;nbsp;came up with this:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;function createTree&amp;#40;tree&amp;#41; {
if &amp;#40;typeof tree === 'string' || typeof tree === 'number'&amp;#41;
return document.createTextNode&amp;#40;tree&amp;#41;;
var tag = tree&amp;#91;0&amp;#93;, attrs = tree&amp;#91;1&amp;#93;, res = document.createElement&amp;#40;tag&amp;#41;;
for &amp;#40;var attr in attrs&amp;#41; {
val = attrs&amp;#91;attr&amp;#93;;
if &amp;#40;attr === 'class'&amp;#41;
res.className = val;
else
$&amp;#40;res&amp;#41;.attr&amp;#40;attr, val&amp;#41;;
}
for &amp;#40;var i = 2; i &amp;lt; tree.length; i++&amp;#41;
res.appendChild&amp;#40;createTree&amp;#40;tree&amp;#91;i&amp;#93;&amp;#41;&amp;#41;;
return res;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is very similar in spirit to&amp;nbsp;&lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt;, except that instead of passing HTML, you give it a&amp;nbsp;data structure representing the DOM tree to&amp;nbsp;construct. It can either be a&amp;nbsp;string (which yields a&amp;nbsp;text node), or a&amp;nbsp;list consisting of the HTML tag name, an object mapping attributes to&amp;nbsp;their values, and zero or more subtrees of the same form. Compare:&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;var html = '&amp;lt;p&amp;gt;This is an &amp;lt;span class=&amp;quot;red&amp;quot;&amp;gt;example.&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;';
$&amp;#40;'#myDiv'&amp;#41;.html&amp;#40;html&amp;#41;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using &lt;code&gt;createTree&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;var tree = &amp;#91;'p', {},
'This is an ',
&amp;#91;'span', {'class': 'red'}, 'example.'&amp;#93;&amp;#93;;
$&amp;#40;'#myDiv'&amp;#41;.empty&amp;#40;&amp;#41;.append&amp;#40;createTree&amp;#40;tree&amp;#41;&amp;#41;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A&amp;nbsp;side benefit is that it is just as easy to&amp;nbsp;build up a&amp;nbsp;tree dynamically as it is to&amp;nbsp;create HTML, and the code often gets clearer. Note how the &lt;code&gt;createTree&lt;/code&gt; version above does not mix single and double quotes which is easy to&amp;nbsp;mess up in the &lt;code&gt;.html&amp;#40;&amp;#41;&lt;/code&gt; version.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-05-15:post:a-quirk-with-javascript-closures</a:id>
<a:title>A quirk with JavaScript closures</a:title>
<a:link href="http://blog.danieljanus.pl/2011/05/15/a-quirk-with-javascript-closures/"/>
<a:updated>2011-05-15T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I&amp;nbsp;keep running into this obstacle every now and then. Consider this example:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&amp;gt; q = &amp;#91;&amp;#93;
&amp;#91;&amp;#93;
&amp;gt; for &amp;#40;var i = 0; i &amp;lt; 3; i++&amp;#41;
q.push&amp;#40;function&amp;#40;&amp;#41; { console.log&amp;#40;i&amp;#41;; }&amp;#41;;
&amp;gt; q&amp;#91;0&amp;#93;&amp;#40;&amp;#41;
3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;nbsp;wanted an array of three closures, each printing a&amp;nbsp;different number to&amp;nbsp;the console when called. Instead, each prints 3 (or, rather, whatever the value of the variable &lt;code&gt;i&lt;/code&gt; happens to&amp;nbsp;be).&lt;/p&gt;&lt;p&gt;I&amp;nbsp;am not exactly sure about the reason, but presumably this happens because the &lt;code&gt;i&lt;/code&gt; in each lambda refers to&amp;nbsp;the &lt;i&gt;variable&lt;/i&gt; &lt;code&gt;i&lt;/code&gt; itself, not to&amp;nbsp;its binding from the creation time of the function.&lt;/p&gt;&lt;p&gt;One solution is to&amp;nbsp;enforce the bindings explicitly on each iteration, like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;for &amp;#40;var i = 0; i &amp;lt; 3; i++&amp;#41;
&amp;#40;function&amp;#40;v&amp;#41; {
q.push&amp;#40;function&amp;#40;&amp;#41; { console.log&amp;#40;v&amp;#41;; }&amp;#41;;
}&amp;#41;&amp;#40;i&amp;#41;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or use &lt;a href='http://documentcloud.github.com/underscore/'&gt;Underscore.js&lt;/a&gt;, which is what I&amp;nbsp;actually do:&lt;/p&gt;&lt;pre&gt;&lt;code class="javascript"&gt;&amp;#95;&amp;#40;&amp;#91;1,2,3&amp;#93;&amp;#41;.each&amp;#40;function&amp;#40;i&amp;#41; {
q.push&amp;#40;function&amp;#40;&amp;#41; { console.log&amp;#40;i&amp;#41;; }&amp;#41;;
}&amp;#41;;
&lt;/code&gt;&lt;/pre&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-03-28:post:the-dijkstran-wheel-of-fortune</a:id>
<a:title>The Dijkstran wheel of fortune: SPSS, Excel, VBA</a:title>
<a:link href="http://blog.danieljanus.pl/2011/03/28/the-dijkstran-wheel-of-fortune/"/>
<a:updated>2011-03-28T00:00:00Z</a:updated>
<a:content type="html">&lt;blockquote&gt;&lt;p&gt; It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. &lt;/p&gt;&lt;p&gt; &lt;p style="text-align: right;"&gt;— Edsger W. Dijkstra, EWD 498&lt;/p&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I&amp;nbsp;like to&amp;nbsp;think of myself somewhat egotistically as a&amp;nbsp;counterexample to&amp;nbsp;the above Dijkstra’s statement. Granted, some of my code is definitely of poor quality, and I&amp;nbsp;dare not call myself a&amp;nbsp;good programmer. But, having started with BASIC on a&amp;nbsp;Commodore 64, then proceeding to&amp;nbsp;learn Pascal (of the Turbo/Borland flavour), then C, x86 assembly, OCaml, Smalltalk, Java, C++, Haskell, Common Lisp, Clojure, and a&amp;nbsp;couple of other languages, with a&amp;nbsp;few enlightenments achieved along the way, I&amp;nbsp;do&amp;nbsp;think I&amp;nbsp;managed to&amp;nbsp;regenerate from the mental wounds that BASIC had inflicted upon me. And now I&amp;nbsp;feel a&amp;nbsp;strange sensation, now that the Dijkstran wheel of fortune has made a&amp;nbsp;full spin: I’ve spend the last few days writing BASIC code. I’ve written several Excel macros in Visual Basic for Applications.&lt;/p&gt;&lt;p&gt;Why the strange selection of a&amp;nbsp;language? Well, this was simply the best tool for the job. What I&amp;nbsp;needed to&amp;nbsp;do&amp;nbsp;was postprocess the output of some statistical analyses performed in &lt;a href=''&gt;SPSS&lt;/a&gt; running under Windows, altering the way the results were presented. SPSS can export data to&amp;nbsp;HTML, Word, and Excel; of these three, the latter is most convenient, because it preserves the structure of the output tables most thoroughly. (In principle, HTML does too, and in fact my first stab was with Clojure, but I&amp;nbsp;stopped after realizing just how much ad-hoc, throwaway code that parses the SPSS-generated HTML, munges it several times to&amp;nbsp;and fro, and then outputs back HTML I’d have to&amp;nbsp;write). So I&amp;nbsp;went the Excel way, and in this post I’d like to&amp;nbsp;share my mixed feelings from that encounter.&lt;/p&gt;&lt;p&gt;Visual Basic the language is icky. It is certainly a&amp;nbsp;step forward from the BASIC I&amp;nbsp;remember from decades ago, in that I&amp;nbsp;didn’t have to&amp;nbsp;number my lines, and it is possible to&amp;nbsp;structure the code nicely so that it doesn’t contain any GOTOs, GOSUBs or RETURNs. And it has this object-oriented feel to&amp;nbsp;it. But compared to&amp;nbsp;modern languages, programming in it resembles voluntarily putting on handcuffs, and then jumping around to&amp;nbsp;avoid stumbling over the logs it throws under your legs. Not quite so big and scary logs as C++ does, but still. I&amp;nbsp;mean, why on earth does VB have to&amp;nbsp;distinguish between expressions and statements? Many languages do, but in most of them an expression is at least a&amp;nbsp;valid statement. Not so in VB. Also, VB is still line-oriented: whether or not you require an &lt;code&gt;End If&lt;/code&gt; in the conditional statement depends on whether it fits in one line or not. But my biggest pain was with the assignments. VB makes a&amp;nbsp;distinction between reference assignments and other assignments, requiring a&amp;nbsp;&lt;code&gt;Set&lt;/code&gt; statement in the first case, and disallowing it in the second. So, &lt;code&gt;Set myCell = thatOtherCell&lt;/code&gt; but &lt;code&gt;foo = 42&lt;/code&gt;. Worse, forgetting the &lt;code&gt;Set&lt;/code&gt; in the first case does not result in an error, which makes such bugs very hard to&amp;nbsp;debug. Yurgh.&lt;/p&gt;&lt;p&gt;Also, the IDE built into Excel for developing VB macros is mediocre. There is an editor, which highlights the syntax and automatically reformats the code, inserting spaces as appropriate, which is nice. It slaps me in face with a&amp;nbsp;modal dialog whenever I&amp;nbsp;make a&amp;nbsp;syntax error and move off the line, which is not so nice. There is a&amp;nbsp;REPL of sorts, taking the form of an “Immediate” window, into which you can type statements (not expressions, remember?) and tap Enter to&amp;nbsp;execute them. You can also &lt;code&gt;Debug.Print&lt;/code&gt; to&amp;nbsp;them, like to&amp;nbsp;a&amp;nbsp;JavaScript console. It is not reachable by Ctrl-Tab from the editor, so I&amp;nbsp;ended up using mouse much more often than normally. I&amp;nbsp;want my Emacs back!&lt;/p&gt;&lt;p&gt;On the other hand, I&amp;nbsp;find the object-oriented API for actually accessing the spreadsheets quite well-designed and pleasant to&amp;nbsp;use. You just grab the object representing your worksheets from the global &lt;code&gt;Worksheets&lt;/code&gt; object (indexable by number or by name), and from there you access your cells. The basic object you work with is the &lt;code&gt;Range&lt;/code&gt; object, representing either a&amp;nbsp;single cell or a&amp;nbsp;bunch of them; you can get or set cell values, change the formatting, call &lt;code&gt;Offset&lt;/code&gt; to&amp;nbsp;navigate around as if with cursor keys. You also can search for specific content in the sheet. Simple enough, easy to&amp;nbsp;use and pick up; and above all, allows to&amp;nbsp;get the job done without getting in the way much.&lt;/p&gt;&lt;p&gt;As for SPSS itself: it sucks. In fact, it sucks so great and in so many different ways that it merits its own blog entry (which will follow someday). For now, I’ll only note down the things pertaining to&amp;nbsp;Excel interop; hopefully it will save somebody’s time.&lt;/p&gt;&lt;p&gt;Problem is, SPSS 19’s Excel export is buggy. In fact, it’s so unreliable that I’ve wasted more hours struggling with it than actually writing my macros. (We’re talking SPSS 19 here; I’ve also tried version 17, with the same results.) It exports small data chunks fine, but the larger your output, the more likely it is that Excel alerts about unreadable content in your file. Excel then offers to&amp;nbsp;repair the data, which mostly succeeds, but inevitably loses the formatting — which for me was a&amp;nbsp;no-no.&lt;/p&gt;&lt;p&gt;So, after long hours of experimentation and attempting different workarounds, I&amp;nbsp;found that it is much, much more reliable to&amp;nbsp;just copy your data and paste it into Excel directly, without exporting to&amp;nbsp;a&amp;nbsp;temporary file. Just do&amp;nbsp;&lt;code&gt;Edit → Copy special&lt;/code&gt; and select Excel BIFF format, to&amp;nbsp;make sure you’re copying the right data. If Excel complains about not being able to&amp;nbsp;understand the copied content (turn on the Clipboard preview to&amp;nbsp;find out), save your output to&amp;nbsp;.spv, restart SPSS, re-run your syntax and try again. With luck, it will eventually work. At least for me it did.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-03-11:post:hello-world-again</a:id>
<a:title>Hello world, again</a:title>
<a:link href="http://blog.danieljanus.pl/2011/03/11/hello-world-again/"/>
<a:updated>2011-03-11T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve been quiet on the front of blogging in English recently. But that doesn’t mean I’ve given up.&lt;/p&gt;&lt;p&gt;After more than a&amp;nbsp;year, I&amp;nbsp;had become tired of maintaining a&amp;nbsp;&lt;a href='http://blosxom.com/'&gt;Blosxom&lt;/a&gt; installation. I&amp;nbsp;greatly admire Blosxom, its minimalism and extensibility, but the default installation is just too minimal for my needs. And the plugins tend to&amp;nbsp;have rough edges. Like the Disqus comments that I’ve enabled at one time on the otherwise static blog pages: the correct number of comments appears in some places but not all; besides, they just don’t feel right.&lt;/p&gt;&lt;p&gt;So I’ve embarked on an experiment with a&amp;nbsp;blogging platform, namely Posterous. I’ve started a&amp;nbsp;&lt;a href='http://plblog.danieljanus.pl/'&gt;blog in Polish&lt;/a&gt; there to&amp;nbsp;comment on local affairs in my mother tongue and to&amp;nbsp;popularize Clojure among Polish programmers. And after a&amp;nbsp;few months, I&amp;nbsp;consider this experiment successful. Posterous supports Markdown, which I&amp;nbsp;grew accustomed to&amp;nbsp;while using Blosxom. It automatically syntax-highlights snippets of Clojure code that I&amp;nbsp;post, which is a&amp;nbsp;big win. It is highly customizable, easy to&amp;nbsp;use (blogging via email FTW!), and lets me control my data. It does have its deficiencies, but on the whole it gets in the way less. So I’m switching to&amp;nbsp;Posterous for “Musings of a&amp;nbsp;Lispnik” too.&lt;/p&gt;&lt;p&gt;It is unclear for me how to&amp;nbsp;migrate the old content to&amp;nbsp;new platform, so for now I’ll leave it as is under &lt;a href='http://danieljanus.pl/oldblog'&gt;a&amp;nbsp;temporary address&lt;/a&gt;, while posting new things exclusively here. (&lt;i&gt;Update 2012-09-24:&lt;/i&gt; After another migration, this time to&amp;nbsp;Octopress, I’ve merged the old contents back where it belongs.)&lt;/p&gt;&lt;p&gt;In the near future, I&amp;nbsp;plan to&amp;nbsp;translate a&amp;nbsp;few articles about Clojure I’d written in Polish and post their English versions here. Stay tuned!&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2011-03-10:post:last-post-here</a:id>
<a:title>Last post here</a:title>
<a:link href="http://blog.danieljanus.pl/2011/03/10/last-post-here/"/>
<a:updated>2011-03-10T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve decided to&amp;nbsp;move my English blog to&amp;nbsp;Posterous. The new address is &lt;a href='http://danieljanus-en.posterous.com'&gt;&lt;code&gt;http://danieljanus-en.posterous.com&lt;/code&gt;&lt;/a&gt;. This URL (&lt;a href='http://blog.danieljanus.pl'&gt;&lt;code&gt;http://blog.danieljanus.pl&lt;/code&gt;&lt;/a&gt;) will point to&amp;nbsp;the new blog in about a&amp;nbsp;week’s time.&lt;/p&gt;&lt;p&gt;I’m only posting this to&amp;nbsp;let people update their RSS feeds to&amp;nbsp;the new address, which is&lt;/p&gt;&lt;p&gt;&lt;a href='http://feeds.feedburner.com/MusingsOfALispnik'&gt;&lt;code&gt;http://feeds.feedburner.com/MusingsOfALispnik&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-05-04:post:defnk</a:id>
<a:title>Keyword arguments</a:title>
<a:link href="http://blog.danieljanus.pl/2010/05/04/defnk/"/>
<a:updated>2010-05-04T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;There’s been an &lt;a href='http://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure'&gt;ongoing&lt;/a&gt; &lt;a href='http://www.fatvat.co.uk/2009/01/passing-parameters-in-clojure.html'&gt;debate&lt;/a&gt; about how to&amp;nbsp;pass optional named arguments to&amp;nbsp;Clojure functions. One way to&amp;nbsp;do&amp;nbsp;this is the &lt;a href='http://richhickey.github.com/clojure-contrib/def-api.html#clojure.contrib.def/defnk'&gt;defnk&lt;/a&gt; macro from &lt;code&gt;clojure.contrib.def&lt;/code&gt;; I&amp;nbsp;hesitate to&amp;nbsp;call it &lt;i&gt;canonical&lt;/i&gt;, since apparently not everyone uses it, but I’ve found it useful a&amp;nbsp;number of times. Here’s a&amp;nbsp;sample:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;user&amp;gt; &amp;#40;use 'clojure.contrib.def&amp;#41;
nil
user&amp;gt; &amp;#40;defnk f &amp;#91;:b 43&amp;#93; &amp;#40;inc b&amp;#41;&amp;#41;
#'user/f
user&amp;gt; &amp;#40;f&amp;#41;
44
user&amp;gt; &amp;#40;f :b 100&amp;#41;
101
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is an example of &lt;i&gt;keyword arguments&lt;/i&gt; in action. Keyword arguments are a&amp;nbsp;core feature of some languages, notably &lt;a href='http://www.gigamonkeys.com/book/functions.html#keyword-parameters'&gt;Common Lisp&lt;/a&gt; and &lt;a href='http://caml.inria.fr/pub/docs/manual-ocaml/manual006.html#htoc38'&gt;Objective Caml&lt;/a&gt;. Clojure doesn’t have them, but it’s pretty easy to&amp;nbsp;emulate their basic usage with macros, as &lt;code&gt;defnk&lt;/code&gt; does.&lt;/p&gt;&lt;p&gt;But there’s more to&amp;nbsp;Common Lisp’s keyword arguments than &lt;code&gt;defnk&lt;/code&gt; provides. In CL, the default value of a&amp;nbsp;keyword argument can be an expression referring to&amp;nbsp;other arguments of the same function. For example:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;CL-USER&amp;gt; &amp;#40;defun f &amp;#40;&amp;amp;key &amp;#40;a 1&amp;#41; &amp;#40;b a&amp;#41;&amp;#41;
&amp;#40;+ a b&amp;#41;&amp;#41;
F
CL-USER&amp;gt; &amp;#40;f&amp;#41;
2
CL-USER&amp;gt; &amp;#40;f :a 45&amp;#41;
90
CL-USER&amp;gt; &amp;#40;f :b 101&amp;#41;
102
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;nbsp;wish &lt;code&gt;defnk&lt;/code&gt; had this feature. Or is there some better way that I&amp;nbsp;don’t know of?&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-04-18:post:sunflower</a:id>
<a:title>Sunflower</a:title>
<a:link href="http://blog.danieljanus.pl/2010/04/18/sunflower/"/>
<a:updated>2010-04-18T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;The program I’ve been &lt;a href=''&gt;writing about recently&lt;/a&gt; has come to&amp;nbsp;a&amp;nbsp;point where I&amp;nbsp;think it can be shown to&amp;nbsp;the wide public. It’s called &lt;a href=''&gt;Sunflower&lt;/a&gt; and has its home on GitHub. It’s nowhere near being completed, and of alpha quality right now, but even at this stage it might be useful.&lt;/p&gt;&lt;p&gt;Just as sunflower seed kernels come wrapped in hulls, most HTML documents seen in the wild come wrapped in noise that is not really part of the document itself. Take any news site: a&amp;nbsp;document from such a&amp;nbsp;site contains things such as advertisements, header, footer, and many links. Now suppose you have many documents grabbed from the same site. Is it possible to&amp;nbsp;somehow automate the extraction of the document “essences”?&lt;/p&gt;&lt;p&gt;Sunflower to&amp;nbsp;the rescue. It relies on the assumption that documents coming from the same source have the same structure. It presents a&amp;nbsp;list of strings to&amp;nbsp;the user, and asks to&amp;nbsp;pick those that are contained in the text essence. Then it finds the coordinates of the smallest HTML subtree that contains all those strings, and uses those coordinates to&amp;nbsp;extract information from all documents. And it comes with a&amp;nbsp;nice, easily understandable GUI for that.&lt;/p&gt;&lt;p&gt;This technique works remarkably well for many collections, although not all. An earlier, proof-of-concept implementation (in Common Lisp) has been used to&amp;nbsp;extract many press texts for the &lt;a href=''&gt;National Corpus of Polish&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I’ve given up on the symbol-capturing approach to&amp;nbsp;wizards I’ve presented in my previous posts. Inspired by the DOM tree in Web apps, with a&amp;nbsp;bag of elements with identifiers, I&amp;nbsp;now have a&amp;nbsp;central bag of Swing widgets (implemented as an atom) identified by keywords. This bag contains tidbits of the mutable state of Sunflower. This means that I&amp;nbsp;can write callback functions like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;#&amp;#40;with-components &amp;#91;strings-model selected-dir&amp;#93;
&amp;#40;.removeAllElements strings-model&amp;#41;
&amp;#40;let &amp;#91;p &amp;#40;-&amp;gt; selected-dir htmls first parse&amp;#41;&amp;#93;
&amp;#40;add-component :parsed p&amp;#41;
&amp;#40;doseq &amp;#91;x &amp;#40;strings p&amp;#41;&amp;#93;
&amp;#40;.addElement strings-model x&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Name and conquer: having parts of state explicitly named mean that I&amp;nbsp;can reliably access them from just about anywhere. This reduces confusion and allows for less tangled, more self-contained and understandable code.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-04-05:post:symbol-capture</a:id>
<a:title>A case for symbol capture</a:title>
<a:link href="http://blog.danieljanus.pl/2010/04/05/symbol-capture/"/>
<a:updated>2010-04-05T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Clojure by default protects macro authors from incidentally capturing a&amp;nbsp;local symbol. Stuart Halloway &lt;a href='http://blog.thinkrelevance.com/2008/12/17/on-lisp-clojure-chapter-9'&gt;describes this&lt;/a&gt; in more detail, explaining why this is a&amp;nbsp;Good Thing. However, sometimes this kind of symbol capture is called for. I’ve encountered one such case today while hacking a&amp;nbsp;Swing application.&lt;/p&gt;&lt;p&gt;As I&amp;nbsp;develop the app, I&amp;nbsp;find new ways to&amp;nbsp;express Swing concepts and interact with Swing objects in a&amp;nbsp;more Clojuresque way, so a&amp;nbsp;library of GUI macros and functions gets written. One of them is a&amp;nbsp;&lt;code&gt;wizard&lt;/code&gt; macro for easy creation of installer-like wizards, where there is a&amp;nbsp;sequence of screens that can be navigated with &lt;i&gt;Back&lt;/i&gt; and &lt;i&gt;Next&lt;/i&gt; buttons at the bottom of the window.&lt;/p&gt;&lt;p&gt;The API (certainly not finished yet) currently looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;wizard &amp;amp; components&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where each Swing &lt;code&gt;component&lt;/code&gt; corresponding to&amp;nbsp;one wizard screen can be augmented by a&amp;nbsp;supplementary map, which can contain, &lt;i&gt;inter alia&lt;/i&gt;, a&amp;nbsp;function to&amp;nbsp;execute upon showing the screen in question.&lt;/p&gt;&lt;p&gt;Now, I&amp;nbsp;want those functions to&amp;nbsp;be able to&amp;nbsp;access the &lt;i&gt;Back&lt;/i&gt; and &lt;i&gt;Next&lt;/i&gt; buttons in case they want to&amp;nbsp;disable or enable them at need. I&amp;nbsp;thus want the API user to&amp;nbsp;be able to&amp;nbsp;use two symbols, &lt;code&gt;back-button&lt;/code&gt; and &lt;code&gt;next-button&lt;/code&gt;, in the macro body, and have them bound to&amp;nbsp;the corresponding buttons.&lt;/p&gt;&lt;p&gt;It is crucial that these bindings be lexical and not dynamic. If they were dynamic, they would be only effective during the definition of the wizard, but not when my closures are invoked later on. Thus, my implementation looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;defmacro wizard &amp;#91;&amp;amp; panels&amp;#93;
`&amp;#40;let &amp;#91;&amp;#126;'back-button &amp;#40;button &amp;quot;&amp;lt; Back&amp;quot;&amp;#41;
&amp;#126;'next-button &amp;#40;button &amp;quot;Next &amp;gt;&amp;quot;&amp;#41;&amp;#93;
&amp;#40;do-wizard &amp;#126;'back-button &amp;#126;'next-button &amp;#126;&amp;#40;vec panels&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;do-wizard&lt;/code&gt; is a&amp;nbsp;private function implementing the actual wizard creation, and the &lt;code&gt;&amp;#126;'foo&lt;/code&gt; syntax forces symbol capture.&lt;/p&gt;&lt;p&gt;By the way, if all goes well, this blog post should be the first one syndicated to&amp;nbsp;Planet Clojure. Hello, Planet Clojure readers!&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-04-04:post:apennines-hiking</a:id>
<a:title>Hiking in the Apennines</a:title>
<a:link href="http://blog.danieljanus.pl/2010/04/04/apennines-hiking/"/>
<a:updated>2010-04-04T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve recently done a&amp;nbsp;week-long hike in the Umbria-Marche region of the Italian Apennines (the vicinity of &lt;a href='http://en.wikipedia.org/wiki/Monte_Catria'&gt;Monte Catria&lt;/a&gt;, near &lt;a href='http://en.wikipedia.org/wiki/Cantiano'&gt;Cantiano&lt;/a&gt;, to&amp;nbsp;be more precise), and here are some tips I’d like to&amp;nbsp;share.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The Umbria-Marche Apennine doesn’t seem to&amp;nbsp;be frequented by a&amp;nbsp;lot of tourists, especially in mid-March. The information offices, although helpful, are often closed (this is not only the case with the mountain region: contrary to&amp;nbsp;information available on the Web, the tourist information at Forlì airport was closed on Sunday morning), and most of the Italians we’ve met didn’t speak English.&lt;/li&gt;&lt;li&gt;The tourist trails in the region are not well marked. Direction marks are nowhere to&amp;nbsp;be found, nor are the signs visible on junctions. We&amp;nbsp;had to&amp;nbsp;ask the locals when leaving Cantiano for Monte Tenetra (and ended up on M. Alto instead anyway).&lt;/li&gt;&lt;li&gt;There are a&amp;nbsp;lot of &lt;i&gt;rifugi&lt;/i&gt; (mountain huts), but most of them are closed at this time of year. We&amp;nbsp;passed by six or seven, out of which only one was available for sleep: Rifugio Fonte del Faggio (depicted), merely a&amp;nbsp;small bothy with one worm-eaten bunk bed. Another one, &lt;a href='http://www.montecatria.com/it/rifugi/rifugio_cupa_delle_cotaline.aspx'&gt;Cupa delle Cotaline&lt;/a&gt;, with restaurant facilities and situated by a&amp;nbsp;station of a&amp;nbsp;local skilift, opened in the morning, but was closed for the night.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;img src="/img/blog/faggio.jpg" alt="Rifugio Fonte del Faggio" /&gt;&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-03-31:post:lein-swank</a:id>
<a:title>The pitfalls of &lt;code&gt;lein swank&lt;/code&gt;</a:title>
<a:link href="http://blog.danieljanus.pl/2010/03/31/lein-swank/"/>
<a:updated>2010-03-31T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;A&amp;nbsp;couple of weeks ago I&amp;nbsp;finally got around to&amp;nbsp;acquainting myself with &lt;a href=''&gt;Leiningen&lt;/a&gt;, one of the most popular build tools for Clojure. The thing that stopped me the most was that Leiningen uses &lt;a href=''&gt;Maven&lt;/a&gt; under the hood, which seemed a&amp;nbsp;scary beast at first sight — but once I’ve overcome the initial fear, it turned out to&amp;nbsp;be a&amp;nbsp;quite simple and useful tool.&lt;/p&gt;&lt;p&gt;One feature in particular is very useful for Emacs users like me: &lt;code&gt;lein swank&lt;/code&gt;. You define all dependencies in &lt;code&gt;project.clj&lt;/code&gt; as usual, add a&amp;nbsp;magical line to&amp;nbsp;&lt;code&gt;:dev-dependencies&lt;/code&gt;, then say&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;$ lein swank
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and lo and behold, you can &lt;code&gt;M-x slime-connect&lt;/code&gt; from your Emacs and have all the code at your disposal.&lt;/p&gt;&lt;p&gt;There is, however, an issue that you must be aware of when using &lt;code&gt;lein swank&lt;/code&gt;: Leiningen uses a&amp;nbsp;custom class loader — &lt;a href=''&gt;AntClassLoader&lt;/a&gt; to&amp;nbsp;be more precise — to&amp;nbsp;load the Java classes referenced by the code. Despite being a&amp;nbsp;seemingly irrelevant thing — an implementation detail — this can bite you in a&amp;nbsp;number of most surprising and obscure ways. Try evaluating the following code in a&amp;nbsp;Leiningen REPL:&lt;/p&gt;&lt;pre&gt;&lt;code class="clojure"&gt;&amp;#40;str &amp;#40;.decode
&amp;#40;java.nio.charset.Charset/forName &amp;quot;ISO-8859-2&amp;quot;&amp;#41;
&amp;#40;java.nio.ByteBuffer/wrap
&amp;#40;into-array Byte/TYPE &amp;#40;map byte &amp;#91;-79 -26 -22&amp;#93;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
;=&amp;gt; &amp;quot;???&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The same code evaluated in a&amp;nbsp;plain Clojure REPL will give you &lt;code&gt;&amp;quot;ąćę&amp;quot;&lt;/code&gt;, which is a&amp;nbsp;string represented in ISO-8859-2 by the three bytes from the above snippet.&lt;/p&gt;&lt;p&gt;Whence the difference? Internally, each charset is represented as a&amp;nbsp;unique instance of its specific class. These are loaded lazily as needed by the &lt;code&gt;Charset/forName&lt;/code&gt; method. Presumably, the system class loader is used for that, and somewhere along the way a&amp;nbsp;&lt;code&gt;SecurityException&lt;/code&gt; gets thrown and caught.&lt;/p&gt;&lt;p&gt;Note also that there are parts of Java API which use the charset lookup under the hood and are thus vulnerable to&amp;nbsp;the same problem, for example &lt;code&gt;Reader&lt;/code&gt; constructors taking charset names. If you use &lt;code&gt;clojure.contrib.duck-streams&lt;/code&gt;, then rebinding &lt;code&gt;&amp;#42;default-encoding&amp;#42;&lt;/code&gt; will not work from a&amp;nbsp;Leiningen REPL. Jars and überjars produced by Leiningen should be fine, though.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-02-16:post:downcasing</a:id>
<a:title>Downcasing strings</a:title>
<a:link href="http://blog.danieljanus.pl/2010/02/16/downcasing/"/>
<a:updated>2010-02-16T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I&amp;nbsp;just needed to&amp;nbsp;convert a&amp;nbsp;big (around 200 MB) text file, encoded in UTF-8 and containing Polish characters, all into lowercase. &lt;code&gt;tr&lt;/code&gt; to&amp;nbsp;the rescue, right? Well, not quite.&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;$ echo ŻŹŚÓŃŁĘĆĄ | tr A-ZĄĆĘŁŃÓŚŹŻ a-ząćęłńóśźż
żźśóńłęćą
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Looks reasonable (apart from the fact that I&amp;nbsp;need to&amp;nbsp;specify an explicit character mapping — it would be handy to&amp;nbsp;just have a&amp;nbsp;lcase utility or suchlike); but here’s what happens on another random string:&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;$ echo abisyński | tr A-ZĄĆĘŁŃÓŚŹŻ a-ząćęłńóśźż
abisyŅski
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;nbsp;was just about to&amp;nbsp;report this as a&amp;nbsp;bug, when I&amp;nbsp;spotted the following in the manual:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Currently &lt;code&gt;tr&lt;/code&gt; fully supports only single-byte characters. Eventually it will support multibyte characters; when it does, the &lt;code&gt;-C&lt;/code&gt; option will cause it to complement the set of characters, whereas &lt;code&gt;-c&lt;/code&gt; will cause it to complement the set of values. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Turns out some of the basic tools don’t support multibyte encodings. &lt;code&gt;dd conv=lcase&lt;/code&gt;, for instance, doesn’t even pretend to&amp;nbsp;touch non-ASCII letters, and perl’s &lt;code&gt;tr&lt;/code&gt; operator likewise fails miserably even when one specifies &lt;code&gt;use utf8&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;This is a&amp;nbsp;sad, sad state of affairs. It’s 2010, UTF-8 has been around for seventeen years, and it’s still not supported by one of the core operating system components as other encodings are becoming more and more obsolete. I’m dreaming of the day my system uses it internally for everything.&lt;/p&gt;&lt;p&gt;Fortunately, not everything is broken. Gawk, for example, works:&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;$ echo koŃ i żÓłw | gawk '{ print tolower&amp;#40;$0&amp;#41;; }'
koń i żółw
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and so does sed.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-04-04:&lt;/i&gt; I&amp;nbsp;should have been more specific. The above rant applies to&amp;nbsp;the GNU tools (&lt;code&gt;tr&lt;/code&gt; and &lt;code&gt;dd&lt;/code&gt;) as found in most Linux distributions; other versions can be more featureful. As &lt;a href='http://alexott.net/'&gt;Alex Ott&lt;/a&gt; points out in an email comment, tr on OS X works as expected for characters outside of ASCII, and also supports character classes as in &lt;code&gt;tr '&amp;#91;:upper:&amp;#93;' '&amp;#91;:lower:&amp;#93;'&lt;/code&gt;. This is yet another testimony to&amp;nbsp;general high quality of Apple software; in this particular case, though, it may well be a&amp;nbsp;direct effect of OS X’s BSD heritage. Does it work on *BSD?&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-02-10:post:clojure-set</a:id>
<a:title>Clojure SET</a:title>
<a:link href="http://blog.danieljanus.pl/2010/02/10/clojure-set/"/>
<a:updated>2010-02-10T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve just taken a&amp;nbsp;short breath off work to&amp;nbsp;put &lt;a href='http://github.com/nathell/setgame'&gt;some code&lt;/a&gt; on GitHub that I&amp;nbsp;had written over one night some two months ago. It is an implementation of the &lt;a href='http://en.wikipedia.org/wiki/Set_(game)'&gt;Set&lt;/a&gt; game in Clojure, using Swing for GUI.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;do&amp;nbsp;not have time to&amp;nbsp;clean up or comment the code, so I’m leaving it as is for now; however, I&amp;nbsp;hope that even in its current state it can be of interest, especially for Clojure learners.&lt;/p&gt;&lt;p&gt;Some random notes on the code:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Clojure is concise! The whole thing is just under 250 lines of code, complete with game logic and the GUI. Of these, the logic is about 50 LOC. Despite this it reads clearly and has been a&amp;nbsp;pleasure to&amp;nbsp;write, thanks to&amp;nbsp;Clojure’s supports for sets as a&amp;nbsp;data structure (in vein of the game’s title and theme).&lt;/li&gt;&lt;li&gt;There are no graphics included. All the drawing is done in the GUI part of code (I’ve replaced the canonical squiggle shape by a&amp;nbsp;triangle and stripes by gradients, for the sake of easier drawing).&lt;/li&gt;&lt;li&gt;I’ve toyed around with different Swing layout managers for this game. Back in the days when I&amp;nbsp;wrote in plain Java, I&amp;nbsp;used to&amp;nbsp;use &lt;a href='https://tablelayout.dev.java.net/'&gt;TableLayout&lt;/a&gt;, but it has a&amp;nbsp;non-free license; &lt;a href='http://www.jgoodies.com/freeware/forms/'&gt;JGoodies Forms&lt;/a&gt; is also nice, but has a&amp;nbsp;slightly more complicated API (and it’s an additional dependency, after all). In the end I’ve settled with the standard GridBagLayout, which is similar in spirit to&amp;nbsp;those two, but requires more boilerplate to&amp;nbsp;set up. As it turned out, simple macrology makes it quite pleasurable to&amp;nbsp;use; see &lt;code&gt;add-gridbag&lt;/code&gt; in the code for details.&lt;/li&gt;&lt;li&gt;Other things of interest might be my function to&amp;nbsp;randomly shuffle seqs, which strikes a&amp;nbsp;nice balance between simplicity/conciseness of implementation and randomness; and a&amp;nbsp;useful debugging macro.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Comments?&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2010-01-18:post:reactivation</a:id>
<a:title>Reactivation (and some ramblings on my blogging infrastructure)</a:title>
<a:link href="http://blog.danieljanus.pl/2010/01/18/reactivation/"/>
<a:updated>2010-01-18T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;This blog has not seen content updates in more than a&amp;nbsp;year. Plenty of things can happen in such a&amp;nbsp;long period, and in fact many aspect of my life have seen major changes over this time. I’m not, however, going to&amp;nbsp;write a&amp;nbsp;lengthy post about all that right now. Instead, I&amp;nbsp;just would like to&amp;nbsp;announce the reactivation of the blog.&lt;/p&gt;&lt;p&gt;You might have noticed that many things have changed. First, the blog has a&amp;nbsp;new address: &lt;a href='http://blog.danieljanus.pl'&gt;&lt;code&gt;http://blog.danieljanus.pl&lt;/code&gt;&lt;/a&gt;; the address of the RSS feed has also changed and is now &lt;a href='http://blog.danieljanus.pl/index.rss'&gt;&lt;code&gt;http://blog.danieljanus.pl/index.rss&lt;/code&gt;&lt;/a&gt; — please update your readers!&lt;/p&gt;&lt;p&gt;Probably the most important change is that you now may post comments under the entries, even though this blog continues to&amp;nbsp;be just a&amp;nbsp;bunch of static HTML pages. This is possible thanks to&amp;nbsp;the &lt;a href='http://disqus.com/'&gt;Disqus&lt;/a&gt; service. I&amp;nbsp;wonder whether it will encourage people to&amp;nbsp;give feedback: I&amp;nbsp;have received very few email comments since I&amp;nbsp;started blogging. Also, the static calendar at the top of each page is gone, replaced by a&amp;nbsp;bunch of links to&amp;nbsp;archive posts.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;have long been considering changing &lt;a href='http://www.blosxom.com/'&gt;Blosxom&lt;/a&gt; to&amp;nbsp;something else. The main reason for such a&amp;nbsp;step is that it’s written in Perl, which makes it particularly hard to&amp;nbsp;debug upon encountering an unexpected behaviour. The single most irritating thing was that Blosxom would unexpectedly change the date of a&amp;nbsp;post that was edited (which did not let me fix typos and other glitches); I&amp;nbsp;found a&amp;nbsp;patch for this somewhere, but lost it.&lt;/p&gt;&lt;p&gt;On the other hand, I&amp;nbsp;really liked — and still like — Blosxom’s minimalistic approach and the ease of adding posts. (The very idea of installing a&amp;nbsp;monstrosity such as Wordpress, with its gazillion of features I&amp;nbsp;don’t need, posts kept in a&amp;nbsp;database and what not, makes me feel dizzy.) I&amp;nbsp;fiddled for a&amp;nbsp;while with the thought of reimplementing Blosxom in Common Lisp, but that turned out to&amp;nbsp;be a&amp;nbsp;more time-consuming project than it initially seemed. So when I&amp;nbsp;found &lt;a href='http://blosxom.ookee.com/'&gt;The Unofficial Blosxom User Group&lt;/a&gt; and learned that, contrary to&amp;nbsp;my belief, Blosxom is still actively maintained and has a&amp;nbsp;thriving community, I&amp;nbsp;ended up staying with the original Perl version, refining my installation so that it no longer gets in the way (&lt;a href='http://blosxom.ookee.com/blog/help/howto_update_posts_without_making_the_date_change.html'&gt;this FAQ entry&lt;/a&gt; did the trick). I&amp;nbsp;also rewrote all my source text files to&amp;nbsp;&lt;a href='http://daringfireball.net/projects/markdown/'&gt;Markdown&lt;/a&gt;, which made them vastly more readable and easy to&amp;nbsp;edit, updating links and adding short followup notes where appropriate, but otherwise leaving old entries as they were.&lt;/p&gt;&lt;p&gt;I’d like to&amp;nbsp;thank &lt;a href='http://www.3ofcoins.net/2010/01/08/revive-the-blog-project-52/'&gt;Maciek Pasternacki&lt;/a&gt; for inspiring me to&amp;nbsp;finally get around to&amp;nbsp;this. While my plans are not as ambitious as his — I&amp;nbsp;am not courageous enough to&amp;nbsp;publicly prove my perseverance, so my blogging will likely continue to&amp;nbsp;be irregular — I&amp;nbsp;plan to&amp;nbsp;write more (having accumulated many ideas for blog posts) and I&amp;nbsp;hope the periods of silence will be much shorter than hitherto.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;would like to&amp;nbsp;take this opportunity to&amp;nbsp;wish my readers all the best in the New Year!&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2009-01-02:post:google-books</a:id>
<a:title>Google Books</a:title>
<a:link href="http://blog.danieljanus.pl/2009/01/02/google-books/"/>
<a:updated>2009-01-02T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Yesterday, upon a&amp;nbsp;midnight dreary, while I&amp;nbsp;pondered, weak and weary, over &lt;a href='http://mitpress.mit.edu/algorithms/'&gt;a&amp;nbsp;renowned volume of the olden lore&lt;/a&gt; (and specifically, upon one of the problems contained in the Polish translation of the first edition), I&amp;nbsp;suddenly felt a&amp;nbsp;need to&amp;nbsp;consult the original version, to&amp;nbsp;check whether there are no mistranslations or unincluded corrections for my copy. So I&amp;nbsp;headed for &lt;a href='http://books.google.com/'&gt;Google Book Search&lt;/a&gt;, and apart from finding what I&amp;nbsp;needed, I&amp;nbsp;followed a&amp;nbsp;link that sounded interesting. Quoth the link, &lt;a href='http://books.google.com/googlebooks/agreement/'&gt;“Groundbreaking Agreement”&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Basically, what it all boils to&amp;nbsp;is two pieces of news — you guessed it, a&amp;nbsp;good one and a&amp;nbsp;bad one. The good news is that Google have come to&amp;nbsp;agreement with several major U.S. publishers that will allow them to&amp;nbsp;provide online access to&amp;nbsp;digitized copies of out-of-print but still copyrighted books. &lt;i&gt;Lots&lt;/i&gt; of books, and even though the service is not going to&amp;nbsp;be free, that means all this richness will be at the fingertips — no more need to&amp;nbsp;travel half the world to&amp;nbsp;the Library of Congress to&amp;nbsp;get one of the rare copies we’re after. Sounds cool, huh? Well, here comes the bad news: it will only be available to&amp;nbsp;U.S. citizens.&lt;/p&gt;&lt;p&gt;Or will it?&lt;/p&gt;&lt;p&gt;I&amp;nbsp;wonder how are they going to&amp;nbsp;check for this precondition. IP-based geolocalization springs to&amp;nbsp;mind. And unless they blacklist some IPs or restrict the credit cards used for payment, all I&amp;nbsp;will need is some proxy on some server physically in the U.S. Say, a&amp;nbsp;shell account on someone’s Linux box. I&amp;nbsp;remember reading a&amp;nbsp;Polish blog post about gaining access to&amp;nbsp;American-exclusive content of some website (last.fm I&amp;nbsp;believe it was) in a&amp;nbsp;similar way. Hmm, hmm. We&amp;nbsp;will see.&lt;/p&gt;&lt;p&gt;So, anyone got a&amp;nbsp;shell account to&amp;nbsp;spare?&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-12-18:post:fighting-procrastination</a:id>
<a:title>anti-procrastination.el</a:title>
<a:link href="http://blog.danieljanus.pl/2008/12/18/fighting-procrastination/"/>
<a:updated>2008-12-18T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Fighting procrastination has been my major concern these days. I’ve devised a&amp;nbsp;number of experimental tools to&amp;nbsp;help me with that. One of them is called &lt;a href='http://bach.ipipan.waw.pl/~nathell/projects/snafu.php'&gt;snafu&lt;/a&gt; and can generate reports of your activity throughout the whole day of work. It’s in a&amp;nbsp;preliminary state, but works (at least since I’ve found and fixed a&amp;nbsp;long-standing bug in it which would cause it to&amp;nbsp;barf every now and then), and I&amp;nbsp;already have a&amp;nbsp;number of ideas for its further expansion.&lt;/p&gt;&lt;p&gt;Reports alone, however, do&amp;nbsp;not quite muster enough motivation for work. I’m doing most of my editing/programming work in Emacs, so yesterday I&amp;nbsp;grabbed the Emacs Lisp manual and came up with a&amp;nbsp;couple of extra lines at the end of my &lt;code&gt;.emacs&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;;;; Written by Daniel Janus, 2008/12/18.
;;; This snippet is placed into the public domain. Feel free
;;; to use it in any way you wish. I am not responsible for
;;; any damage resulting from its usage.
&amp;#40;defvar store-last-modification-time t&amp;#41;
&amp;#40;defvar last-modification-time nil&amp;#41;
&amp;#40;defun mark-last-modification-time &amp;#40;beg end len&amp;#41;
&amp;#40;let &amp;#40;&amp;#40;b1 &amp;#40;substring &amp;#40;buffer-name &amp;#40;current-buffer&amp;#41;&amp;#41; 0 1&amp;#41;&amp;#41;&amp;#41;
&amp;#40;when &amp;#40;and store-last-modification-time
&amp;#40;not &amp;#40;string= b1 &amp;quot; &amp;quot;&amp;#41;&amp;#41;
&amp;#40;not &amp;#40;string= b1 &amp;quot;&amp;#42;&amp;quot;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;setq last-modification-time &amp;#40;current-time&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;add-hook 'after-change-functions 'mark-last-modification-time&amp;#41;
&amp;#40;defun write-lmt &amp;#40;&amp;#41;
&amp;#40;setq store-last-modification-time nil&amp;#41;
&amp;#40;when last-modification-time
&amp;#40;with-temp-file &amp;quot;/tmp/emacs-lmt&amp;quot;
&amp;#40;multiple-value-bind &amp;#40;a b c&amp;#41; last-modification-time
&amp;#40;princ a &amp;#40;current-buffer&amp;#41;&amp;#41;
&amp;#40;terpri &amp;#40;current-buffer&amp;#41;&amp;#41;
&amp;#40;princ b &amp;#40;current-buffer&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;setq store-last-modification-time t&amp;#41;&amp;#41;
&amp;#40;run-at-time nil 1 'write-lmt&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Every second (to&amp;nbsp;change that to&amp;nbsp;every 10 seconds, change the &lt;code&gt;1&lt;/code&gt; to&amp;nbsp;&lt;code&gt;10&lt;/code&gt; in the last line) it creates a&amp;nbsp;file named &lt;code&gt;/tmp/emacs-lmt&lt;/code&gt; which contains the time of last modification of any non-system buffer.&lt;/p&gt;&lt;p&gt;That’s all there is to&amp;nbsp;it, at least on the Emacs side. The other part is a&amp;nbsp;simple shell script, which uses &lt;a href='http://www.mplayerhq.hu/'&gt;MPlayer&lt;/a&gt; to&amp;nbsp;display a&amp;nbsp;nag-screen for five seconds, and then give me some time to&amp;nbsp;start doing anything useful before nagging me again:&lt;/p&gt;&lt;pre&gt;&lt;code class="bash"&gt;#!/bin/bash
TIMEOUT=300
while true; do
cat /tmp/emacs-lmt | &amp;#40;
read a; read b;
c=&amp;quot;`date +%s`&amp;quot;;
let x=c-65536&amp;#42;a-b;
if test $x -gt $TIMEOUT;
then mplayer -fs $HOME/p.avi;
sleep 15;
fi&amp;#41;
sleep 1
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The nag-screen in my case is an animation which I’ve created using MEncoder from a&amp;nbsp;single frame which looks &lt;a href='http://bach.ipipan.waw.pl/~nathell/procrastination.png'&gt;like this&lt;/a&gt;. Beware the expletives! (This is one of the few cases I&amp;nbsp;find their usage justified, as the strong message bites the conscience more strongly.)&lt;/p&gt;&lt;p&gt;I’ve only been testing this setup for one day, but so far it’s working flawlessly: I&amp;nbsp;got more done yesterday than for the two previous days combined, and that’s excluding the hour or so that took me to&amp;nbsp;write these snippets.&lt;/p&gt;&lt;p&gt;If anyone else happens to&amp;nbsp;give it a&amp;nbsp;try, I’d love to&amp;nbsp;hear any comments.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-09-23:post:immensely-powerful-tool</a:id>
<a:title>The immensely powerful tool</a:title>
<a:link href="http://blog.danieljanus.pl/2008/09/23/immensely-powerful-tool/"/>
<a:updated>2008-09-23T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;A&amp;nbsp;pen and a&amp;nbsp;sheet of paper are simple utilities; but there lies vast and sheer power in them that I&amp;nbsp;was not aware of. Up until now. So what can they be used for that one might possibly not realize?&lt;/p&gt;&lt;p&gt;Short answer: serializing the stream of consciousness.&lt;/p&gt;&lt;p&gt;Yes, it’s simple, and you may laugh at me now. I&amp;nbsp;myself am a&amp;nbsp;little amazed why I&amp;nbsp;haven’t noticed this before. But this answer lends itself to&amp;nbsp;another question: what good is this serialization, and what exactly do&amp;nbsp;I&amp;nbsp;mean by it, anyway? And the answer to&amp;nbsp;&lt;i&gt;that&lt;/i&gt; is a&amp;nbsp;little longer. So here goes.&lt;/p&gt;&lt;p&gt;I’m one of the people who tend to&amp;nbsp;have problems with concentrating when thinking, especially when thinking hard. This is not to&amp;nbsp;say that I&amp;nbsp;am not capable of thinking hard: I&amp;nbsp;am, but doing so requires a&amp;nbsp;level of concentration that is tricky for me to&amp;nbsp;exert for a&amp;nbsp;prolonged period. (Unless, of course, I&amp;nbsp;am in the state of absolute fascination, where this is taken care of subconsciously. But that’s another story.) More often than not, a&amp;nbsp;tough problem requiring a&amp;nbsp;significant amount of work just has to&amp;nbsp;be dealt with. And then things start to&amp;nbsp;distract attention. There is an itch to&amp;nbsp;scratch, thoughts are shreds, each one pertaining to&amp;nbsp;a&amp;nbsp;tiny bit of the problem, but intertwined with hundreds of other bits of other problems, forming a&amp;nbsp;dense, tangled web, hard to&amp;nbsp;navigate over, and jumping fast from one to&amp;nbsp;another, it becomes more and more unclear what’s next.&lt;/p&gt;&lt;p&gt;So what can one do? One way is to&amp;nbsp;grab a&amp;nbsp;writing device and just &lt;i&gt;start writing&lt;/i&gt;. Running text is linear in nature, so you end up traversing the thought graph depth-first and writing down each thought as you traverse its node. And what’s more, translating ideas to&amp;nbsp;written language &lt;i&gt;slows you down&lt;/i&gt;, which is a&amp;nbsp;&lt;a href='http://www.catb.org/jargon/html/G/Good-Thing.html'&gt;Good Thing&lt;/a&gt; because it makes you see your way through the graph more consciously. It might take you longer to&amp;nbsp;walk from point A&amp;nbsp;to&amp;nbsp;point B than to&amp;nbsp;drive there by car, but definitely you will see more of the landscape as you go. Arriving at the final destination, or simply putting down the pen because enough thoughts have been collected and serialized (there’s never really any end of the stream), makes you end up with a&amp;nbsp;half-product: an unsmithed lump of ore out of which you can forge ingots.&lt;/p&gt;&lt;p&gt;But why a&amp;nbsp;pen and paper, as opposed to, say, a&amp;nbsp;text editor? I&amp;nbsp;think any writing utensil would work to&amp;nbsp;some extent, but for me this seems to&amp;nbsp;be the best option, for several reasons. First of all, I&amp;nbsp;can type on the keyboard much faster than I&amp;nbsp;can write legibly by hand, so this further slows down the pace (which is a&amp;nbsp;Good Thing as we&amp;nbsp;have observed already).&lt;/p&gt;&lt;p&gt;Second, there is something magical in handwriting which a&amp;nbsp;text editor will never be able to&amp;nbsp;achieve: it’s hard to&amp;nbsp;describe. But the net effect is a&amp;nbsp;very evident focus on Here and Now, the pen moving across the paper, the sheet filling up with more and more lines of script. This environment is naturally single-tasked: no Alt-Tab to&amp;nbsp;press to&amp;nbsp;switch to&amp;nbsp;another terminal, no blinking icon of an instant-messaging program (unless a&amp;nbsp;phone happens to&amp;nbsp;ring). This causes synergy with the concentration caused by serializing thoughts.&lt;/p&gt;&lt;p&gt;If you have never tried this approach, feel free to&amp;nbsp;do&amp;nbsp;so. Although I&amp;nbsp;cannot guarantee it will work for you, it certainly does work for me.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-08-09:post:small-lisp</a:id>
<a:title>Who said Common Lisp programs cannot be small?</a:title>
<a:link href="http://blog.danieljanus.pl/2008/08/09/small-lisp/"/>
<a:updated>2008-08-09T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;So, how much disk space does your average CL image eat up? A&amp;nbsp;hundred megs? Fifty? Twenty? Five, perhaps, if you’re using LispWorks with a&amp;nbsp;tree-shaker? Well then, how about this?&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;&amp;#91;nathell@chamsin salza2-2.0.4&amp;#93;$ ./cl-gzip closures.lisp test.gz
&amp;#91;nathell@chamsin salza2-2.0.4&amp;#93;$ gunzip test
&amp;#91;nathell@chamsin salza2-2.0.4&amp;#93;$ diff closures.lisp test
&amp;#91;nathell@chamsin salza2-2.0.4&amp;#93;$ ls -l cl-gzip
-rwxr-xr-x 1 nathell nathell 386356 2008-08-09 11:08 cl-gzip
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That’s right. A&amp;nbsp;standalone executable of a&amp;nbsp;mini-gzip, written in Common Lisp, taking up &lt;i&gt;under 400K!&lt;/i&gt; And it only depends on glibc and GMP, which are available by default on pretty much every Linux installation. (This is on a&amp;nbsp;32-bit x86 machine, by the way).&lt;/p&gt;&lt;p&gt;I&amp;nbsp;used the most recent version of &lt;a href='http://ecls.sourceforge.net/'&gt;ECL&lt;/a&gt; for compiling this tiny example. The key to&amp;nbsp;the size was configuring ECL with &lt;code&gt;--disable-shared --enable-static CFLAGS=&amp;quot;-Os -ffunction-sections -fdata-sections&amp;quot; LDFLAGS=&amp;quot;-Wl,-gc-sections&amp;quot;&lt;/code&gt;. This essentially gives you a&amp;nbsp;poor man’s tree shaker for free at a&amp;nbsp;linker level. And ECL in itself produces comparatively tiny code.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;built this example from &lt;a href='http://www.xach.com/lisp/salza2'&gt;Salza2&lt;/a&gt;’s source by loading the following code snippet:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;defvar salza
'&amp;#40;&amp;quot;package&amp;quot; &amp;quot;reset&amp;quot; &amp;quot;specials&amp;quot;
&amp;quot;types&amp;quot; &amp;quot;checksum&amp;quot; &amp;quot;adler32&amp;quot; &amp;quot;crc32&amp;quot; &amp;quot;chains&amp;quot;
&amp;quot;bitstream&amp;quot; &amp;quot;matches&amp;quot; &amp;quot;compress&amp;quot; &amp;quot;huffman&amp;quot;
&amp;quot;closures&amp;quot; &amp;quot;compressor&amp;quot; &amp;quot;utilities&amp;quot; &amp;quot;zlib&amp;quot;
&amp;quot;gzip&amp;quot; &amp;quot;user&amp;quot;&amp;#41;&amp;#41;
&amp;#40;defvar salza2
&amp;#40;mapcar &amp;#40;lambda &amp;#40;x&amp;#41; &amp;#40;format nil &amp;quot;&amp;#126;A.lisp&amp;quot; x&amp;#41;&amp;#41;
salza&amp;#41;&amp;#41;
&amp;#40;defvar salza3
&amp;#40;mapcar &amp;#40;lambda &amp;#40;x&amp;#41; &amp;#40;format nil &amp;quot;&amp;#126;A.o&amp;quot; x&amp;#41;&amp;#41;
salza&amp;#41;&amp;#41;
&amp;#40;defun build-cl-gzip &amp;#40;&amp;#41;
&amp;#40;dolist &amp;#40;x salza2&amp;#41;
&amp;#40;load x&amp;#41;
&amp;#40;compile-file x :system-p t&amp;#41;&amp;#41;
&amp;#40;c:build-program
&amp;quot;cl-gzip&amp;quot;
:lisp-files salza3
:epilogue-code
'&amp;#40;progn
&amp;#40;in-package :salza2&amp;#41;
&amp;#40;gzip-file &amp;#40;second &amp;#40;si::command-args&amp;#41;&amp;#41;
&amp;#40;third &amp;#40;si::command-args&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;build-cl-gzip&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Sadly enough, there’s no ASDF in here. I&amp;nbsp;have yet to&amp;nbsp;figure out how to&amp;nbsp;leverage ASDF to&amp;nbsp;build small binaries in this constrained environment.)&lt;/p&gt;&lt;p&gt;This gave me a&amp;nbsp;standalone executable 1.2 meg in size. I&amp;nbsp;then proceeded to&amp;nbsp;compress it with &lt;a href='http://upx.sourceforge.net/'&gt;UPX&lt;/a&gt; (with arguments &lt;code&gt;--best --crp-ms=999999&lt;/code&gt;) and got the final result. How cool is that?&lt;/p&gt;&lt;p&gt;I&amp;nbsp;am actively looking for a&amp;nbsp;new job. If you happen to&amp;nbsp;like my writings and think I&amp;nbsp;might be just the right man for the team you’re building up, please feel free to&amp;nbsp;consult my &lt;a href='http://bach.ipipan.waw.pl/~nathell/cv-en.pdf'&gt;résumé&lt;/a&gt; or pass it on.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-Jan-17&lt;/i&gt;: the above paragraph is no longer valid.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-06-23:post:cl-morfeusz</a:id>
<a:title>cl-morfeusz: A ninety minutes’ hack</a:title>
<a:link href="http://blog.danieljanus.pl/2008/06/23/cl-morfeusz/"/>
<a:updated>2008-06-23T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Here’s what I&amp;nbsp;came up with today, after no more than 90 minutes of coding (complete with comments and all):&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;MORFEUSZ&amp;gt; &amp;#40;morfeusz-analyse &amp;quot;zażółć gęślą jaźń&amp;quot;&amp;#41;
&amp;#40;&amp;#40;0 1 &amp;quot;zażółć&amp;quot; &amp;quot;zażółcić&amp;quot; &amp;quot;impt:sg:sec:perf&amp;quot;&amp;#41;
&amp;#40;1 2 &amp;quot;gęślą&amp;quot; &amp;quot;gęśl&amp;quot; &amp;quot;subst:sg:inst:f&amp;quot;&amp;#41;
&amp;#40;2 3 &amp;quot;jaźń&amp;quot; &amp;quot;jaźń&amp;quot; &amp;quot;subst:sg:nom.acc:f&amp;quot;&amp;#41;&amp;#41;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is &lt;a href='http://danieljanus.pl/code/morfeusz.lisp'&gt;cl-morfeusz&lt;/a&gt; in action, a&amp;nbsp;Common Lisp interface to&amp;nbsp;&lt;a href='http://nlp.ipipan.waw.pl/~wolinski/morfeusz/'&gt;Morfeusz&lt;/a&gt;, the morphological analyser for Polish.&lt;/p&gt;&lt;p&gt;It’s a&amp;nbsp;single Lisp file, so there’s no ASDF system definition or asdf-installability for now. I’m not putting it under version control, either. Or, should I&amp;nbsp;say, not yet. When I&amp;nbsp;get around to&amp;nbsp;it, I&amp;nbsp;plan to&amp;nbsp;write a&amp;nbsp;simple parser and write a&amp;nbsp;Polish-language version of &lt;a href='http://en.wikipedia.org/wiki/Colossal_Cave_Adventure'&gt;the text adventure that started it all&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Meanwhile, you may use cl-morfeusz for anything you wish (of course, as long as you comply with Morfeusz’s license). Have fun!&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-Jan-17&lt;/i&gt;: With the advent of UTF-8 support in CFFI, the ugly workarounds in the code are probably no longer necessary; I&amp;nbsp;don’t have time to&amp;nbsp;check it right now, though.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-06-23:post:you-win-some</a:id>
<a:title>You win some, you lose some, you talk some</a:title>
<a:link href="http://blog.danieljanus.pl/2008/06/23/you-win-some/"/>
<a:updated>2008-06-23T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;After my &lt;a href='http://blog.danieljanus.pl/im-not-playing-this-stupid-game-anymore.html'&gt;shameful performance&lt;/a&gt; in the previous tournament, this weekend saw my greatest achievement in tournament Scrabble to&amp;nbsp;date: that of advancing to&amp;nbsp;the quarterfinals of the Cup of Poland. For the record, &lt;a href='http://www.pfs.org.pl/turnieje/2008/w080622.txt'&gt;here&lt;/a&gt; are the final standings. In the quarterfinal, I&amp;nbsp;lost both games to&amp;nbsp;Tomasz Zwoliński (the former Champion of Poland), who went on to&amp;nbsp;win the Cup.&lt;/p&gt;&lt;p&gt;On Thursday, I&amp;nbsp;will be delivering a&amp;nbsp;presentation about the dark side of programming: error handling and how to&amp;nbsp;cope up with Murphy’s law. The talk will last around 30 minutes and be held within &lt;a href='http://aulapolska.pl/'&gt;TechAula&lt;/a&gt;, a&amp;nbsp;place to&amp;nbsp;hear about exciting and revolutionary technologies in software engineering. Feel invited to&amp;nbsp;register and show up.&lt;/p&gt;&lt;p&gt;(Postscriptum 11 July: By public demand, the slides from my talk are now &lt;a href='http://danieljanus.pl/2008-aula-errorhandling.pdf'&gt;available for download&lt;/a&gt;.)&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-06-19:post:another-metapost</a:id>
<a:title>Another metapost</a:title>
<a:link href="http://blog.danieljanus.pl/2008/06/19/another-metapost/"/>
<a:updated>2008-06-19T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;No, I&amp;nbsp;am not going to&amp;nbsp;write about &lt;a href='http://foundry.supelec.fr/projects/metapost/'&gt;the programming language for generating vector graphics&lt;/a&gt;. This is not a&amp;nbsp;real post, but rather a&amp;nbsp;note to&amp;nbsp;self to&amp;nbsp;write ones on certain topics once I&amp;nbsp;get ready for that. And as for today’s title, I&amp;nbsp;just couldn’t resist the pun. ;-)&lt;/p&gt;&lt;p&gt;I’ve been rewriting the Poliqarp Java (GUI) client for the last two weeks or so. The point is to&amp;nbsp;convert it to&amp;nbsp;use &lt;a href='http://bach.ipipan.waw.pl/~nathell/blog/poliqarp-new-protocol.html'&gt;the new protocol&lt;/a&gt;, and to&amp;nbsp;take the opportunity of turning a&amp;nbsp;messy, kludgey and bit-rotting pile of code into a&amp;nbsp;neatly decoupled, cleanly designed, robust and comprehensible utility. And the further I&amp;nbsp;get, the more I&amp;nbsp;see how much it’s worth it. I&amp;nbsp;strongly believe that at the end of this path, upon remergence with the mainline, Poliqarp will become better than ever before.&lt;/p&gt;&lt;p&gt;Thus, when I&amp;nbsp;have something to&amp;nbsp;show (I&amp;nbsp;hope to&amp;nbsp;deliver a&amp;nbsp;preliminary working version, though not yet feature-complete, within the upcoming week or so), I&amp;nbsp;will probably brag about the design solutions I’ve taken. While I’m at it, I&amp;nbsp;will possibly also write the long-delayed description of the new build system.&lt;/p&gt;&lt;p&gt;If there is anybody out there besides me who actually cares for that, stay tuned!&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-06-11:post:mind-the-symlinks</a:id>
<a:title>Today’s lesson: Mind the symlinks</a:title>
<a:link href="http://blog.danieljanus.pl/2008/06/11/mind-the-symlinks/"/>
<a:updated>2008-06-11T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Probably every day I&amp;nbsp;keep learning new things, without even realizing it most of the time. The vast majority of them are minor or even tiny tidbits of knowledge; but even these might be worth noting down from time to&amp;nbsp;time, especially when they are tiny pitfalls I’d fallen into and spent a&amp;nbsp;couple of minutes getting out. By sharing them, I&amp;nbsp;might hopefully prevent someone else for slipping and falling in.&lt;/p&gt;&lt;p&gt;So here’s a&amp;nbsp;simple Unix question: If you enter a&amp;nbsp;subdirectory of the current directory and back to&amp;nbsp;&lt;code&gt;..&lt;/code&gt;, where will you end up? The most obvious answer is, of course, “in the original directory”, and is mostly correct. But is it always? Let’s see.&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;nathell@breeze:&amp;#126;$ pwd
/home/nathell
nathell@breeze:&amp;#126;$ cd foobar
nathell@breeze:&amp;#126;/foobar$ cd ..
nathell@breeze:&amp;#126;$ pwd
/home/nathell
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the hypothesis seems to&amp;nbsp;be right. But let’s try doing this in Python, just for the heck of it:&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;nathell@breeze:&amp;#126;$ python
Python 2.5.2 &amp;#40;r252:60911, Apr 21 2008, 11:12:42&amp;#41;
&amp;#91;GCC 4.2.3 &amp;#40;Ubuntu 4.2.3-2ubuntu7&amp;#41;&amp;#93; on linux2
Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.
&amp;gt;&amp;gt;&amp;gt; import os
&amp;gt;&amp;gt;&amp;gt; print os.getcwd&amp;#40;&amp;#41;
/home/nathell
&amp;gt;&amp;gt;&amp;gt; os.chdir&amp;#40;&amp;quot;foobar&amp;quot;&amp;#41;
&amp;gt;&amp;gt;&amp;gt; os.chdir&amp;#40;&amp;quot;..&amp;quot;&amp;#41;
&amp;gt;&amp;gt;&amp;gt; print os.getcwd&amp;#40;&amp;#41;
/var
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whoa, hang on! What’s that &lt;code&gt;/var&lt;/code&gt; doing there? Of course the one thing I&amp;nbsp;didn’t tell you is that &lt;code&gt;foobar&lt;/code&gt; is not really a&amp;nbsp;directory, but rather a&amp;nbsp;symlink pointing to&amp;nbsp;one (&lt;code&gt;/var/log&lt;/code&gt; in this case).&lt;/p&gt;&lt;p&gt;The corollary is that the shell builtin &lt;code&gt;cd&lt;/code&gt; is &lt;i&gt;not the same&lt;/i&gt; as Unix &lt;code&gt;chdir&amp;#40;&amp;#41;&lt;/code&gt; (it is easily checked that both Perl and C exhibit the same behaviour). In fact, the shell builtin has an oft-forgotten command-line switch, &lt;code&gt;-P&lt;/code&gt;, which causes it to&amp;nbsp;follow physical instead of logical path structure.&lt;/p&gt;&lt;p&gt;On a&amp;nbsp;closing note: I&amp;nbsp;have somewhat neglected the blog throughout the previous month, but I&amp;nbsp;hope to&amp;nbsp;revive it soon. It is not unlikely that such irregularities will recur.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-05-19:post:recently-read-1</a:id>
<a:title>Recently read #1: Akhmatova meets Bashō (Vasil Bykaŭ, “The Wall”)</a:title>
<a:link href="http://blog.danieljanus.pl/2008/05/19/recently-read-1/"/>
<a:updated>2008-05-19T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;(Introductory note: This post marks the beginning of a&amp;nbsp;new series on this blog, aptly titled “Recently read.” Every now and then I&amp;nbsp;will try to&amp;nbsp;verbalize afterthoughts inspired by the books I&amp;nbsp;happen to&amp;nbsp;read, and post them here. I&amp;nbsp;hope these recommendations or anti-recommmendations might turn out to&amp;nbsp;be useful for someone.)&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Give me&lt;br&gt; a kiss to build a dream on,&lt;br&gt; and my imagination&lt;br&gt; will thrive upon that kiss;&lt;br&gt; sweetheart,&lt;br&gt; I ask no more than this —&lt;br&gt; a kiss to build a dream on. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Thusly starts the &lt;a href='http://www.youtube.com/watch?v=e3PXiV95kwA'&gt;Fallout 2 intro&lt;/a&gt; — a&amp;nbsp;mini-movie that can be considered a&amp;nbsp;piece of art in its own right. Louis Armstrong sings these words in an abandoned underground cinema, wherein a&amp;nbsp;movie is displayed, touching on nostalgia for pre-War times as well as severe dangers that lurk on the surface of the earth. And then come these words…&lt;/p&gt;&lt;p&gt;&lt;a href='http://www.youtube.com/watch?v=_mcJAI6oRYY'&gt;“War, war never changes.”&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Just like throughout the entire Fallout saga, these words reverberated in my mind as I&amp;nbsp;read “The Wall,” a&amp;nbsp;collection of short stories by Vasil Bykaŭ, the late Belarussian writer.&lt;/p&gt;&lt;p&gt;For the war indeed does not change. And wherever it appears, it carries around such an amount of destruction and utter wrongness that it is next to&amp;nbsp;unimaginable for a&amp;nbsp;generation grown up in a&amp;nbsp;relatively peaceful place and time such as ours. In fact, even the words “utter wrongness” do&amp;nbsp;not do&amp;nbsp;justice to&amp;nbsp;what was once an unescapable reality. There is only one way to&amp;nbsp;find appropriate words: to&amp;nbsp;show it, show it without overlooking anything, show it dryly and aloofly in all its hideousness.&lt;/p&gt;&lt;p&gt;And Bykaŭ does. There is not a&amp;nbsp;single word of moralizing in these stories. There are no high words, and barely even a&amp;nbsp;human thought beyond fear for life. There is pure depiction; and yet every word in this depiction stands firm and cannot be removed without losing the level of detail called for. This induces associations with Anna Akhmatova and her famous “Requiem,” which begins as follows:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; Это было, когда улыбался&lt;br&gt; только мертвый, спокойствию рад. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;“Это было.” “It happened.” These simple words are immensely powerful. And the same two words, unspoken, echo throughout the entire book. It happened, and it was like this. Nothing more can, or should, be told.&lt;/p&gt;&lt;p&gt;I’ve mentioned the level of detail; this aspect of these stories deserves longer comment. It is imminent that they would not be quite as powerful were it not for the detail. One can almost sense the chill of a&amp;nbsp;dawn rising up above some godforsaken trench somewhere on the battlefront. Or shudder at the cold dampness of the soil inside it. Or smell the stench of decay rising above a&amp;nbsp;corpse shot several days ago. Or feel the almost palpable fear floating in the crossfire of danger, one on the enemy side, the other shaped as one’s own commandment. Or the gloom with which a&amp;nbsp;small group of soldiers sets out to&amp;nbsp;dig their final resting place before committing suicide, lest worse fate befall them.&lt;/p&gt;&lt;p&gt;These stories are almost “haikuistic,” so to&amp;nbsp;speak, in that each one of them resembles a&amp;nbsp;very thinly cut and faithfully portrayed slice of reality from which there is no escape. This shows most strongly in case of the shortest ones, like “The Hill,” which are just several pages long, but it arguably holds even for the longest text in the book, the opening novella, “Love Me, Soldier.” (In which, by the way, Falloutesque associations are particularly strong: imagine a&amp;nbsp;Belarussian sergeant who finds a&amp;nbsp;fellow countrygirl hiding in a&amp;nbsp;village in Austria, at the very end of the war, and falls in love with her. Doesn’t that sound like “a&amp;nbsp;kiss to&amp;nbsp;build a&amp;nbsp;dream on?” Well, in Bykaŭ’s world, good dreams never come true.)&lt;/p&gt;&lt;p&gt;I&amp;nbsp;quoted Akhmatova’s “it happened.” Yet, perhaps, the most striking and saddening impression from “The Wall” as a&amp;nbsp;whole, and one that sets it apart from other war literature, is that this should really read “it still happens.” For the war has ended, but it takes long for a&amp;nbsp;nation to&amp;nbsp;recover from the scars it left; especially the Belarussian nation, who have been held captive by various regimes for too long and have never actually experienced freedom that we&amp;nbsp;take for granted. Once a&amp;nbsp;wound has been healed, it is all too easy to&amp;nbsp;reopen it. And fear for speaking one’s own language remains the same, war or no war.&lt;/p&gt;&lt;p&gt;No wonder Bykaŭ’s writings are still censored in his homeland. Thanks to&amp;nbsp;the Internet, though, &lt;a href='http://kamunikat.org/4108.html'&gt;the full Polish text&lt;/a&gt; of all the stories is available online. Highly recommended.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-05-05:post:inward-ripeness</a:id>
<a:title>Inward ripeness</a:title>
<a:link href="http://blog.danieljanus.pl/2008/05/05/inward-ripeness/"/>
<a:updated>2008-05-05T00:00:00Z</a:updated>
<a:content type="html">&lt;blockquote&gt;&lt;p&gt; How soon hath Time, the subtle thief of youth,&lt;br&gt; Stol’n on his wing my three and twentieth year!&lt;br&gt; My hasting days fly on with full career,&lt;br&gt; But my late spring no bud or blossom shew’th.&lt;br&gt; Perhaps my semblance might deceive the truth&lt;br&gt; That I to manhood am arrived so near;&lt;br&gt; And inward ripeness doth much less appear,&lt;br&gt; That some more timely-happy spirits endu’th.&lt;br&gt; Yet be it less or more, or soon or slow,&lt;br&gt; It shall be still in strictest measure ev’n&lt;br&gt; To that same lot, however mean or high,&lt;br&gt; Toward which Time leads me, and the will of Heav’n:&lt;br&gt; &amp;nbsp;&amp;nbsp;All is, if I have grace to use it so,&lt;br&gt; &amp;nbsp;&amp;nbsp;As ever in my great Task-Master’s eye. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;John Milton is said to&amp;nbsp;have composed this sonnet on his twenty-fourth birthday, and his thoughts (including, but not limited to, the criticism of the achievements so far) are very much in line with mine on my very own 24th birthday. One wonders what is the programming equivalent of “Paradise Lost.”&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-30:post:cl-netstrings</a:id>
<a:title>cl-netstrings</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/30/cl-netstrings/"/>
<a:updated>2008-04-30T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;I’ve just packaged up the Common Lisp netstring handling code that I&amp;nbsp;&lt;a href='http://blog.danieljanus.pl/hacking-away-with-json-rpc.html'&gt;wrote a&amp;nbsp;week ago&lt;/a&gt; into a&amp;nbsp;neat library. Unsurprisingly enough, it is called cl-netstrings and has its own &lt;a href='http://github.com/nathell/cl-netstrings'&gt;home on the Web&lt;/a&gt;. It’s even asdf-installable! I&amp;nbsp;wonder whether this one turns out to&amp;nbsp;be useful for anybody besides me…&lt;/p&gt;&lt;p&gt;The other thing I’ve been working on is a&amp;nbsp;new build system for Poliqarp. But that’s the story for another post — most probably I&amp;nbsp;will write about it when it gets out of a&amp;nbsp;state of constant flux.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-Jan-17&lt;/i&gt;: cl-netstrings is now hosted on GitHub; I’ve updated the link.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-25:post:best-os-ever</a:id>
<a:title>Best OS ever</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/25/best-os-ever/"/>
<a:updated>2008-04-25T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;If you are reading this on a&amp;nbsp;box that does not have an impressive amount of RAM (say, 512 MB or less) and is running a&amp;nbsp;fairly recent Linux, then for goodness sake, drop everything you are doing right now and follow the instructions in this entry. I’m going to&amp;nbsp;show you how to&amp;nbsp;make your system use the memory in a&amp;nbsp;more efficient way, &lt;i&gt;yielding an effect almost equivalent to&amp;nbsp;increasing its amount — with no expenses whatsoever!&lt;/i&gt; Sounds good? Read on.&lt;/p&gt;&lt;p&gt;You see, there’s this Linux kernel module for kernels 2.6.17 and up (that’s what the phrase fairly recent in the previous paragraph macroexpands to), called &lt;a href='http://code.google.com/p/compcache'&gt;Compcache&lt;/a&gt;. It works by slicing out a&amp;nbsp;contiguous chunk of your RAM (25% by default, but it’s settable, of course) and setting it up as a&amp;nbsp;swap space with highmost priority. The trick is that pages that are swapped out to&amp;nbsp;this area are compressed using the &lt;a href='http://www.oberhumer.com/opensource/lzo/'&gt;LZO&lt;/a&gt; algorithm, which provides very fast compression/decompression while maintaining a&amp;nbsp;decent compression ratio. In this way, more unused pages can fit in memory, and less of them are swapped out to&amp;nbsp;disk, which can considerably cut down disk swap usage. I’ve enabled it in my system and it doesn’t seem to&amp;nbsp;cause any problems, while providing a&amp;nbsp;visible efficiency boost. Here’s how I&amp;nbsp;did it on a&amp;nbsp;freshly-installed &lt;a href='http://www.ubuntu.com/products/whatisubuntu/804features/'&gt;Ubuntu Hardy&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I&amp;nbsp;installed the Ubuntu package &lt;code&gt;build-essential&lt;/code&gt;, then downloaded Compcache from its site, extracted it, entered its directory and compiled it by saying make. So far, so easy.&lt;/li&gt;&lt;li&gt;Unfortunately, one cannot say &lt;code&gt;make install&lt;/code&gt; — creating a&amp;nbsp;flexible cross-distro &lt;code&gt;install&lt;/code&gt; target is admittedly hard. So I&amp;nbsp;installed it by hand, ensuring that my system enables it automatically on boot-up.&lt;/li&gt;&lt;li&gt;I&amp;nbsp;created a&amp;nbsp;directory &lt;code&gt;/lib/modules/2.6.24-16-generic/ubuntu/compcache/&lt;/code&gt; and copied the four kernel modules (&lt;code&gt;compcache.ko&lt;/code&gt;, &lt;code&gt;lzo1x&amp;#95;compress.ko&lt;/code&gt;, &lt;code&gt;lzo1x&amp;#95;decompress.ko&lt;/code&gt;, and &lt;code&gt;tlsf.ko&lt;/code&gt;) created by the compilation to&amp;nbsp;that directory.&lt;/li&gt;&lt;li&gt;Next, I&amp;nbsp;ran &lt;code&gt;depmod -a&lt;/code&gt; to&amp;nbsp;make the modules loadable by &lt;code&gt;modprobe&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;I&amp;nbsp;edited the file &lt;code&gt;/etc/modules&lt;/code&gt; and added a&amp;nbsp;line at the end, containing the single word &lt;code&gt;compcache&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;I&amp;nbsp;copied the shell scripts &lt;code&gt;use&amp;#95;compcache.sh&lt;/code&gt; and &lt;code&gt;unuse&amp;#95;compcache.sh&lt;/code&gt; that come with compcache to&amp;nbsp;&lt;code&gt;/usr/local/bin&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;I&amp;nbsp;created an executable script &lt;code&gt;/etc/init.d/compcache&lt;/code&gt; with the following contents:&lt;pre&gt;&lt;code class="bash"&gt;#!/bin/sh
case &amp;quot;$1&amp;quot; in
start&amp;#41;
/usr/local/bin/use&amp;#95;compcache.sh ;;
stop&amp;#41;
/usr/local/bin/unuse&amp;#95;compcache.sh ;;
esac
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;The last step was to&amp;nbsp;create a&amp;nbsp;symlink &lt;code&gt;/etc/rc2.d/S02compcache&lt;/code&gt; pointing to&amp;nbsp;that script.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I&amp;nbsp;then rebooted the system and verified that the new swapspace is in use:&lt;/p&gt;&lt;pre&gt;&lt;code class="bash"&gt;nathell@chamsin:&amp;#126;$ cat /proc/swaps
Filename Type Size Used Priority
/dev/sdb2 partition 996020 0 -1
/dev/ramzswap0 partition 128896 111396 100
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With the final release of Hardy installed on my main box and compcache optimizing its memory usage, I&amp;nbsp;do&amp;nbsp;not hesitate to&amp;nbsp;call this combo the best OS I&amp;nbsp;have ever had installed.&lt;/p&gt;&lt;p&gt;And no, I&amp;nbsp;don’t own a&amp;nbsp;Mac. :-/&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-24:post:hacking-away-with-json-rpc</a:id>
<a:title>Hacking away with JSON-RPC</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/24/hacking-away-with-json-rpc/"/>
<a:updated>2008-04-24T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Let’s try:&lt;/p&gt;&lt;pre&gt;&lt;code class="lisp"&gt;&amp;#40;let &amp;#40;&amp;#40;s &amp;#40;socket-stream
&amp;#40;socket-connect &amp;quot;localhost&amp;quot; 10081
:element-type '&amp;#40;unsigned-byte 8&amp;#41;&amp;#41;&amp;#41;&amp;#41;&amp;#41;
&amp;#40;write-netstring &amp;quot;{\&amp;quot;method\&amp;quot;:\&amp;quot;ping\&amp;quot;,\&amp;quot;params\&amp;quot;:&amp;#91;&amp;#93;,\&amp;quot;id\&amp;quot;:1}&amp;quot; s&amp;#41;
&amp;#40;finish-output s&amp;#41;
&amp;#40;princ &amp;#40;read-netstring s&amp;#41;&amp;#41;
&amp;#40;close s&amp;#41;&amp;#41;
; { &amp;quot;result&amp;quot;: &amp;quot;pong&amp;quot; }
; --&amp;gt; T
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yay! This is Common Lisp talking to&amp;nbsp;a&amp;nbsp;&lt;a href='http://json-rpc.org/'&gt;JSON-RPC&lt;/a&gt; server written in C. This means that I&amp;nbsp;have now the foundations for rewriting Poliqarp on top of JSON-RPC (according to&amp;nbsp;the &lt;a href='http://blog.danieljanus.pl/poliqarp-new-protocol.html'&gt;protocol spec&lt;/a&gt; I&amp;nbsp;have recently posted) up and running, and all that remains is to&amp;nbsp;fill the remainder.&lt;/p&gt;&lt;p&gt;Well, to&amp;nbsp;be honest, this is not exactly JSON-RPC. First off, as you might have noticed, the above snippet of code sends JSON-RPC requests as &lt;a href='http://cr.yp.to/proto/netstrings.txt'&gt;netstrings&lt;/a&gt;. This is actually intentional, and the reasons for adopting this encoding have been described in detail in the spec (it basically boils down to&amp;nbsp;the fact that it greatly simplifies reading from and writing to&amp;nbsp;network, especially in C). I&amp;nbsp;wrote some crude code to&amp;nbsp;handle netstrings in CL — now it occurred to&amp;nbsp;me that it might actually be worthwhile to&amp;nbsp;polish it up a&amp;nbsp;little, write some documentation and put on &lt;a href='http://www.cliki.net/'&gt;CLiki&lt;/a&gt; as an asdf-installable library. I’ll probably get on to&amp;nbsp;this quite soon.&lt;/p&gt;&lt;p&gt;Second, the resulting JSON object does not have all the necessary stuff. It contains the result, but not the error or id (as mandated by the &lt;a href='http://json-rpc.org/wiki/specification'&gt;JSON-RPC spec&lt;/a&gt;). This is actually a&amp;nbsp;deficiency of the &lt;a href='http://www.big-llc.com/software.jsp'&gt;JSON-RPC C library&lt;/a&gt; I’m currently using. It places the burden of constructing objects that are proper JSON-RPC responses on the programmer, instead of doing that itself. This will be easy to&amp;nbsp;sort out, however, because the library is small and adheres to&amp;nbsp;the &lt;a href='http://en.wikipedia.org/wiki/KISS_principle'&gt;KISS principle&lt;/a&gt;. More of a&amp;nbsp;problem is that the licensing of that library is unclear; I&amp;nbsp;emailed the maintainers to&amp;nbsp;explain the status.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-24:post:forgetting</a:id>
<a:title>Forgetting</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/24/forgetting/"/>
<a:updated>2008-04-24T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;It has just occurred to&amp;nbsp;me that the best way to&amp;nbsp;throwing things out of one’s mind is to&amp;nbsp;let it be absorbed by something else. I&amp;nbsp;guess this is oft-overlooked fact, even though it seems to&amp;nbsp;be quite obvious. In particular, forcing oneself not to&amp;nbsp;think about something is &lt;i&gt;not&lt;/i&gt; a&amp;nbsp;wise strategy, since it leads to&amp;nbsp;mental strain and thinking more and more, eventually yielding dejectedness that can be hard to&amp;nbsp;get over.&lt;/p&gt;&lt;p&gt;And what could be more absorbing than debugging a&amp;nbsp;&lt;code&gt;SIGSEGV&lt;/code&gt; buried deeply in the innards of some library early in the morning? ;–)&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-22:post:eclm-2008</a:id>
<a:title>ECLM 2008</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/22/eclm-2008/"/>
<a:updated>2008-04-22T00:00:00Z</a:updated>
<a:content type="html">&lt;blockquote&gt;&lt;p&gt; &lt;i&gt;What is there left for me to do in this life&lt;/i&gt;?&lt;br&gt; &lt;i&gt;Did I achieve what I had set in my sights?&lt;/i&gt;&lt;br&gt; &lt;i&gt;Am I a happy man, or is this sinking sand?&lt;/i&gt;&lt;br&gt; &lt;i&gt;Was it all worth it?—was it all worth it?&lt;/i&gt;&lt;br&gt; &lt;p style="text-align: right;"&gt;— Queen&lt;/p&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Gusts of moderate wind are blowing at my face through the open window of a&amp;nbsp;train from Amsterdam to&amp;nbsp;Warsaw as I&amp;nbsp;write these words. The last buildings of Amsterdam have vanished a&amp;nbsp;while ago, giving ground to&amp;nbsp;the damp, low countryside of the Netherlands — not quite fascinating sight to&amp;nbsp;be watching — so I&amp;nbsp;decided to&amp;nbsp;fire up my laptop and write down some impressions while they are sharp and vivid — impressions from the &lt;a href='http://www.weitz.de/eclm2008/'&gt;European Common Lisp Meeting&lt;/a&gt; that was held in Amsterdam yesterday.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;was there with &lt;a href='http://blog.pasternacki.net/'&gt;Maciek&lt;/a&gt; and &lt;a href='http://lisp.jogger.pl/'&gt;Richard&lt;/a&gt;. Amsterdam did not receive us warmly, pouring some mild yet cold rain on us, but our hosts — Lispniks from the Hague, Gabriele and Victor from &lt;a href='http://streamtech.nl/'&gt;Streamtech&lt;/a&gt; — turned out to&amp;nbsp;be really nice guys. I’m not going to&amp;nbsp;go into a&amp;nbsp;very detailed description of the social aspects of our trip, instead focusing on the conference itself. And that is definitely a&amp;nbsp;topic worth talking about for a&amp;nbsp;long time.&lt;/p&gt;&lt;p&gt;The first man to&amp;nbsp;speak was Jeremy Jones of &lt;a href='http://www.clozure.com/'&gt;Clozure Associates&lt;/a&gt;, talking about InspireData and how they did it in Lisp. Although they also seem to&amp;nbsp;be the people behind Clozure CL the implementation of Common Lisp, InspireData, the product their presentation was about, seems to&amp;nbsp;have been written in LispWorks. It is a&amp;nbsp;quite interesting application for browsing datasets in many interesting ways and draw conclusions for them. Jeremy started off with a&amp;nbsp;demonstration presenting the key ideas of InspireData and what it can do, and this almost instantly hooked the attention of most of the gathered Lispers; mine, at least, definitely. First off, it seems to&amp;nbsp;be quite a&amp;nbsp;nice success story of a&amp;nbsp;real-world application of Lisp, well worth learning about and mentioning where it deserves a&amp;nbsp;mention. Second, one of its great features shown by the demo is that one can copy HTML tables from a&amp;nbsp;Web browser and paste them as InspireData datasets. Given that Poliqarp now has statistical features and can export its data to&amp;nbsp;HTML, I&amp;nbsp;wonder whether it is possible to&amp;nbsp;couple it with InspireData to&amp;nbsp;interactively explore linguistic material in an absorbing way. That’s certainly a&amp;nbsp;topic worthy of further research.&lt;/p&gt;&lt;p&gt;And last but not least, Jeremy outlined the points they did wrong and those they got right. Among those latter were two letters that now constitute a&amp;nbsp;huge part of my professional life: &lt;strong&gt;QA&lt;/strong&gt;. He just couldn’t emphasize enough how crucial the fact that they had a&amp;nbsp;serious quality assurance process from the very beginning proved to&amp;nbsp;yield the final quality of the product. That’s the lesson I’m now quickly learning. When I&amp;nbsp;learned that InspireData was mostly tested by hand by a&amp;nbsp;skilled QA team, I&amp;nbsp;felt somewhat proud of being able to&amp;nbsp;automate large parts of the process at Sentivision. I’m very curious where this path will lead me to. Let’s hope for the best!&lt;/p&gt;&lt;p&gt;The next speaker was Nicolas Neuss of University of Karlsruhe, talking about &lt;a href='http://www.femlisp.org/'&gt;Femlisp&lt;/a&gt;, a&amp;nbsp;framework for solving partial differential equations in Common Lisp. I&amp;nbsp;have little to&amp;nbsp;say about this one, since I&amp;nbsp;lack the mathematical background needed to&amp;nbsp;fully comprehend and appreciate the topic; it’s just not my kettle of fish. Undoubtedly, though, Femlisp seems to&amp;nbsp;be filling its niche in a&amp;nbsp;neat way, as the demonstrations showed.&lt;/p&gt;&lt;p&gt;After a&amp;nbsp;coffee break, Stefan Richter came up with the one presentation that I’ve been looking forward to&amp;nbsp;the most; that of using Common Lisp for large, scalable Internet systems. After all the talks were over, Maciek dubbed it a&amp;nbsp;“very nice anti-FUD presentation” and I&amp;nbsp;could not agree more. I&amp;nbsp;didn’t learn many new things from it, but the author clearly knows how to&amp;nbsp;attempt to&amp;nbsp;convince non-Lispers to&amp;nbsp;try out Lisp. The talk started off with outlining the typical designs of Web apps and portals, starting with simple one-server scenarios that don’t scale well and progressing in the direction of more scalable and extensible ones. Stefan then pointed out that in some mainstream languages like Java there exists a&amp;nbsp;mature and proven infrastructure for employing such designs. And then came the key point — &lt;i&gt;that this is the case also for Common Lisp!&lt;/i&gt; All the necessary tools are there, ready to&amp;nbsp;use Right Now and free for the most part; they’re just not as mature in some cases. This is not much of a&amp;nbsp;problem, though, given the incremental nature of Lisp development: any problem at hand is typically fixable much faster than in case of other languages. The only weird thing was that the author advocated using continuation-based Web frameworks (such as &lt;a href='http://common-lisp.net/project/cl-weblocks/'&gt;Weblocks&lt;/a&gt; or &lt;a href='http://common-lisp.net/project/ucw/'&gt;UnCommon Web&lt;/a&gt;) just a&amp;nbsp;couple of minutes after discouraging using sticky sessions.&lt;/p&gt;&lt;p&gt;Next came Killian Sprotte with a&amp;nbsp;speech about &lt;a href='http://www2.siba.fi/PWGL/'&gt;PWGL&lt;/a&gt;, the program for computer-aided music composing. I&amp;nbsp;have very mixed feelings about it. Notice that I&amp;nbsp;didn’t use the word “presentation” — there was no presentation at all. Yes, that’s right. The speaker was just talking and showing off various things in the musical engine. Now, having no presentation accompanying the talk is not necessarily a&amp;nbsp;bad thing in itself; but without one, it’s a&amp;nbsp;little harder to&amp;nbsp;draw attention of the audience and a&amp;nbsp;whole lot easier to&amp;nbsp;deliver a&amp;nbsp;chaotic talk instead of a&amp;nbsp;cleanly-structured and well-organized one. Such was the case with this speech. Some features were shown, but with a&amp;nbsp;fair amount of obscurity and boredom thrown in, leaving me with a&amp;nbsp;rather low overall impression.&lt;/p&gt;&lt;p&gt;As for PWGL itself, some of the ideas employed in it seem a&amp;nbsp;bit peculiar (for want of a&amp;nbsp;better word) to&amp;nbsp;me. As befits a&amp;nbsp;Lisp program, it is an extensible utility that actually allows users to&amp;nbsp;program music just as one programs software. But the way that programming is done… well, think of a&amp;nbsp;graphical editor for Lisp programs. An editor in which to&amp;nbsp;write, say, a&amp;nbsp;factorial function, you right-click an initially blank sheet, select &lt;code&gt;defun&lt;/code&gt; from a&amp;nbsp;pop-up with a&amp;nbsp;complicated set of menus and submenus… and kaboom! up comes a&amp;nbsp;box divided into several sub-boxes. They correspond to&amp;nbsp;— what else they could? — the name of the function, list of arguments, and a&amp;nbsp;body. You can draw boxes representing computations, drag them around and link them with arrows — this is supposed to&amp;nbsp;build complicated expressions out of simpler ones. And there is a&amp;nbsp;huge library of musical tools, all available for the convenience of a&amp;nbsp;programmer. Or, should I&amp;nbsp;say, a&amp;nbsp;composer.&lt;/p&gt;&lt;p&gt;Sounds cool? Maybe — for a&amp;nbsp;newbie. I&amp;nbsp;can’t really say. As someone who has high experience with Lisp and programming in general, I&amp;nbsp;can only speak for myself. And for me all this click-and-drag-programming seems to&amp;nbsp;be an unnecessarily tedious, obscure and error-prone way of doing things. Stuff like score editors, chord editors or various transformations is admittedly cool, but for lower-level matters the kind of visualization PWGL offers (and it obviously has its rough edges) seems to&amp;nbsp;get in the way rather than staying out of it. But perhaps that’s just me?&lt;/p&gt;&lt;p&gt;By the time the fourth talk ended, most Lispers were already hungry, so a&amp;nbsp;lunch break followed. I&amp;nbsp;talked to&amp;nbsp;some guy (I&amp;nbsp;don’t remember his name, alas) who’s working on porting Clozure CL to&amp;nbsp;64-bit Windows. This is great news — when the port’s complete, it has high chances of becoming the free Common Lisp implementation of choice for many Windows Lisp hackers.&lt;/p&gt;&lt;p&gt;Juan José García-Ripoll then &lt;a href='http://ecls.wiki.sourceforge.net/space/showimage/eclm2008.pdf'&gt;talked&lt;/a&gt; about &lt;a href='http://ecls.sourceforge.net/'&gt;ECL&lt;/a&gt;, another CL implementation that is characterized by a&amp;nbsp;fairly small memory and disk footprint, while still managing to&amp;nbsp;achieve decent performance (via compilation to&amp;nbsp;C) and good standard compliance. It was good to&amp;nbsp;see that ECL is still quite alive and getting better and better with each release. Just for the heck of it, I&amp;nbsp;attempted in the evening to&amp;nbsp;reproduce the problem I&amp;nbsp;had with ECL a&amp;nbsp;while ago on a&amp;nbsp;fresh CVS checkout. I&amp;nbsp;managed to&amp;nbsp;reproduce it (for the curious, it was an issue with ECL failing to&amp;nbsp;build after having been &lt;code&gt;configure&lt;/code&gt;d with the option &lt;code&gt;--disable-shared&lt;/code&gt;). So I&amp;nbsp;reported the bug to&amp;nbsp;Juan, and he promised to&amp;nbsp;look into it within the next days. And I&amp;nbsp;must say that reporting bugs IRL to&amp;nbsp;open source projects’ maintainers is a&amp;nbsp;very nice experience. :-)&lt;/p&gt;&lt;p&gt;And then came a&amp;nbsp;really big surprise, and I&amp;nbsp;mean a&amp;nbsp;&lt;i&gt;nice&lt;/i&gt; surprise. It took the form of Kristofer Kvello of &lt;a href='http://www.selvaag.no/'&gt;Selvaag&lt;/a&gt;, a&amp;nbsp;Norwegian-based house-building company, and his presentation on &lt;a href='http://www.selvaag.no/en/Companies/Selvaagbluethink/aboutus/Sider/default.aspx'&gt;House Designer&lt;/a&gt;, a&amp;nbsp;Common Lisp program for aiding in designing residences, as the name suggests. Yet another example of a&amp;nbsp;success story in an area CL can really excel at. Basically, what House Designer can do&amp;nbsp;is that you give it a&amp;nbsp;&lt;i&gt;sketch&lt;/i&gt;, containing a&amp;nbsp;rough description of the shape of a&amp;nbsp;flat or residence and layout of rooms, and out comes a&amp;nbsp;very detailed project with all sorts of bells and whistles: the program automatically figures out what the number of windows should be and where they should be located, the number and location of electric outlets, the optimal types of walls, layout of water installation and what not. It’s transfixing when you think of the sheer amount of tedious labour it automates, taking into account all of the professional knowledge about designing houses accumulated over years, some parts of which a&amp;nbsp;human can easily omit. And it’s been Lisp all the lifetime of this project, and it’s Lisp all the way down (except for the GUI in Java)! Very, very impressive!&lt;/p&gt;&lt;p&gt;Marc Battyani’s talk about &lt;a href='http://www.hpcplatform.com/'&gt;programming FPGAs in Lisp&lt;/a&gt; probably should not have been stacked so late in the programme. I&amp;nbsp;mean, the topic seems to&amp;nbsp;be quite interesting (though a&amp;nbsp;bit low-level for my interests), but there was something about Marc’s way of talking and showing things that sent me off dozing almost instantaneously. I’d been a&amp;nbsp;bit tired after the many hours of sitting and listening to&amp;nbsp;speeches, especially after having woken up at six o’clock, and so I&amp;nbsp;somewhat regret missing large parts of the talk. It’s nice to&amp;nbsp;know, though, that it is possible to&amp;nbsp;do&amp;nbsp;such things with Lisp. Seems to&amp;nbsp;have a&amp;nbsp;high hack value, as in: “Why do&amp;nbsp;it this way? Because we&amp;nbsp;&lt;i&gt;can&lt;/i&gt;!”&lt;/p&gt;&lt;p&gt;And what better end of a&amp;nbsp;conference could one ask for than a&amp;nbsp;rant by Kenny Tilton? If you have only encountered Kenny on the Usenet (some of the crème de la crème of his postings is &lt;a href='http://www.pasternacki.net/en/ken-tilton-fortunes'&gt;meticulously collected by Maciek&lt;/a&gt;) and think he’s one heck of a&amp;nbsp;freak, you definitely should listen to&amp;nbsp;him live. Here was another talk without slides — just talking and demonstrating stuff — but this time, it was a&amp;nbsp;totally different thing. Kenny sure knows how to&amp;nbsp;attract the attention of the audience and how not to&amp;nbsp;let it loose throughout an hour’s worth of talking. And he changes topics with mastery, using digressions to&amp;nbsp;a&amp;nbsp;great effect to&amp;nbsp;avoid the boredom slipping in, caused by bragging about one thing all the time. There was &lt;a href='http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html'&gt;Cells&lt;/a&gt; in that talk, there was &lt;a href='http://www.theoryyalgebra.com/'&gt;teaching of algebra&lt;/a&gt;, and there was high-speed driving through the streets of New York. I&amp;nbsp;only hope someone has recorded that to&amp;nbsp;put it online.&lt;/p&gt;&lt;p&gt;So, this was it. There was much talk afterwards, there was much beer, there was much socializing, there was much rejoicing. I&amp;nbsp;saw a&amp;nbsp;real &lt;a href='http://laptop.org/'&gt;XO-1&lt;/a&gt; and played with it for a&amp;nbsp;while, and boy, isn’t it cute! And then we&amp;nbsp;all came back. And here I&amp;nbsp;am, sitting at my desk in Warsaw (it’s the next day already; I&amp;nbsp;really wish my laptop had a&amp;nbsp;better battery), finishing up this longish blog entry and asking myself: was this 50 euro well spent?&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt; &lt;i&gt;Yes, it was a worthwhile experience, hahhahahahahhaaaa!&lt;/i&gt;&lt;br&gt; (evil chuckle à la Kenny)&lt;br&gt; &lt;i&gt;It was worth it!&lt;/i&gt; &lt;/p&gt;&lt;/blockquote&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-16:post:poliqarp-new-protocol</a:id>
<a:title>Poliqarp’s new protocol</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/16/poliqarp-new-protocol/"/>
<a:updated>2008-04-16T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;The first version of the document I’ve been writing about &lt;a href='http://blog.danieljanus.pl/tex-hackery.html'&gt;a&amp;nbsp;couple of days ago&lt;/a&gt; is now &lt;a href='http://bach.ipipan.waw.pl/~nathell/new-protocol.pdf'&gt;ready for public review&lt;/a&gt;. I’ll be making an initial attempt at the implementation once I&amp;nbsp;return from the &lt;a href='http://weitz.de/eclm2008/'&gt;European Common Lisp Meeting ‘08&lt;/a&gt; and write a&amp;nbsp;report.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-14:post:im-not-playing-this-stupid-game-anymore</a:id>
<a:title>I’m not playing this stupid game anymore</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/14/im-not-playing-this-stupid-game-anymore/"/>
<a:updated>2008-04-14T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Not until the next tournament, that is. My achievements in the 12th Scrabble Championship of Warsaw can be described as “mediocre” at best; four won, one drawn and seven lost games mean that my general rating will drop down by two points or so. Oh well. Everybody knows it’s a&amp;nbsp;stupid game. ;-) At least I’ve managed to&amp;nbsp;get a&amp;nbsp;decent small score, with an average of 377 points per game.&lt;/p&gt;&lt;p&gt;Random resolutions for the indefinite future:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Get a&amp;nbsp;final draft of the C++09 standard when it’s ready and acquaint myself with it as closely as possible. I&amp;nbsp;strongly dislike C++ (and I’m not alone in this — see the &lt;a href='http://yosefk.com/c++fqa/'&gt;Frequently Questioned Answers&lt;/a&gt; about C++ for very detailed criticisms); however, I’ve long wanted to&amp;nbsp;learn that language better just to&amp;nbsp;know all the strengths and weaknesses of the enemy. The ideal moment for this will be when the new standard is out; this will give me the advantage of not having to&amp;nbsp;unlearn the things changed by the standard, while staying on a&amp;nbsp;cutting and competitive edge.&lt;/li&gt;&lt;li&gt;Get a&amp;nbsp;copy of &lt;a href='http://en.wikipedia.org/wiki/Federico_Garc%C3%ADa_Lorca'&gt;Federico García Lorca&lt;/a&gt;’s poems translated into Polish by Jerzy Ficowski. I&amp;nbsp;have only a&amp;nbsp;very vague knowledge of Lorca (just his Romance of the Spanish Civil Guard (&lt;a href='http://www.poesia-inter.net/index214.htm'&gt;Romance de la Guardia Civil Española&lt;/a&gt;)), but I&amp;nbsp;very much like what little I&amp;nbsp;know.&lt;/li&gt;&lt;/ol&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-10:post:recipe-for-successful-presentation</a:id>
<a:title>Recipe for a successful presentation</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/10/recipe-for-successful-presentation/"/>
<a:updated>2008-04-10T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;&lt;a href='http://www.latex-project.org/'&gt;LaTeX&lt;/a&gt; + &lt;a href='http://latex-beamer.sourceforge.net/'&gt;Beamer&lt;/a&gt; (for typesetting the presentation in a&amp;nbsp;visually pleasant, clean, simple and consistent way) + &lt;a href='http://impressive.sourceforge.net/'&gt;KeyJNote&lt;/a&gt; (for presenting it stylishly to&amp;nbsp;the audience) = a&amp;nbsp;recipe for success. In particular, KeyJNote, which I&amp;nbsp;found only yesterday, seems to&amp;nbsp;be a&amp;nbsp;fine and tremendously useful piece of software, despite being very young. The only annoyance I&amp;nbsp;have found in it is that it doesn’t respond to&amp;nbsp;Alt-Tab when in fullscreen mode. On the typographical side, I&amp;nbsp;used the &lt;a href='http://www.cert.fr/dcsd/THESES/sbouveret/francais/LaTeX.html'&gt;progressbar&lt;/a&gt; Beamer theme and the &lt;a href='http://www.nowacki.strefa.pl/torunska-e.html'&gt;Torunian Antiqua&lt;/a&gt; font, both to&amp;nbsp;great effect.&lt;/p&gt;&lt;p&gt;While I’m at this topic, &lt;a href='http://jan.rychter.com/'&gt;Jan Rychter&lt;/a&gt; has recently posted &lt;a href='http://jan.rychter.com/blog/files/sztuka-prezentacji-03-2008.html'&gt;a&amp;nbsp;great guide to&amp;nbsp;giving presentations&lt;/a&gt;, especially short ones. I&amp;nbsp;heartily recommend it to&amp;nbsp;those of you who speak Polish (is there actually any non-Polish-speaking person reading this?)&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-Jan-17&lt;/i&gt;: KeyJNote is now called &lt;a href='http://impressive.sourceforge.net/'&gt;Impressive&lt;/a&gt;.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-07:post:ubuntu-postinstall</a:id>
<a:title>Ubuntu post-installation tricks</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/07/ubuntu-postinstall/"/>
<a:updated>2008-04-07T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;Yesterday, my level of frustration with my old operating system at work exceeded a&amp;nbsp;critical point, and I&amp;nbsp;installed a&amp;nbsp;fresh daily build of the not-yet-released &lt;a href='https://wiki.ubuntu.com/HardyHeron'&gt;Ubuntu 8.04&lt;/a&gt; in place of it. Then, in addition to&amp;nbsp;usual post-installation chores like setting up mail, hardware, etc., I&amp;nbsp;performed a&amp;nbsp;couple of steps to&amp;nbsp;make the system more pleasurable to&amp;nbsp;use. Here’s what I&amp;nbsp;did, just in case someone finds this useful.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;First, I&amp;nbsp;tweaked the font rendering. This was one area that has long been a&amp;nbsp;PITA for Linux users (at least for me, since 2000 or so), but as far as Ubuntu is concerned, they introduced a&amp;nbsp;change to&amp;nbsp;Freetype somewhere along the way between Feisty and Gutsy which, when set up properly, makes the font rendering on LCD displays far superior for me to&amp;nbsp;that of, say, Windows XP, in particular at small font sizes. The way to&amp;nbsp;enable it is to&amp;nbsp;enable sub-pixel rendering, and set the hinting level to&amp;nbsp;“slight.” This results in a&amp;nbsp;rendering very close to&amp;nbsp;what the author of &lt;a href='http://www.antigrain.com/research/font_rasterization'&gt;Texts Rasterization Exposures&lt;/a&gt; managed to&amp;nbsp;achieve.&lt;/li&gt;&lt;li&gt;I&amp;nbsp;installed the package &lt;code&gt;msttcorefonts&lt;/code&gt; to&amp;nbsp;get Microsoft’s free-as-in-beer set of core TrueType fonts, including Times New Roman, Arial, Georgia, etc. There are very many sites out there on the Web that were designed with these fonts in mind, and this is one of the few areas Microsoft doesn’t completely suck at.&lt;/li&gt;&lt;li&gt;Next I&amp;nbsp;enabled bitmap fonts. The way to&amp;nbsp;do&amp;nbsp;this is to&amp;nbsp;become root, cd to&amp;nbsp;&lt;code&gt;/etc/fonts/conf.d&lt;/code&gt;, remove the symlink named &lt;code&gt;70-no-bitmaps.conf&lt;/code&gt;, and make a&amp;nbsp;symlink pointing to&amp;nbsp;&lt;code&gt;/etc/fonts/conf.avail/70-yes-bitmaps.conf&lt;/code&gt; instead. This would come in handy in the next step.&lt;/li&gt;&lt;li&gt;Which was installing my favourite console font. Unfortunately, it doesn’t come preinstalled with the Gnome-based Ubuntu, but it was no big deal. The font is named console8x16 and it comes with Kubuntu’s (and KDE’s) default terminal emulator, Konsole. So I&amp;nbsp;downloaded &lt;a href='http://packages.ubuntu.com/hardy/konsole'&gt;an appropriate package&lt;/a&gt; (manually, without the help of APT, because all I&amp;nbsp;wanted was the font, not the package itself). I&amp;nbsp;then installed Midnight Commander (which I&amp;nbsp;use a&amp;nbsp;lot, if only for its great vfs feature, which allows to&amp;nbsp;access, inter alia, Debian/Ubuntu packages as if they were directories), grabbed the file &lt;code&gt;console8x16.pcf.gz&lt;/code&gt;, installed it in &lt;code&gt;/usr/share/fonts/X11/misc&lt;/code&gt;, changed to&amp;nbsp;that directory, ran &lt;code&gt;mkfontdir&lt;/code&gt; and &lt;code&gt;mkfontscale&lt;/code&gt;, logged out and restarted the X server.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The last step was to&amp;nbsp;use this font for Emacs, too. So I&amp;nbsp;installed Emacs, created the file &lt;code&gt;&amp;#126;/.Xdefaults&lt;/code&gt; containing the single line&lt;/p&gt;&lt;pre&gt;&lt;code class="nohighlight"&gt;Emacs&amp;#42;font: -misc-console-medium-r-normal--16-160-72-72-c-80-iso10646-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and ran &lt;code&gt;xrdb &amp;#126;/.Xdefaults&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Then I&amp;nbsp;got round to&amp;nbsp;configuring Emacs itself. But that’s a&amp;nbsp;story for another post.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-07:post:yavp</a:id>
<a:title>YAVP</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/07/yavp/"/>
<a:updated>2008-04-07T00:00:00Z</a:updated>
<a:content type="html">&lt;pre&gt;&lt;code class="nohighlight"&gt;Jezus, the high elven wizard, saved the world with his brave efforts and became a great ruler while saving himself 34 times.
He scored 24999532 points and advanced to level 50.
He survived for 0 years, 123 days, 0 hours, 11 minutes and 39 seconds &amp;#40;176207 turns&amp;#41;.
Jezus visited 127 places.
His strength score was modified by +26 during his career.
His learning score was modified by +17 during his career.
His willpower score was modified by +10 during his career.
His dexterity score was modified by +7 during his career.
His toughness score was modified by +25 during his career.
His charisma score was modified by +9 during his career.
His appearance score was modified by +6 during his career.
His mana score was modified by +13 during his career.
His perception score was modified by +15 during his career.
He was unnaturally aged by 76 years.
He was the champion of the arena.
He was a member of the thieves guild.
He made a little water dragon very happy.
He defeated the arch enemy of a mighty karmic wyrm.
He adhered to the principles of the Cat Lord and thus rose to great fame.
He saved Khelavaster from certain death.
He left the Drakalor Chain after completing his quest and became a great leader and famous hero.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yay! Now that I&amp;nbsp;have finished ADOM for the first time ever, after something like six years of trying, I&amp;nbsp;can finally get back to&amp;nbsp;work with peace of mind. :-)&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-06:post:tex-hackery</a:id>
<a:title>The TeX Hackery</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/06/tex-hackery/"/>
<a:updated>2008-04-06T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;After a&amp;nbsp;longish while of inactivity, I&amp;nbsp;finally got around to&amp;nbsp;finishing the draft spec of a&amp;nbsp;next-generation protocol for &lt;a href='http://poliqarp.sf.net/'&gt;Poliqarp&lt;/a&gt;, the be-all-end-all corpus concordance tool that I&amp;nbsp;maintain. The spec is being written in LaTeX, and it has a&amp;nbsp;number of subsections that describe particular methods of the protocol. Each one of those is further divided into sub-subsections that describe the method’s signature, purpose, syntax of request, syntax of response, and an optional example. I&amp;nbsp;thought to&amp;nbsp;write a&amp;nbsp;couple of macros to&amp;nbsp;help me separate the document’s logic from details of formatting, so that I&amp;nbsp;could say:&lt;/p&gt;&lt;pre&gt;&lt;code class="latex"&gt;\synopsis/&amp;#40;&amp;#41; -&amp;gt; {version : int; extensions : string&amp;#42;}/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and have it expanded into:&lt;/p&gt;&lt;pre&gt;&lt;code class="latex"&gt;\paragraph{Synopsis}
\verb/{version : int; extensions : string&amp;#42;}/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Being a&amp;nbsp;casual LaTeX user who hardly ever writes his own macros, I&amp;nbsp;first thought to&amp;nbsp;use LaTeX’s command-defining commands, &lt;code&gt;\newcommand&lt;/code&gt; and &lt;code&gt;\renewcommand&lt;/code&gt;. However, I&amp;nbsp;quickly ran into the limitation that the argument of commands defined in such a&amp;nbsp;way can only be delimited by curly braces, which I&amp;nbsp;could not use because they might appear in the argument itself.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;googled around and found that this limitation can be overcome by using &lt;code&gt;\def&lt;/code&gt; instead, which is not a&amp;nbsp;LaTeX macro but rather an incantation of plain TeX, and allows to&amp;nbsp;use arbitrary syntax for delimiting arguments. Having found that, my first shot was:&lt;/p&gt;&lt;pre&gt;&lt;code class="latex"&gt;\def\synopsis/#1/{\paragraph{Synopsis}\verb/#1/}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which, obviously enough, turned out not to&amp;nbsp;work, producing errors about &lt;code&gt;\verb&lt;/code&gt; ended by an end-of-line.&lt;/p&gt;&lt;p&gt;“What the heck?” I&amp;nbsp;thought, and resorted to&amp;nbsp;Google again, this time searching for tex macros expanding to&amp;nbsp;verb. This yielded an entry from some TeX FAQ, which basically states that the &lt;code&gt;\verb&lt;/code&gt; is a&amp;nbsp;“fragile” command, and as such it cannot appear in bodies of macros. Ook. So it can’t be done?&lt;/p&gt;&lt;p&gt;“But,” I&amp;nbsp;thought, “TeX is such a&amp;nbsp;flexible and powerful tool, there must be some way around this!” And, as it would turn out, there is. Yet more googling led me to&amp;nbsp;&lt;a href='http://groups.google.pl/group/comp.text.tex/browse_thread/thread/5bca05fb8865a9c2'&gt;this thread&lt;/a&gt; on comp.text.tex, where someone gives the following answer for a&amp;nbsp;similar question:&lt;/p&gt;&lt;pre&gt;&lt;code class="latex"&gt;\def\term#{ %
\afterassignment\Term \let\TErm= }%
\edef\Term{\noexpand\verb \string}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now this is overkill. Why in the world am I&amp;nbsp;forced to&amp;nbsp;stuff such incomprehensible hackery into my document just to&amp;nbsp;perform a&amp;nbsp;seemingly simple task?! Easy things should be easy — that’s one of the principles of good design.&lt;/p&gt;&lt;p&gt;Reluctantly, I&amp;nbsp;copied it over, and attempted to&amp;nbsp;adjust it to&amp;nbsp;my needs. After a&amp;nbsp;number of initial failed attempts, I&amp;nbsp;thought that I&amp;nbsp;might actually attempt to&amp;nbsp;understand what all these &lt;code&gt;\afterassignment&lt;/code&gt;’s, &lt;code&gt;\noexpand&lt;/code&gt;’s and &lt;code&gt;\edef&lt;/code&gt;’s are for, so I&amp;nbsp;downloaded the &lt;a href='http://www-cs-faculty.stanford.edu/~knuth/abcde.html'&gt;TeXbook&lt;/a&gt; and dived straight in.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;spent another fifteen minutes or so reading bits of it and trying to&amp;nbsp;understand tokens, macros, when they are expanded and when merely carried over, etc. But a&amp;nbsp;sparkle of thought made me replace the whole complicated thingy with a&amp;nbsp;simple snippet that actually worked.&lt;/p&gt;&lt;pre&gt;&lt;code class="latex"&gt;\def\synopsis{\paragraph{Synopsis}\verb}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That’s right. This superficially resembles a&amp;nbsp;C preprocessor macro, and works because I&amp;nbsp;was lucky enough to&amp;nbsp;have &lt;code&gt;\verb&lt;/code&gt; appear last in the definition, thus allowing the “arguments” of &lt;code&gt;\synopsis&lt;/code&gt; to&amp;nbsp;be specified just like arguments to&amp;nbsp;&lt;code&gt;\verb&lt;/code&gt; and fit at exactly right place. I’m almost certain that it does not always work this way, but for now it’ll suffice.&lt;/p&gt;&lt;p&gt;Oh well. TeX is undoubtedly a&amp;nbsp;fine piece of software that provides splendid results if used right. But I&amp;nbsp;can’t get over the impressions that there are a&amp;nbsp;great deal more idiosyncracies like this in it than in, say, Common Lisp, even though the latter’s heritage tracks back to&amp;nbsp;as early as 1958 and is a&amp;nbsp;whopping twenty years longer than TeX’s. (On the side note, as it turns out, someone has already written &lt;a href='http://www3.interscience.wiley.com/cgi-bin/abstract/98518913/ABSTRACT'&gt;a&amp;nbsp;Lisp-based preprocessor for TeX macros&lt;/a&gt;. Gotta check it out someday.)&lt;/p&gt;&lt;p&gt;As for the TeXbook itself: it is a&amp;nbsp;fine piece of documentation that I&amp;nbsp;will definitely have to&amp;nbsp;add to&amp;nbsp;my must-read list, though it admittedly has a&amp;nbsp;math-textbookish feel to&amp;nbsp;it. First, however, I&amp;nbsp;want to&amp;nbsp;finish “Shaman’s Crossing” by Robin Hobb (which I&amp;nbsp;will probably brag about in a&amp;nbsp;separate post once I’m finished with it) and tackle Christian Queinnec’s “Lisp in Small Pieces”.&lt;/p&gt;</a:content>
</a:entry>
<a:entry>
<a:id>tag:blog.danieljanus.pl,2008-04-04:post:introduction</a:id>
<a:title>Introduction</a:title>
<a:link href="http://blog.danieljanus.pl/2008/04/04/introduction/"/>
<a:updated>2008-04-04T00:00:00Z</a:updated>
<a:content type="html">&lt;p&gt;So, there. Inspired by the newly-started blogs of some of &lt;a href='http://www.joemonster.org/blog/pietshaq'&gt;my&lt;/a&gt; &lt;a href='http://jan.rychter.com/blog/'&gt;acquaintances&lt;/a&gt;, I&amp;nbsp;had this thought that I&amp;nbsp;might actually have a&amp;nbsp;word or two on a&amp;nbsp;number of subjects, and that it might even be worth sharing. And here I&amp;nbsp;am, typing this introductory entry in my Emacs.&lt;/p&gt;&lt;p&gt;I&amp;nbsp;guess the first thing one usually writes about in a&amp;nbsp;blog is introducing himself to&amp;nbsp;the public, so for those of you who have arrived here through some links on the Web and don’t know me, here goes. I&amp;nbsp;am a&amp;nbsp;23-year-old (soon to&amp;nbsp;be 24, though) programmer geek, living in Warsaw, Poland. In 2006, I&amp;nbsp;graduated from Warsaw University, where I&amp;nbsp;majored in computer science, and am now working full-time as a&amp;nbsp;senior software engineer at &lt;a href='http://www.sentivision.com/'&gt;Sentivision&lt;/a&gt;. I&amp;nbsp;have a&amp;nbsp;&lt;a href='http://danieljanus.pl/'&gt;homepage&lt;/a&gt; (currently in Polish only, though I&amp;nbsp;probably will translate it to&amp;nbsp;English some day). These days, I&amp;nbsp;tend to&amp;nbsp;use Common Lisp for most of my programming work, though I&amp;nbsp;also occassionally use Python, Ruby, C, Perl, OCaml, Haskell, Java, and a&amp;nbsp;handful of other languages.&lt;/p&gt;&lt;p&gt;This is going to&amp;nbsp;be a&amp;nbsp;blog about my personal interests. This means mostly programming, with a&amp;nbsp;fair share of posts about books, poetry, Scrabble, music, biking, cats, and a&amp;nbsp;bunch of other topics thrown in. The new entries will most likely be added irregularly, whenever I&amp;nbsp;feel like sharing a&amp;nbsp;thought. My mother tongue is Polish, but I&amp;nbsp;will try to&amp;nbsp;maintain this blog in English just to&amp;nbsp;polish up my English writing skills (no pun intended) and for greater worldwide understandability.&lt;/p&gt;&lt;p&gt;As you might have noticed, there is no possibility of leaving comments. This is a&amp;nbsp;side-effect of the fact that this blog is, technically, just a&amp;nbsp;bunch of static HTML pages (automatically generated with Blosxom), and is in line with my idea of blog comments: I&amp;nbsp;view them as a&amp;nbsp;way of providing direct feedback to&amp;nbsp;the author, not as a&amp;nbsp;publically available message board with discussions having a&amp;nbsp;heavy tendency to&amp;nbsp;drift off topic. So, should you like to&amp;nbsp;comment on some post, feel free to&amp;nbsp;drop me an email; I’ll be happy to&amp;nbsp;respond to&amp;nbsp;interesting mails in the blog. I&amp;nbsp;can be contacted at dj at danieljanus dot pl.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Update 2010-Jan-17&lt;/i&gt;: Several things have changed —– in particular, Sentivision doesn’t exist anymore — but I&amp;nbsp;haven’t done any editing in this post other than updating the links.&lt;/p&gt;</a:content>
</a:entry>
</a:feed>
* Trying 212.47.254.231...
* TCP_NODELAY set
* Connected to blog.danieljanus.pl (212.47.254.231) port 80 (#0)
> GET /atom.xml HTTP/1.1
> Host: blog.danieljanus.pl
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.4.6 (Ubuntu)
< Date: Wed, 22 Jan 2020 06:52:23 GMT
< Content-Type: text/xml
< Content-Length: 249013
< Last-Modified: Tue, 21 Jan 2020 21:19:01 GMT
< Connection: keep-alive
< ETag: "5e276ac5-3ccb5"
< Accept-Ranges: bytes
<
{ [1152 bytes data]
* Connection #0 to host blog.danieljanus.pl left intact
* Closing connection 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment