<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://dominik.honnef.co/</id>
  <title>Dominik Honnef</title>
  <updated>2013-03-11T08:39:35Z</updated>
  <link rel="alternate" href="http://dominik.honnef.co/"/>
  <link rel="self" href="http://dominik.honnef.co/atom.xml"/>
  <author>
    <name>Dominik Honnef</name>
    <uri>http://dominik.honnef.co</uri>
  </author>
  <entry>
    <id>tag:dominik.honnef.co,2013-03-11:/posts/2013/03/writing_go_in_emacs/</id>
    <title type="html">Writing Go in Emacs</title>
    <published>2013-03-11T08:39:35Z</published>
    <updated>2013-03-11T08:39:35Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2013/03/writing_go_in_emacs/"/>
    <content type="html">&lt;p&gt;Using the right tools plays a big role in getting your job done
efficiently. In the case of programming Go, most of your time will be
spent in an editor. It is therefore key that your editor doesn’t get
in your way and, optimally, assists you wherever it can.&lt;/p&gt;

&lt;p&gt;In this article, I will talk about go-mode for Emacs, its history and
features, as well as useful extensions to it.&lt;/p&gt;

&lt;p&gt;Even though this article is targeted at Emacs users, parts of it,
mainly the feature list, might be of interest to users of other
editors as well, to see what’s possible and to adopt some of the
ideas. You will want to skip the &lt;em&gt;History&lt;/em&gt; and &lt;em&gt;Obtaining it&lt;/em&gt; sections
though.&lt;/p&gt;

&lt;h3 id="history-of-go-mode"&gt;History of go-mode&lt;/h3&gt;

&lt;p&gt;Go has been including a mode for Emacs for a long time now. Until
recently, however, it was rather fragile. It regularly messed up
indentation or syntax highlighting, for quite some time it could
completely lock up your editor and it didn’t feel really integrated in
Emacs, lacking support for functions like &lt;code&gt;beginning-of-defun&lt;/code&gt;. It
also didn’t include a lot of extra features.&lt;/p&gt;

&lt;p&gt;All in all, it was better than having to use nano, but not by much.&lt;/p&gt;

&lt;p&gt;All that changed around February this year, when I rewrote the mode
from scratch. I took special care to build it on top of a solid
foundation, making use of Emacs’s parsing facilities, as opposed to
the previous version of the mode, which implemented its own parser.
Apart from generally bug-free behavior, this also allowed building a
lot of functions on top of it.&lt;/p&gt;

&lt;h3 id="obtaining-it"&gt;Obtaining it&lt;/h3&gt;

&lt;p&gt;There are two ways of obtaining go-mode and both are very similar. The
first way is using the one that comes with the
&lt;a href="http://tip.golang.org/misc/emacs/"&gt;Go distribution itself&lt;/a&gt;, the
second way is to get it from
&lt;a href="https://github.com/dominikh/go-mode.el"&gt;GitHub&lt;/a&gt;, where I push all new
changes before they find their way into the Go repository.&lt;/p&gt;

&lt;p&gt;When using the one that comes bundled with Go, be sure to use the one
that comes with &lt;em&gt;tip&lt;/em&gt;, the development version of Go. The current
release, 1.0.3, includes the old, outdated version of go-mode.&lt;/p&gt;

&lt;h4 id="installation"&gt;Installation&lt;/h4&gt;

&lt;p&gt;If using go-mode from Go tip, put both &lt;code&gt;go-mode.el&lt;/code&gt; and &lt;code&gt;go-mode-load.el&lt;/code&gt;
into a directory of your choice, add it to Emacs’s load paths via&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-to-list&lt;/span&gt; &lt;span class="ss"&gt;'load-path&lt;/span&gt; &lt;span class="s"&gt;"/place/where/you/put/it"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and require it via&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="ss"&gt;'go-mode-load&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will install autoload entries and associate &lt;code&gt;*.go&lt;/code&gt; files with
go-mode.&lt;/p&gt;

&lt;p&gt;If using go-mode from the git repository, the procedure is similar,
but requires an additional step to generate the &lt;code&gt;go-mode-load.el&lt;/code&gt;
file. From within Emacs, run &lt;code&gt;M-x update-file-autoloads&lt;/code&gt;, point it at
the &lt;code&gt;go-mode.el&lt;/code&gt; file and tell it to generate a &lt;code&gt;go-mode-load.el&lt;/code&gt; file.
From that point on the procedure is the same as before.&lt;/p&gt;

&lt;h3 id="features"&gt;Features&lt;/h3&gt;

&lt;p&gt;For Emacs, a programming mode is often about more than just
indentation and syntax highlighting. Integration with the tools of the
language is often key, easy navigation of code, even crossing package
boundaries, is appreciated and some people even rely on on-the-fly
syntax checking.&lt;/p&gt;

&lt;p&gt;go-mode, either directly or by using the work of others, offers all of
this and more.&lt;/p&gt;

&lt;p&gt;We’ll discover how to read documentation, format and navigate code,
how to use Go’s own pastebin, how to get syntax checking, autocompletion and snippets.&lt;/p&gt;

&lt;h4 id="reading-documentation"&gt;Reading documentation&lt;/h4&gt;

&lt;p&gt;Using the &lt;code&gt;godoc&lt;/code&gt; function, you can invoke the identically named Go
tool from within Emacs and read package documentation in a view-mode
buffer. Additional feature: You can tab complete import paths.&lt;/p&gt;

&lt;h4 id="formatting-code"&gt;Formatting code&lt;/h4&gt;

&lt;p&gt;Maybe one of the most important tools of Go is &lt;em&gt;gofmt&lt;/em&gt;, which
automatically formats your code to the one true coding style, used by
every Go developer.&lt;/p&gt;

&lt;p&gt;In Emacs, there are two ways to use &lt;em&gt;gofmt&lt;/em&gt;. One way is to invoke
&lt;em&gt;gofmt&lt;/em&gt; manually with the identically named function &lt;code&gt;gofmt&lt;/code&gt;, which
will patch the current buffer according to gofmt. The other way is to
use a before-save-hook to run &lt;code&gt;gofmt&lt;/code&gt; every time you save a Go buffer.
Enabling that hook is as easy as doing&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'before-save-hook&lt;/span&gt; &lt;span class="ss"&gt;'gofmt-before-save&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have used this hook before and complained about your cursor
jumping around, don’t worry: This has been fixed in the new go-mode.
At the very most, your cursor will be placed on the beginning of the
current line, if it had to be reformatted.&lt;/p&gt;

&lt;h4 id="managing-imports"&gt;Managing imports&lt;/h4&gt;

&lt;p&gt;On a first glance, managing imports in Go doesn’t seem like much of a
deal. You either add import statements at the top of your file or you
remove them. But when rapidly developing a new application, this can
cause a lot of jumping around. Did you just realize that you forgot to
import the fmt package? Previously, this meant going to the beginning
of the buffer, advancing to the block of import statements (if it
existed yet), going to its end and adding your new import. And when
you realized you didn’t need it after all, you had to repeat the same
procedure to remove it again.&lt;/p&gt;

&lt;p&gt;The new go-mode has three functions for working with imports:
&lt;code&gt;go-import-add&lt;/code&gt;, &lt;code&gt;go-remove-unused-imports&lt;/code&gt; and &lt;code&gt;go-goto-imports&lt;/code&gt;.&lt;/p&gt;

&lt;h5 id="go-import-add"&gt;go-import-add&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;go-import-add&lt;/code&gt;, bound to &lt;code&gt;C-c C-a&lt;/code&gt; by default, will prompt you for an
import path (again supporting tab completion) and insert it in the
import block, creating it if necessary. If an import already existed
but was commented, it will be uncommented.&lt;/p&gt;

&lt;p&gt;If prefixed with &lt;code&gt;C-u&lt;/code&gt;, it will ask you for an alias, too. An annoying
procedure of moving around and mental context switching has just been
reduced to a keystroke.&lt;/p&gt;

&lt;h5 id="go-remove-unused-imports"&gt;go-remove-unused-imports&lt;/h5&gt;

&lt;p&gt;Instead of offering a function for removing a single import, go-mode
will detect all unused imports and delete them (or comment them) once
you run &lt;code&gt;go-remove-unused-imports&lt;/code&gt;. It is not bound to a key by
default, but you can bind it yourself if you want to. Personally I
have bound it to &lt;code&gt;C-c C-r&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'go-mode-hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;local-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-c C-r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'go-remove-unused-imports&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id="go-goto-imports"&gt;go-goto-imports&lt;/h5&gt;

&lt;p&gt;If you decide you want to look at your imports or edit them manually,
go-goto-imports will take you to them automatically, placing your
cursor after the last import. It isn’t bound to a key, either, mainly
because I couldn’t come up with a good default that didn’t violate
Emacs guidelines. But you can bind it manually, just like before:&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'go-mode-hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;local-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="s"&gt;"C-c i"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'go-goto-imports&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="navigating-code"&gt;Navigating code&lt;/h4&gt;

&lt;p&gt;Also important for efficient programming is quick navigation of code.
&lt;code&gt;go-goto-imports&lt;/code&gt; was only the tip of the iceberg.&lt;/p&gt;

&lt;p&gt;go-mode supports &lt;code&gt;beginning-of-defun&lt;/code&gt; (&lt;code&gt;C-M-a&lt;/code&gt;) and &lt;code&gt;end-of-defun&lt;/code&gt;
(&lt;code&gt;C-M-e&lt;/code&gt;), two core Emacs functions for navigating between functions.
Additionally, functions such as &lt;code&gt;narrow-to-defun&lt;/code&gt; and &lt;code&gt;mark-defun&lt;/code&gt;
rely on these two functions.&lt;/p&gt;

&lt;p&gt;If that isn’t enough, you can also use
&lt;a href="http://emacswiki.org/emacs/ImenuMode"&gt;Imenu&lt;/a&gt; to jump to specific
function or type declarations.&lt;/p&gt;

&lt;p&gt;Even if you long for a feature that’s usually only provided by IDEs,
or by making use of etags, namely jumping to the declaration of a
symbol under your cursor, go-mode got you covered.&lt;/p&gt;

&lt;p&gt;go-mode integrates with
&lt;a href="https://code.google.com/p/rog-go/source/browse/exp/cmd/godef/"&gt;godef&lt;/a&gt;,
an amazing little tool written by
&lt;a href="https://twitter.com/rogpeppe"&gt;Roger Peppe&lt;/a&gt;. godef is able to parse
your code, and the code of other packages, and the code of the Go
standard library, and can tell you what exactly the symbol you’re
looking at means and where it has been defined.&lt;/p&gt;

&lt;p&gt;go-mode makes use of this to provide the two functions
&lt;code&gt;godef-describe&lt;/code&gt; and &lt;code&gt;godef-jump&lt;/code&gt;. &lt;code&gt;godef-describe&lt;/code&gt; will tell you what
you’re looking at, while &lt;code&gt;godef-jump&lt;/code&gt; will take you to its definition.
And yes, this works across files, packages and into the standard
library, without needing any tags. And it has almost no measurable
delay.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;godef-describe&lt;/code&gt; is bound to &lt;code&gt;C-c C-d&lt;/code&gt; and &lt;code&gt;godef-jump&lt;/code&gt; is bound to
&lt;code&gt;C-c C-j&lt;/code&gt;. If you want to, you can bind &lt;code&gt;godef-jump&lt;/code&gt; to &lt;code&gt;M-.&lt;/code&gt;, which
is the default key for &lt;code&gt;find-tag&lt;/code&gt;, something you might already be
using for other programming languages:&lt;/p&gt;

&lt;pre class="cl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;'go-mode-hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
                          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;local-set-key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;kbd&lt;/span&gt; &lt;span class="nv"&gt;\"M-.\"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ss"&gt;'godef-jump&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are two important notes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Update (2013-03-19): The godef features in go-mode are now part
of the Go repository.&lt;/strong&gt; As of writing this article, the godef
functions haven’t reached the Go repository yet. They are only
available in the git version. This will hopefully change in the next
couple of days.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You will obviously need to install godef, which is as easy as doing
&lt;code&gt;go get code.google.com/p/rog-go/exp/cmd/godef&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;video controls=""&gt;
  &lt;source src="/video/go_emacs/godef_mp4.mp4" type="video/mp4"&gt;&lt;/source&gt;
  &lt;source src="/video/go_emacs/godef_ogg.ogg" type="video/ogg"&gt;&lt;/source&gt;
  Your browser does not support the video tag.
&lt;/video&gt;

&lt;h4 id="interacting-with-the-playground"&gt;Interacting with the Playground&lt;/h4&gt;

&lt;p&gt;Go has its own pastebin, called the
&lt;a href="http://play.golang.org/"&gt;Playground&lt;/a&gt;. When asking for help with code,
or sharing solutions to those who need help, it is often expected to
use the Playground, especially because it can execute code.&lt;/p&gt;

&lt;p&gt;It makes sense that go-mode integrates with the Playground. It offers
&lt;code&gt;go-play-buffer&lt;/code&gt; and &lt;code&gt;go-play-region&lt;/code&gt; to send the current buffer or
region to the Playground and store a link in your kill ring.&lt;/p&gt;

&lt;p&gt;It can also directly download a paste from the Playground into Emacs,
by using &lt;code&gt;go-download-play&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id="on-the-fly-syntax-checking"&gt;On-the-fly syntax checking&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www.emacswiki.org/emacs/FlyMake"&gt;FlyMake&lt;/a&gt; is Emacs’s solution
to on-the-fly syntax checking. Many programming modes offer support
for it (some more easily than others).&lt;/p&gt;

&lt;p&gt;
  &lt;img src="/img/go_emacs/goflymake.png" alt="Screenshot of goflymake" /&gt;
&lt;/p&gt;

&lt;p&gt;In the case of Go,
&lt;a href="https://twitter.com/dougmaceachern"&gt;Doug MacEachern&lt;/a&gt; wrote
&lt;a href="https://github.com/dougm/goflymake"&gt;goflymake&lt;/a&gt;, which consists of a
small Go binary and some elisp to integrate it with Emacs. Because Go
compiles blazingly fast, using goflymake doesn’t cause any performance
penalties. Personally I am letting FlyMake compile my Go buffers every
time I insert a newline. More conservative settings would compile
after a certain amount of idle time, or when saving the buffer.&lt;/p&gt;

&lt;h4 id="autocompletion"&gt;Autocompletion&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/nsf/gocode"&gt;gocode&lt;/a&gt;, written by
&lt;a href="https://github.com/nsf"&gt;nsf&lt;/a&gt;, provides the kind of autocompletion
that you might know from IDEs. It provides context-sensitive
autocompletion and works across a variety of editors, including Emacs.
The project’s README includes detailed installation instructions.&lt;/p&gt;

&lt;p&gt;Note: it suggests using auto-complete-mode and mentions company-mode
as an alternative. Personally I recommend trying company-mode first.
auto-complete-mode isn’t as lightweight and can be harder to
configure.&lt;/p&gt;

&lt;p&gt;
  &lt;img src="/img/go_emacs/gocode.png" alt="Screenshot of gocode" /&gt;
&lt;/p&gt;

&lt;h4 id="snippets"&gt;Snippets&lt;/h4&gt;

&lt;p&gt;Some people like them, some think they’re useless: Snippets. Short
words that, upon pressing TAB, turn into longer words, sentences or
code constructs. One of the more popular implementations of snippets
for Emacs is &lt;a href="https://github.com/capitaomorte/yasnippet"&gt;YASnippet&lt;/a&gt;,
and it is YASnippet that I wrote a
&lt;a href="https://github.com/dominikh/yasnippet-go/tree/master/go-mode"&gt;small number of Go snippets&lt;/a&gt;
for.&lt;/p&gt;

&lt;h4 id="finding-unchecked-errors-with-go-errcheck"&gt;Finding unchecked errors with go-errcheck&lt;/h4&gt;

&lt;p&gt;Last but not least, there’s
&lt;a href="https://github.com/dominikh/go-errcheck.el"&gt;go-errcheck&lt;/a&gt;, offering
Emacs integration for &lt;a href="https://github.com/kisielk/errcheck"&gt;errcheck&lt;/a&gt;.
errcheck is a tool written by
&lt;a href="http://www.kamilkisiel.net/"&gt;Kamil Kisiel&lt;/a&gt; for finding and reporting
unchecked errors in your Go code.&lt;/p&gt;

&lt;p&gt;
  &lt;img src="/img/go_emacs/go-errcheck.png" alt="Screenshot of go-errcheck" /&gt;
&lt;/p&gt;

&lt;p&gt;go-errcheck offers the &lt;code&gt;go-errcheck&lt;/code&gt; function, which will run errcheck
on the current package and report errors in a compilation buffer.
Additionally, it supports setting errcheck flags on a default and
per-package basis.&lt;/p&gt;

&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;I hope I was able to give you a good overview of the features that you
can enjoy while writing Go code in Emacs. If I forgot any cool
packages, or if you have suggestions or comments, please leave me a
message. Check the &lt;a href="/contact/"&gt;contact page&lt;/a&gt; to find ways of
contacting me.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2012-12-05:/posts/2012/12/go__on_implicit_type_conversions__type_identity_and_a_little_gotcha/</id>
    <title type="html">Go: On implicit type conversions, type identity and a little gotcha</title>
    <published>2012-12-05T22:08:35Z</published>
    <updated>2012-12-05T22:08:35Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2012/12/go__on_implicit_type_conversions__type_identity_and_a_little_gotcha/"/>
    <content type="html">&lt;p&gt;A well known design decision in the Go programming language is the
absence of implicit type conversions. An &lt;code&gt;int&lt;/code&gt; is always an &lt;code&gt;int&lt;/code&gt; and not
an &lt;code&gt;int32&lt;/code&gt; and certainly not a &lt;code&gt;float&lt;/code&gt;. And a &lt;code&gt;net.IP&lt;/code&gt; is not a &lt;code&gt;[]byte&lt;/code&gt;… or
is it?&lt;/p&gt;

&lt;p&gt;Knowing only the “no implicit type conversions” principle, the
&lt;a href="http://play.golang.org/p/xNBc9evi96"&gt;following code&lt;/a&gt; should not compile:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But it does! Now, the definition of &lt;code&gt;net.IP&lt;/code&gt; is &lt;code&gt;type IP []byte&lt;/code&gt;, but we
also know that this should be an entirely new type and not an alias,
because Go doesn’t have type aliases, either. So why does this compile
and execute properly?&lt;/p&gt;

&lt;p&gt;The secret lies in Go’s understanding of
&lt;a href="http://golang.org/ref/spec#Type_identity"&gt;type identity&lt;/a&gt; and
&lt;a href="http://golang.org/ref/spec#Assignability"&gt;assignability&lt;/a&gt;. The
following part is of special importance:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A value x is assignable to a variable of type T (“x is assignable to T”) in any of these cases:&lt;/p&gt;

  &lt;p&gt;[…]&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;x’s type V and T have identical underlying types and at least one of V or T is not a named type.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;And in our case, &lt;code&gt;[]byte&lt;/code&gt; is not a named type (unlike &lt;code&gt;byte&lt;/code&gt; or
&lt;code&gt;net.IP&lt;/code&gt;, which are), which means that values of type &lt;code&gt;net.IP&lt;/code&gt; and
&lt;code&gt;[]byte&lt;/code&gt; can be freely assigned to each other. And of course the same
applies to all other identical scenarios, &lt;code&gt;net.IP&lt;/code&gt; and &lt;code&gt;[]byte&lt;/code&gt; are
just examples.&lt;/p&gt;

&lt;p&gt;The remaining question is: Why did they add this special case to the
language specification? Go is not a language of odd exceptions, but at
first glance, this exception does seem very odd. The only sensible
explanation I came across are function types. Consider the &lt;a href="http://play.golang.org/p/r6ivafqGwr"&gt;following
code&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BinaryOp&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;BinaryOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If &lt;code&gt;BinaryOp&lt;/code&gt; (a named type) and &lt;code&gt;func(int, int) int&lt;/code&gt; (an unnamed
type) weren’t identical, writing anonymous functions would be
&lt;a href="http://play.golang.org/p/RTit2DS_TG"&gt;quite a bit uglier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I don’t know if the initial example, identity of named and unnamed
slice types, was intentional or an accident caused by an overly broad
specification, but I’d recommend not making use of it and sticking to
explicit conversions, even if they’re not necessary. Clarity of code
trumps saving a few keystrokes.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2012-04-16:/posts/2012/04/dealing_with_encodings_in_go/</id>
    <title type="html">Dealing with encodings in Go</title>
    <published>2012-04-16T15:31:41Z</published>
    <updated>2012-04-16T15:31:41Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2012/04/dealing_with_encodings_in_go/"/>
    <content type="html">&lt;p&gt;One not well documented aspect of Go is how it handles string
encodings, or how strings are actually treated internally. This
article tries to shed some light on basic aspects of that, to get you
started.&lt;/p&gt;

&lt;h3 id="its-all-utf-8-right"&gt;It’s all UTF-8, right?&lt;/h3&gt;

&lt;p&gt;A source of confusion is the fact that Go &lt;strong&gt;source code&lt;/strong&gt; has to be
encoded in UTF-8, meaning that string literals, variable/function
names etc. most consist solely of UTF-8 code points. This does,
however, not mean that strings in Go must only contain valid UTF-8
data. For example, the following string literal is okay to use, even
though it does not describe a valid UTF-8 string: &lt;code&gt;"Hello,
\x90\xA2\x8A\x45"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In fact, the string datatype is effectively nothing more than an
immutable byte array. This also means that using the index operator
will return a specific byte, not a &lt;a href="http://en.wikipedia.org/wiki/Code_point"&gt;rune&lt;/a&gt;:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0x%x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"世界"&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 0xb8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Furthermore, the &lt;code&gt;len()&lt;/code&gt; function will also return a string’s length in
bytes, not runes:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, 世界"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="but-isnt-go-aware-of-utf-8"&gt;But isn’t Go aware of UTF-8?&lt;/h3&gt;

&lt;p&gt;Even though strings are mere byte arrays, Go does have proper support
for UTF-8. For example the &lt;code&gt;range&lt;/code&gt; operator will iterate over a string
by yielding runes, instead of bytes:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello, 世界"&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%c "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; H e l l o ,   世 界&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And by importing the &lt;code&gt;unicode/utf8&lt;/code&gt; package, it is also possible to
validate strings, or more importantly, get their rune count (which
effectively can be compared to the string’s length as we’d interpret
it):&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello, 世界"&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuneCountInString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 9&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="and-how-do-i-deal-with-other-encodings"&gt;And how do I deal with other encodings?&lt;/h3&gt;

&lt;p&gt;Even though Go has good support for UTF-8 (and minimal support for
UTF-16), it has no built-in support for any other encoding. If you
have to use other encodings (e.g. when dealing with user input), you
have to use third party packages, like for example &lt;a href="http://code.google.com/p/go-charset/"&gt;go-charset&lt;/a&gt;.
go-charset makes it quite easy to convert between different string
encodings.&lt;/p&gt;

&lt;p&gt;If you want to further work with input data, the best idea is to first
convert it to UTF-8 and then use Go’s built-in features:&lt;/p&gt;

&lt;pre class="go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"code.google.com/p/go-charset/charset"&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"io/ioutil"&lt;/span&gt;
  &lt;span class="s"&gt;"strings"&lt;/span&gt;
  &lt;span class="s"&gt;"unicode/utf8"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"code.google.com/p/go-charset/data"&lt;/span&gt; &lt;span class="c1"&gt;// include the conversion maps in the binary&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello, \x90\xA2\x8A\x45"&lt;/span&gt; &lt;span class="c1"&gt;// CP932 encoded version of "Hello, 世界"&lt;/span&gt;

  &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;charset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CP932"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// convert from CP932 to UTF-8&lt;/span&gt;
  &lt;span class="n"&gt;s2_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                         &lt;span class="c1"&gt;// =&amp;gt; Hello, 世界&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;                    &lt;span class="c1"&gt;// =&amp;gt; 13&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuneCountInString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 9&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Even though this article is rather short, I hope that it was able to
convey the following main points:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Strings in Go are mere byte arrays&lt;/li&gt;
  &lt;li&gt;There is built-in functionality for dealing with UTF-8&lt;/li&gt;
  &lt;li&gt;Any other encoding is best converted to UTF-8 first&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For further reading, I recommend &lt;a href="https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/1yL7IsqADSw"&gt;a discussion on the Go mailing list&lt;/a&gt;,
which also sheds light on why strings behave the way they do (hint:
it’s mostly about performance, and freedom).&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2012-03-28:/posts/2012/03/breaking_backwards_compatibility_in_good_conscience/</id>
    <title type="html">Breaking backwards compatibility in good conscience</title>
    <published>2012-03-28T10:57:31Z</published>
    <updated>2012-03-28T10:57:31Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2012/03/breaking_backwards_compatibility_in_good_conscience/"/>
    <content type="html">&lt;p&gt;A couple of days ago I released Cinch 2.0 – version 2.0 of the
most-used IRC library written in Ruby. The purpose of this article,
however, is not to talk about all the new features and improvements in
Cinch (check the &lt;a href="http://bit.ly/GLoXVP"&gt;changelog&lt;/a&gt; if you’re curious) but why it
breaks backwards compatibility and how that’s not a bad thing.&lt;/p&gt;

&lt;p&gt;The Ruby community basically has two main camps: Those who think that
breaking backwards compatibility is no problem, as long as your
version numbers signalise it (c.f. &lt;a href="http://semver.org/"&gt;Semantic Versioning&lt;/a&gt;), and
those who think that breaking backwards compatibility is proof of bad
API design and should be avoided at all costs.&lt;/p&gt;

&lt;p&gt;Loren Segal, creator of &lt;a href="http://yardoc.org/"&gt;YARD&lt;/a&gt;, belongs to the latter camp.
Notably, the current version of YARD (0.7.5 as of writing) is still
compatible with the earliest releases. According to him, he still uses
the same plugins and templates that he wrote for version 0.2.x,
released roughly 4 years ago.&lt;/p&gt;

&lt;p&gt;He says that this is possible because he put a lot of thought into the
API, planning &lt;em&gt;before&lt;/em&gt; writing code. While I agree that maintaining
backwards compatibility is a noble cause, and that planning &lt;em&gt;can&lt;/em&gt;
help, I don’t think that everything can be planned perfectly. I think
that Loren accomplished a great feat by planning the API in such a
solid way that it worked out for him, but it might not for others, and
it might not be a sign of bad will.&lt;/p&gt;

&lt;p&gt;I myself put quite some thought into the API of Cinch before releasing
version 1.0 – I tried to consider as many scenarios as possible,
planning ahead and avoiding future conflicts. And I failed. Cinch was
my first IRC library with focus on writing multithreaded bots, and
while I tried to get everything right, I overlooked many little
details. Details that only became apparent when users came to me,
pointing out problems they were having.&lt;/p&gt;

&lt;p&gt;While I could’ve maintained &lt;em&gt;some&lt;/em&gt; parts of the flawed API in version
2.0, other parts had to be removed completely because they were plain
broken and unfixable. And I didn’t want to maintain the flawed parts,
either. Why? Because they added unnecessary complexity to the code
base of Cinch, and because on the long run it won’t matter. Cinch is
now 1.5 years old and it will be around for much longer. In a couple
of years, nobody will care that the API changed. In fact it will
probably not take more than a couple of months.&lt;/p&gt;

&lt;p&gt;My point is that it’s a good idea to try and avoid breaking the API,
but only as long as it makes sense and as long as it doesn’t have a
negative effect on your code, or the rest of the API, in the long run.
And if you’ve made a mistake while designing the API, it is better to
admit the mistake and fix it than to live with it for the rest of your
project’s life.&lt;/p&gt;

&lt;p&gt;Everyone who has taken a look at the &lt;a href="https://github.com/lsegal/yard"&gt;code base of YARD&lt;/a&gt;
knows that it indeed has been designed very well, but I think this is
an exceptional case and not the norm and it shouldn’t be assumed that
everyone can achieve the same. Maybe it was even a bit of luck that it
worked out so well.&lt;/p&gt;

&lt;p&gt;Of course this isn’t a free ticket for breaking APIs every second
release, either. If you have to constantly break backwards
compatibility, maybe you should put at least &lt;strong&gt;some&lt;/strong&gt; thought into
design first.&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-10-29:/posts/2011/10/linux_raid___dm_crypt__poor_write_performance/</id>
    <title type="html">Linux RAID + dm-crypt: Poor write performance</title>
    <published>2011-10-28T23:41:47Z</published>
    <updated>2011-10-28T23:41:47Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/10/linux_raid___dm_crypt__poor_write_performance/"/>
    <content type="html">&lt;p&gt;I’ve been running a RAID 6 with four active disks for quite some time
now, and performance always seemed adequate, achieving about 230MB/s
read and 90MB/s write (obviously in rather artifical tests using dd;
actual file operations might vary).&lt;/p&gt;

&lt;p&gt;Now it occured to me, that encrypting my data might actually be a good
idea, so I looked into cryptsetup for adding encryption on top of my
RAID, using LUKS. Now, anyone familiar with RAIDs should know that
alignment is key to proper performance. cryptsetup offers an option
called &lt;code&gt;--align-payload&lt;/code&gt; to align data at a multiple of 512 bytes.
Based on the chunk size I am using (512KB) and the number of disks,
2048 seemed to be the right value for the setting.&lt;/p&gt;

&lt;p&gt;Weirdly enough, though, it didn’t matter what value I used: 2048,
1024, none at all or completely arbitrary values: Write performance
would always suffer and be around 30MB/s, with my CPU being almost
idle. I spent hours trying to figure out what I might’ve been doing
wrong, why the option wasn’t having any effect and so on, until I
found an aligning-unrelated setting called &lt;code&gt;stripe_cache_size&lt;/code&gt;, which
defaults to 256 on many systems, mine including. After setting that
option to a higher value of 8192, my write speeds rocketed up to
190MB/s for both plain md0 as well as the encrypted device.&lt;/p&gt;

&lt;p&gt;The option can be set by simply writing a value to
&lt;code&gt;/sys/block/&amp;lt;your_md_device&amp;gt;/md/stripe_cache_size&lt;/code&gt;, so for example: &lt;code&gt;echo
8192 &amp;gt; /sys/block/md0/md/stripe_cache_size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please be aware that the setting describes the number of pages to
cache, so a higher value will consume more memory.&lt;/p&gt;

&lt;p&gt;Also note that I did not rely on the speed output of dd but instead used
nmon, to avoid getting higher speeds caused by buffers. In fact, the
system will continue writing data while dd already thinks it is done.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-08-25:/posts/2011/08/electronics__my_first_experiences_with_various_shops/</id>
    <title type="html">Electronics: My first experiences with various shops</title>
    <published>2011-08-25T14:53:02Z</published>
    <updated>2011-08-25T14:53:02Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/08/electronics__my_first_experiences_with_various_shops/"/>
    <content type="html">&lt;p class="preface"&gt;This is part three of a series of me describing my new experiences with
electronics.&lt;/p&gt;

&lt;p&gt;First of all, sorry for the late third article, but ever since I
received my Arduino I was really busy playing around with it.&lt;/p&gt;

&lt;p&gt;Quite a bit has happened since my last article and I will try to catch
up as quickly as possible. One thing that happened is that I had to
order quite a bit more tools and components than I initially thought.&lt;/p&gt;

&lt;p&gt;In this article I will concentrate on my experiences with the various
shops I’ve ordered from so far and how they performed.&lt;/p&gt;

&lt;h2 id="baustelnde"&gt;bausteln.de&lt;/h2&gt;

&lt;p&gt;I ordered my Arduino starter kit from bausteln and they were quick to
send me a package. Everything was well packaged, nothing was missing
and they even included a neat little plastic box for storage.&lt;/p&gt;

&lt;p&gt;There was, however, a little problem: The included breadboard is
about half the size of the one depicted in images. Now, I know that
relying on images is my fault, and the article description didn’t
include any measurements, either, so I really shouldn’t have expected
a breadboard of a specific size.&lt;/p&gt;

&lt;p&gt;But my problem isn’t really with the small breadboard (even twice the
size would still be too small for any serious work) but the fact that
I’ve tried to contact the owner of the shop (it’s a single person) and
never got a reply. I’ve also tried to write a product review to warn
potential new customers, but said review has to be accepted by the
shop owner and he never did.&lt;/p&gt;

&lt;p&gt;I do not know if he simply doesn’t care or just missed the messages,
but I do not feel comfortable doing business with someone who cannot
even reply to emails or monitor his shop.&lt;/p&gt;

&lt;h2 id="futurlec"&gt;Futurlec&lt;/h2&gt;

&lt;p&gt;Packages from Hong Kong take a long time… Three weeks to be exact,
at least if you live in Germany. But obviously &lt;a href="http://www.futurlec.com/"&gt;Futurlec&lt;/a&gt; is
not to blame nor did I expect any faster shipping.&lt;/p&gt;

&lt;p&gt;I was, however, honestly surprised about their quality. Everything was
packaged well, components were new, nothing was bent, nothing was
broken and nothing was missing.&lt;/p&gt;

&lt;p&gt;As you might remember, I ordered a couple of “value packs” from
Futurlec. Basically bags full of discrete components of different
sizes/values. What I expected was one big bag per component type, full
of stuff, unsorted and with bent legs. I was surprised to see that
each value had its very own small bag, properly labelled as well.&lt;/p&gt;

&lt;p&gt;Should I ever have to buy components in bulk again, I will definitely
consider Futurlec a second time.&lt;/p&gt;

&lt;h2 id="reichelt"&gt;Reichelt&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.reichelt.de/"&gt;Reichelt&lt;/a&gt; is a German electronics store, selling everything
from components to tools and gadgets. Unlike other German competitors
like Conrad, Reichelt has cheap prices and doesn’t completely ignore
the hobbyist/maker market.&lt;/p&gt;

&lt;p&gt;So far I made two purchases, mostly containing soldering equipment,
but also a few ICs and more importantly a big breadboard. Both
packages arrived fast (within 1-2 days).&lt;/p&gt;

&lt;p&gt;Everything was packaged well, everything worked properly, I am happy.&lt;/p&gt;

&lt;h2 id="pollin"&gt;Pollin&lt;/h2&gt;

&lt;p&gt;The 4th shop I ordered from is &lt;a href="http://www.pollin.de/shop/index.html"&gt;Pollin&lt;/a&gt;, another German store.
They’re kind of an electronics store, but they concentrate mostly on
buying and selling remaining stock and the like. Sometimes they sell
random LCD screens without any documentation, or even old Russian ICs.&lt;/p&gt;

&lt;p&gt;I ordered 20 little plastic boxes for storing my components, 0.85€ per piece.&lt;/p&gt;

&lt;p&gt;Shipping was moderately fast (3 days), everything was packaged well
etc. The boxes aren’t of best quality, but hey, I paid 85ct per box
and it has a reason they’re that cheap. Render me satisfied.&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-07-26:/posts/2011/07/electronics__starting_small/</id>
    <title type="html">Electronics: Starting small</title>
    <published>2011-07-26T17:57:50Z</published>
    <updated>2011-07-26T17:57:50Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/07/electronics__starting_small/"/>
    <content type="html">&lt;p class="preface"&gt;This is part two of a series of me describing my new experiences with
electronics.&lt;/p&gt;

&lt;p&gt;As I said in my last post, I want to start with simple hardware. The
reasons for this should be pretty obvious: neither do I have a
concrete idea for a project, nor am I certain that I’ll stay
interested for long enough. Consequently, I don’t want to spend too
much money.&lt;/p&gt;

&lt;p&gt;A rough limit I have set for myself is about 60€.&lt;/p&gt;

&lt;h3 id="disregard-females-acquire-hardware"&gt;Disregard Females, Acquire Hardware&lt;/h3&gt;

&lt;p&gt;The first step is to find a platform to work with, where the following
aspects are the most important ones to me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the developing environment has to be compatible with Linux&lt;/li&gt;
  &lt;li&gt;it has to be affordable&lt;/li&gt;
  &lt;li&gt;it has to be solder-free&lt;/li&gt;
  &lt;li&gt;it mustn’t be too limited&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Friends quickly pointed in the direction of Arduino, an open-source platform.&lt;/p&gt;

&lt;h4 id="what-is-arduino"&gt;What is Arduino?&lt;/h4&gt;

&lt;p&gt;Arduino is both a community and a hardware platform. The idea of
Arduino is to provide an open platform for average people, especially
artists (with a wide meaning of artist).&lt;/p&gt;

&lt;p&gt;Open, in this context, means that the circuit design as well as the
source code are freely available to anyone. An implication of this is
that anyone can design (and sell) his own Arduino. A nice side-effect
is that no single entity can control the price and thus Arduinos are
very affordable, starting at 20€ for the basic ones.&lt;/p&gt;

&lt;h4 id="what-arduino-to-get"&gt;What Arduino to get?&lt;/h4&gt;

&lt;p&gt;There’s not “one Arduino” that you can buy, but different designs for
different tasks. There are Arduinos especially made for
&lt;a href="http://www.arduino.cc/en/Main/ArduinoBoardLilyPad"&gt;sewing into clothes&lt;/a&gt;,
&lt;a href="http://www.arduino.cc/en/Main/ArduinoBoardNano"&gt;extremely small ones&lt;/a&gt;
for small devices and a
&lt;a href="http://arduino.cc/en/Main/ArduinoBoardUno"&gt;variety of palm-sized ones&lt;/a&gt;
for prototyping (which is what we’re after).&lt;/p&gt;

&lt;p&gt;The current “revisions” of the main prototyping boards are called
&lt;a href="http://arduino.cc/en/Main/ArduinoBoardUno"&gt;“Arduino Uno”&lt;/a&gt; and
&lt;a href="http://arduino.cc/en/Main/ArduinoBoardMega2560"&gt;“Arduino Mega 2560”&lt;/a&gt;,
where the only difference is that the Mega has more pins, more memory
and is more expensive.&lt;/p&gt;

&lt;p&gt;The Arduino Uno can be bought for about 20-30€ (depending on where you
live) and the Arduino Mega for about 40-60€.&lt;/p&gt;

&lt;p&gt;Considering that I want to start small, the Arduino Uno is the perfect
choice, especially because I still have to get more components to
actually be able to do something with it.&lt;/p&gt;

&lt;h4 id="starter-kits"&gt;Starter kits&lt;/h4&gt;

&lt;p&gt;Luckily, a lot of shops sell starter kits consisting of an Arduino Uno
and some basic components. The most promising one I found is the
&lt;a href="http://www.sparkfun.com/products/10173"&gt;“SparkFun Inventor’s Kit”&lt;/a&gt;,
which comes with an Arduino, a lot of sensors and some actuators, for
65€. For more information on the exact list of parts, click the link.&lt;/p&gt;

&lt;p&gt;Unfortunately, shipping to Germany is rather expensive, and even
though some German shops sell the very same kit, they sell it for more
than 65€, so that exceeds my limit, especially the one imposed by my
bank account.&lt;/p&gt;

&lt;p&gt;I did, however, find
&lt;a href="http://bausteln.de/shop/arduino/sets/einsteigerset.html"&gt;a comparable kit&lt;/a&gt;
at a German shop called “bausteln” for only 59€. It comes with nearly
the exact same components, just lacking two of the sensors and a DC
motor. Since I already own multiple DC motors, and the missing sensors
can easily be bought separately later, I chose to buy that kit.&lt;/p&gt;

&lt;h4 id="buying-in-bulk"&gt;Buying in bulk&lt;/h4&gt;

&lt;p&gt;I never realised how cheap resistors, transistors and diodes can be if
bought in bulk, at least if buying at shops that specialise on that
kind of selling, like &lt;a href="http://www.futurlec.com"&gt;Futurlec&lt;/a&gt; does.&lt;/p&gt;

&lt;p&gt;Beside all the single components they sell, they also sell
&lt;a href="http://www.futurlec.com/ValuePacks.shtml"&gt;bags full of them&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;$2.95 for 300 resistors? Bought! $2.95 for ceramic capacitors? Bought!
$5.95 for Linear ICs? You guessed it, bought! $4.95 for 100 LEDs?
Nope, I already have plenty of LEDs, thanks anyway. And so it goes on
for most of the “value packs” Futurlec sells. Those are certainly a
great way to get you started. For about $25 plus shipping (which is
also extremely affordable) you get bags full of everything you’ll need
as a starter.&lt;/p&gt;

&lt;h4 id="my-shopping-list"&gt;My shopping list&lt;/h4&gt;

&lt;p&gt;And this is what I eventually ended up buying:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://bausteln.de/shop/arduino/sets/einsteigerset.html"&gt;Arduino Einsteigerset&lt;/a&gt; – $72&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.futurlec.com/ValuePacks.shtml"&gt;Value packs&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;300 1/4W resistors – $2.95&lt;/li&gt;
      &lt;li&gt;200 ceramic capacitors – $2.95&lt;/li&gt;
      &lt;li&gt;100 electrolytic capacitors – $3.95&lt;/li&gt;
      &lt;li&gt;50 Linear ICs – $5.95&lt;/li&gt;
      &lt;li&gt;100 diodes – $2.95&lt;/li&gt;
      &lt;li&gt;100 transistors – $4.95&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.futurlec.com/cgi-bin/search/qty_price.cgi?part_no=LEDBARRED"&gt;Red bargraph&lt;/a&gt; – $0.30&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.futurlec.com/cgi-bin/search/qty_price.cgi?part_no=JUMPERKIT"&gt;Jumper wires&lt;/a&gt; – $4.90&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In total that’s $100.9 or 70.19€, plus shipping. That’s very close to
my limit of 60€ so I am satisfied.&lt;/p&gt;

&lt;p&gt;More articles coming once I received my packages.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-07-25:/posts/2011/07/electronics__introducing_myself_to_the_world_of_electronics/</id>
    <title type="html">Electronics: Introducing myself to the world of electronics</title>
    <published>2011-07-25T17:29:30Z</published>
    <updated>2011-07-25T17:29:30Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/07/electronics__introducing_myself_to_the_world_of_electronics/"/>
    <content type="html">&lt;p class="preface"&gt;This is part one of a series of me describing my new experiences with
electronics.&lt;/p&gt;

&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;

&lt;p&gt;I’ve never really been interested in electronics (ie. circuits,
microcontrollers etc). Sure, I understand, on a basic level, how most
of the gadgets and computers that I own work, but I wouldn’t be able
to build anything myself or explain what e.g. a diode is used for.&lt;/p&gt;

&lt;p&gt;The closest I ever got to working with electronics was owning a kit
for children, consisting of a couple transistors, resistors,
capacitors and LEDs. My interest didn’t last long though, especially
because I cooked one of the transistors early on, rendering me unable
to build most of the circuits from the manual.&lt;/p&gt;

&lt;p&gt;Being a geek, however, I am always interested in acquiring new skills
that somehow relate to computers and electronics are just a logical
extension (or rather simplification) of computers. Furthermore I found
the following reasons to learn more about electronics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Parts of it might be considered common knowledge among my circles&lt;/li&gt;
  &lt;li&gt;It might be a nice skillset for my CV, especially the microcontroller aspect&lt;/li&gt;
  &lt;li&gt;My studies at university will require me to work with microcontrollers, anyway&lt;/li&gt;
  &lt;li&gt;I heard it is supposed to be a fun experience!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what am I going to do now? I’ll look for an affordable
microcontroller and components needed for basic circuits and go from
there. More on that in my next articles.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-07-13:/posts/2011/07/sketchup_plugin__selection_manager/</id>
    <title type="html">SketchUp Plugin: Selection Manager</title>
    <published>2011-07-13T15:00:33Z</published>
    <updated>2011-07-13T15:00:33Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/07/sketchup_plugin__selection_manager/"/>
    <content type="html">&lt;p&gt;Disappointed with &lt;a href="http://www.smustard.com/script/SelectionMemory"&gt;SelectionMemory&lt;/a&gt; and not willing to pay $5
for &lt;a href="http://www.smustard.com/script/SelectionMemory2"&gt;SelectionMemory2&lt;/a&gt; (not mentioning the bad interface it has), I went
to write my own plugin for saving and restoring selections.&lt;/p&gt;

&lt;p&gt;The main benefits compared to other solutions are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It is free&lt;/li&gt;
  &lt;li&gt;It has no artificial limit with regard to how many selections can be saved&lt;/li&gt;
  &lt;li&gt;It is driven via the context menu&lt;/li&gt;
  &lt;li&gt;Selections can be saved with the model and won’t be lost when closing SketchUp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the readme as well as the plugin itself, check the &lt;a href="https://github.com/dominikh/sketchup-selection_manager"&gt;git repository at GitHub&lt;/a&gt;.&lt;/p&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-07-08:/posts/2011/07/don_t_abbreviate__thanks____sorry__or__please_/</id>
    <title type="html">Don't Abbreviate "Thanks," "Sorry" or "Please"</title>
    <published>2011-07-08T10:19:37Z</published>
    <updated>2011-07-08T10:19:37Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/07/don_t_abbreviate__thanks____sorry__or__please_/"/>
    <content type="html">&lt;dl&gt;
  &lt;dt&gt;Author&lt;/dt&gt;
  &lt;dd&gt;Matti Virkkunen&lt;/dd&gt;
  &lt;dt&gt;Editor&lt;/dt&gt;
  &lt;dd&gt;Ludvig Ericson&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;When you say thanks to somebody, you’re expressing gratitude. You’re
telling the person that you really appreciate what he/she did for you.
If somebody has given you something without wanting anything in return
(and even if they did want something in return, it never hurts to be
polite) you really &lt;em&gt;should&lt;/em&gt; be grateful. The best way to mess this up is
to say “thx” or “10x” or “ty” or something like that. I can’t believe
that somebody is really grateful when he doesn’t even have time to
type “thanks” but instead abbreviates it to “thx” or something to save
himself from typing–get this–three extra letters.&lt;/p&gt;

&lt;p&gt;Another thing is saying “sorry.” It’s often said that “sorry” is the
most important and at the same time the most difficult word to say. If
somebody doesn’t bother to type the whole word “sorry” but instead
uses “sry” or “soz” etc, I can’t really believe that he’s truly sorry.
It’s more like “Okay, whatever, I’ll just settle this huge mistake
I’ve made by saying ‘sry.’”&lt;/p&gt;

&lt;p&gt;And the third word, “please,” shouldn’t be abbreviated either. It’s a
bit like “thanks” in advance, it means approximately “I’ll appreciate
if you help me with my problem here.” It’ll send out a message saying
that you’re a nice enough person and will hopefully increase your
chances of getting help. Don’t mess this great opportunity up by using
“plz” or “pls” or something similar.&lt;/p&gt;

&lt;p&gt;I don’t really mind people abbreviating other words although
abbreviating just to save the trouble of typing two letters is dumb. I
guess abbreviating words like that is fine when you’re talking with
people you know really well, and know they won’t mind, but not on some
support IRC channel or forum where people donate their time to the
community to help others for free. Just don’t abbreviate “thanks,”
“sorry” and “please” because they’re meant to express “strong” things,
gratitude and regret.&lt;/p&gt;

&lt;p&gt;Thank you for reading this.&lt;/p&gt;

&lt;p&gt;Matti “Lumpio-“ Virkkunen&lt;/p&gt;

&lt;p&gt;[editor’s note: Some text removed. The following paragraphs are whole
additions, and do not in any way represent what the original author
wrote or intended to write.]&lt;/p&gt;

&lt;p&gt;Using aforementioned abbreviations in the purpose of portraying the
typical user who would in honesty use them are excused, this is called
being ironic or sometimes caricature.&lt;/p&gt;

&lt;p&gt;Applying aforementioned thinking on all abbreviations (for example
“e.g.”) does simply not make sense. Please note that the point in not
abbreviating words that bear a major weight is that a full word shows
that you have cared enough to type the whole word out, thereby showing
respect and/or engagement in a given task. Had you written out “e.g.”
as “exempli gratia,” one would perceive it as emphasis, since such
abbreviation is rarely, if ever, written out.&lt;/p&gt;

&lt;p&gt;That said, abbreviating too much isn’t very nice either. Most readers
would subconsciously or consciously have to reinterpret one sentence
or even one word a few times, so while it might take less time to
write in an overly abbreviated manner, it takes twice the time for
some people to read said text, resulting in unwanted emotions for the
reader. Don’t abbreviate too often, when in doubt, go with the
expanded version.&lt;/p&gt;

&lt;p&gt;[editor’s note: This is a heavily edited version of Matti Virkkunen’s
original work (available over HTTP at
http://lumpio.no-ip.com/dont-use-thx-sry-plz.txt) and perhaps can not
be legitimately said to have been authored wholly by said person.]&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2011-05-01:/posts/2011/05/rsemantic___latent_semantic_analysis_for_ruby/</id>
    <title type="html">rsemantic – Latent Semantic Analysis for Ruby</title>
    <published>2011-05-01T14:39:47Z</published>
    <updated>2011-05-01T14:39:47Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2011/05/rsemantic___latent_semantic_analysis_for_ruby/"/>
    <content type="html">&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;

&lt;p&gt;Some time ago, I started reading
&lt;a href="http://astore.amazon.com/mojombo-20/detail/1594487715"&gt;&lt;em&gt;Where Good Ideas Come From: The Natural History of Innovation&lt;/em&gt;&lt;/a&gt;
and one thing it mentions is an application called “DEVONthink”.
DEVONthink is an application you’d use for storing all kind of
documents (RSS feeds, emails, notes, articles) and the by far most
interesting feature is its ability to recommend similar documents,
without asking the user to provide categories/tags or summaries by
himself. Instead, DEVONthink automatically analyses all your documents
and calculates the similarity.&lt;/p&gt;

&lt;p&gt;The really interesting part here is that DEVONthink is able to tell if
different words have similar meanings, e.g. “canine” and “dog”. That
means that if you’re reading a new article which talks mostly about
dogs, DEVONthink will be able to suggest an article about canines.
This isn’t done by a fixed list of words with similar meanings, but
again by analysing all documents and checking which words get used
together often.&lt;/p&gt;

&lt;p&gt;Unfortunately, DEVONthink is only available for OS X and not for
Linux. Besides that, it works with a centralised database, while I
believe in the beauty of plain text files. That is why I began
researching how DEVONthink is able to successfully find similar
documents and I quickly found Latent Semantic Analysis, short
LSA.&lt;/p&gt;

&lt;h3 id="latent-semantic-analysis"&gt;Latent Semantic Analysis&lt;/h3&gt;

&lt;p&gt;Now, I do not want to explain LSA in detail, but summarized it works
as follows: First, a term-document matrix gets constructed, storing
which terms occur how often in which documents. Such a matrix usually
is quite sparse, meaning that it is mostly populated with zeros. LSA
then decomposes the matrix into three parts (this is known as
&lt;a href="http://en.wikipedia.org/wiki/Singular_value_decomposition"&gt;Singular Value Decomposition, SVD&lt;/a&gt;), reduces the singular values to
the K biggest values and then recomposes the matrix. This effectively
reduces the dimensions of the vector space, putting similar words
closer together.&lt;/p&gt;

&lt;p&gt;For a detailed (and mathematically accurate) description, check out
the &lt;a href="http://en.wikipedia.org/wiki/Latent_semantic_analysis"&gt;Wikipedia article about LSA.&lt;/a&gt;&lt;/p&gt;

&lt;h3 id="lsa-in-ruby"&gt;LSA in Ruby&lt;/h3&gt;

&lt;p&gt;Trying to avoid having to do the math by myself, I looked for a ready
library for Ruby that’d offer LSA. I found rsemantic, which by itself
looked promising, not only offering LSA but also &lt;a href="http://en.wikipedia.org/wiki/Tf-idf"&gt;tf-idf&lt;/a&gt; (a way to
give common words negative scores).&lt;/p&gt;

&lt;p&gt;The only problem with rsemantic was, that it depends on &lt;a href="http://rubyforge.org/projects/linalg/"&gt;linalg&lt;/a&gt;,
another Ruby library, which provides binding to &lt;a href="http://en.wikipedia.org/wiki/LAPACK"&gt;LAPACK&lt;/a&gt;, a Fortran
library for linea algebra. Now the problem with linalg is that it
doesn’t compile on modern systems, at all. Apparently it requires gcc
3.x, and the maintainer has seemingly abandonned the project quite
some time ago.&lt;/p&gt;

&lt;p&gt;Looking for an alternative to either rsemantic (which wasn’t actively
developed anymore, either) or linalg, I found the GNU Science Library
(GSL), for which someone wrote working Ruby bindings.&lt;/p&gt;

&lt;p&gt;The next step was obvious: port rsemantic to GSL. At the same time, I
was able to improve other parts of rsemantic, cleaning up the whole
code base and drastically improving the performance, to a point where
the only time consuming process is doing the SVD itself.&lt;/p&gt;

&lt;h3 id="the-future-of-rsemantic"&gt;The future of rsemantic&lt;/h3&gt;

&lt;p&gt;Luckily, the developer of rsemantic is still interested in the project
(and even actively using it, according to him). He therefore merged my
changes and added me as a contributor to the
&lt;a href="https://github.com/josephwilk/rsemantic"&gt;git repository at GitHub&lt;/a&gt;, allowing me to further work on the
library.&lt;/p&gt;

&lt;p&gt;A new version of the gem will be released as soon as both of us are
happy with all the recent changes.&lt;/p&gt;

&lt;p&gt;Furthermore, I am working on an improved API for rsemantic. While
currently it is pretty low-level (and not that object-oriented), I am
working on a far more high-level API. Following are two examples,
first for the new API, then for the old one.&lt;/p&gt;

&lt;h4 id="new-api"&gt;New API&lt;/h4&gt;
&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"semantic"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"pp"&lt;/span&gt;

&lt;span class="n"&gt;corpus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Semantic&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Corpus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:transforms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:LSA&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# The directory /tmp/some_texts/ contains Wikipedia articles about&lt;/span&gt;
&lt;span class="c1"&gt;# various animals (beagle.txt canidae.txt cat.txt dog.txt gecko.txt&lt;/span&gt;
&lt;span class="c1"&gt;# german_shepherd.txt reptile.txt salamander.txt)&lt;/span&gt;
&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/some_texts/*.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Here we add each article to the corpus (collection of documents).&lt;/span&gt;
  &lt;span class="c1"&gt;# `:name` is an attribute we're assigning to the document. There is&lt;/span&gt;
  &lt;span class="c1"&gt;# no limit in the names and amount of attributes you can attach to&lt;/span&gt;
  &lt;span class="c1"&gt;# each document.&lt;/span&gt;
  &lt;span class="n"&gt;corpus&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Semantic&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# Build the index, Depending on the CPU, available memory and most&lt;/span&gt;
&lt;span class="c1"&gt;# importantly the size of the corpus, this can take some time.&lt;/span&gt;
&lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build_index&lt;/span&gt;

&lt;span class="c1"&gt;# Compares the article about dogs to all other articles and returns a&lt;/span&gt;
&lt;span class="c1"&gt;# score for each article, representing the similarity.&lt;/span&gt;

&lt;span class="c1"&gt;# In the example output we can see, that rsemantic correctly says that&lt;/span&gt;
&lt;span class="c1"&gt;# "dog.txt" is by far the most related to&lt;/span&gt;
&lt;span class="c1"&gt;# {german_shepherd,beagle,canidae}.txt, and not to e.g. reptiles.&lt;/span&gt;
&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"dog.txt"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;related&lt;/span&gt;
&lt;span class="c1"&gt;# {#&amp;lt;Semantic::Corpus 8 documents, @options={:transforms=&amp;gt;[:LSA]}&amp;gt;=&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;#   [#&amp;lt;Semantic::SearchResult:0x0000000283db30&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"gecko.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.05935175420757509&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283dbd0&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"reptile.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.09322815190241214&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283db08&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"cat.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.14170011833185264&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283db80&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"salamander.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.17269285169838045&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283db58&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"canidae.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.2107975969277189&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283dba8&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"beagle.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.4041096720670102&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283dbf8&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"german_shepherd.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=0.508139138880475&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#    #&amp;lt;Semantic::SearchResult:0x0000000283dc20&lt;/span&gt;
&lt;span class="c1"&gt;#     @document=#&amp;lt;Semantic::Document @attributes={:name=&amp;gt;"dog.txt"}&amp;gt;,&lt;/span&gt;
&lt;span class="c1"&gt;#     @score=1.0000000000000688&amp;gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="old-api"&gt;Old API&lt;/h4&gt;
&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"semantic"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"pp"&lt;/span&gt;

&lt;span class="n"&gt;corpus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Semantic&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Corpus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:transforms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:LSA&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;documents&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;document_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;

&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/some_texts/*.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;documents&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;
  &lt;span class="n"&gt;document_names&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# This automatically builds the index for all documents&lt;/span&gt;
&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Semantic&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Search&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:transforms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:LSA&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document_names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dog.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;document_names&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# The resulting scores are the same, but we have to manually keep&lt;/span&gt;
&lt;span class="c1"&gt;# track of file names, indices, and the scores are not sorted, either.&lt;/span&gt;
&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;
&lt;span class="c1"&gt;# {"dog.txt"=&amp;gt;1.0000000000000688,&lt;/span&gt;
&lt;span class="c1"&gt;#  "german_shepherd.txt"=&amp;gt;0.508139138880475,&lt;/span&gt;
&lt;span class="c1"&gt;#  "reptile.txt"=&amp;gt;0.09322815190241214,&lt;/span&gt;
&lt;span class="c1"&gt;#  "beagle.txt"=&amp;gt;0.4041096720670102,&lt;/span&gt;
&lt;span class="c1"&gt;#  "salamander.txt"=&amp;gt;0.17269285169838045,&lt;/span&gt;
&lt;span class="c1"&gt;#  "canidae.txt"=&amp;gt;0.2107975969277189,&lt;/span&gt;
&lt;span class="c1"&gt;#  "gecko.txt"=&amp;gt;0.05935175420757509,&lt;/span&gt;
&lt;span class="c1"&gt;#  "cat.txt"=&amp;gt;0.14170011833185264}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2010-10-27:/posts/2010/10/why_you_should_try_tmux_instead_of_screen/</id>
    <title type="html">Why You Should Try tmux Instead of screen</title>
    <published>2010-10-27T01:42:05Z</published>
    <updated>2010-10-27T01:42:05Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2010/10/why_you_should_try_tmux_instead_of_screen/"/>
    <content type="html">&lt;h3 id="what-screen-is"&gt;What screen is&lt;/h3&gt;

&lt;p&gt;If you’re reading this article, you probably already know what &lt;em&gt;GNU
Screen&lt;/em&gt; is: the most well-known terminal multiplexer in the world of
Unix. If that doesn’t ring any bells, I recommend reading
&lt;a href="http://en.wikipedia.org/wiki/GNU_Screen"&gt;the Wikipedia article about GNU Screen&lt;/a&gt;
before continuing with this article.&lt;/p&gt;

&lt;h3 id="an-alternative"&gt;An Alternative&lt;/h3&gt;

&lt;p&gt;There are, however, also some other terminal multiplexers besides GNU
screen, most notably &lt;a href="http://sourceforge.net/projects/tmux/"&gt;tmux&lt;/a&gt;. While technically screen and tmux serve the
same purpose – multiplexing terminals – their functionality and
quality differ drastically.&lt;/p&gt;

&lt;h3 id="the-history-of-screen-and-tmux"&gt;The History of screen And tmux&lt;/h3&gt;

&lt;p&gt;Development of screen started in 1987; additions and fixes have
been contributed ever since. On the one hand, that means that screen
is a solid and proven piece of software; On the other hand, though, it
also means that the codebase isn’t the cleanest one nor easy to
understand. As a result of this, new additions are rare and
development mostly concentrates on fixing existing bugs.&lt;/p&gt;

&lt;p&gt;Tmux, on the other side, saw the light of day in late 2007. And
because the developer was able to learn from screen’s mistakes while
at the same time picking up existing and field-tested features, tmux
has a solid and extensible code base – and it is actively developed by
a very responsive developer.&lt;/p&gt;

&lt;h3 id="actual-new-features"&gt;Actual New Features&lt;/h3&gt;

&lt;p&gt;So, tmux has a better codebase and has (nearly, more on that later)
all the features screen has – but chances are high that you are not
interested in the code at all, so why should you care? Because tmux
has a lot of features that screen has always been missing.&lt;/p&gt;

&lt;h4 id="a-sensible-configuration-format"&gt;A Sensible Configuration Format&lt;/h4&gt;

&lt;p&gt;If there was only one shortcoming of screen that you were allowed to
name, which one would it be? Right, the format of the configuration
files…&lt;/p&gt;

&lt;p&gt;Let’s look at a prominent example: a hardstatus (called “status line”
in tmux) that contains the computer’s hostname, a list of all windows,
the load average and a clock:&lt;/p&gt;

&lt;pre class="text"&gt;&lt;code&gt;hardstatus alwayslastline '%{gk}[ %{G}%H %{g}][%= %{wk}%?%-Lw%?%{=b kR}(%{W}%n*%f%t%?(%u)%?%{=b kR})%{= kw}%?%+Lw%?%?%= %{y}][%{G} %l%{y}] %{y}[%{G} %m/%d %c %{y}]%{W}'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;img src="/img/tmux_screen/screen_status_bar.png" alt="screen status_bar" /&gt;
&lt;/p&gt;

&lt;p&gt;If I didn’t tell you what that option did, were you able to understand
it, or more importantly, able to write it yourself? No, you probably
wouldn’t. (If you, in fact, are able to: congratulations, and sincere
condolences).&lt;/p&gt;

&lt;p&gt;So, how would that look like in tmux? Here’s how:&lt;/p&gt;

&lt;pre class="text"&gt;&lt;code&gt;set -g status-left ' #[fg=green,bold]#H#[default]'
set -g status-right '#[fg=yellow,bold]#(cut -d " " -f 1-4 /proc/loadavg)#[default] #[fg=cyan,bold]%Y-%m-%d %H:%M:%S#[default] '
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;img src="/img/tmux_screen/tmux_status_bar.png" alt="tmux status_bar" /&gt;
&lt;/p&gt;

&lt;p&gt;Okay, so it’s easy to see where colors are being set (and yes, they do
differ from the screen example, just ignore that. It would look the
same for other colors, too), it’s kind of obvious what “#H” means (and
the man pages of tmux have a complete list of all available codes), we
instantly can see how the load average is displayed, and the clock
format string should be obvious.&lt;/p&gt;

&lt;p&gt;But wait, where’s the list of windows? That’s a built-in feature of
tmux and thus doesn’t have to be set explicitly.&lt;/p&gt;

&lt;p&gt;Of course there are a lot of more options, like the following one,
which loads the emacs keymap:&lt;/p&gt;

&lt;pre class="text"&gt;&lt;code&gt;set-window-option -g mode-keys emacs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another major aspect of tmux’s config format is that it is basically a
batch script: it is a simple list of commands that will be executed
when tmux is started – they’re the same commands that you use in
keybinds, the command prompt and shell scripts (more on that in a
minute). If you want to always create two windows when a session is
created, you can put this into your configuration:&lt;/p&gt;

&lt;pre class="text"&gt;&lt;code&gt;new-window -n some_name
new-window -n another_name
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id="scriptable"&gt;Scriptable&lt;/h4&gt;

&lt;p&gt;Another major aspect of tmux is that nearly all commands can be
invoked from the command line, allowing complex scripts controlling
tmux sessions. &lt;code&gt;tmux new-window&lt;/code&gt;, for example, would create a new
window. Splitting, moving and resizing windows, setting options and a
lot more actions are possible as well. Even the status bar can
dynamically be changed.&lt;/p&gt;

&lt;h4 id="emacs-and-vi-keymaps"&gt;Emacs And Vi Keymaps&lt;/h4&gt;

&lt;p&gt;tmux supports two different keymaps, imitating either Emacs or vi.
Those keymaps will be used in copy mode and the command prompt.&lt;/p&gt;

&lt;h4 id="mouse-support"&gt;Mouse Support&lt;/h4&gt;

&lt;p&gt;Yeah, power users will smile at this feature, but novices might
actually like it: panes can be selected using the mouse, and in copy
mode, the mouse wheel is supported as well.&lt;/p&gt;

&lt;h4 id="menus"&gt;Menus&lt;/h4&gt;

&lt;p&gt;Nice to have, tmux has menus for selecting windows and sessions.
&lt;img src="/img/tmux_screen/tmux_menu.png" alt="menu in tmux" /&gt;&lt;/p&gt;

&lt;h4 id="multiple-buffers"&gt;Multiple buffers&lt;/h4&gt;

&lt;p&gt;Much like the kill ring in Emacs, tmux can keep more than one
selection/piece of copied text in memory.&lt;/p&gt;

&lt;h4 id="bsd-license"&gt;BSD License&lt;/h4&gt;

&lt;p&gt;Unlike GNU Screen, tmux is licensed under the simplified BSD license.
Obviously this will please everyone who dislikes the GPL – but there’s
even a real benefit from the choice in license: tmux is part of
OpenBSD since version 4.6.&lt;/p&gt;

&lt;h3 id="differences-to-screen"&gt;Differences to screen&lt;/h3&gt;

&lt;h4 id="server-model"&gt;Server Model&lt;/h4&gt;

&lt;p&gt;One speciality of tmux is that when creating your first session, it
spawns a server which manages said session and all future sessions. In
fact it is also possible to change the current session on the fly,
using commands or even a fancy navigatable menu.&lt;/p&gt;

&lt;p&gt;With tmux, it is not uncommon to have a set of different sessions (one
for work, one for server management, and so on) and to quickly switch
between them, effectively creating another level of grouping of
windows.&lt;/p&gt;

&lt;p&gt;Sessions can also be grouped, which means that they share the same set
of windows but have independent options and allow multiple users to
work with the same windows – much like &lt;code&gt;screen -x&lt;/code&gt;, just a tad more
flexible.&lt;/p&gt;

&lt;h4 id="window-splitting"&gt;Window Splitting&lt;/h4&gt;

&lt;p&gt;This one is probably the most confusing aspect of tmux, to people
coming from screen. While splitting in screen means displaying
multiple windows at once, in tmux it means splitting a window into
multiple panes. It is, however, possible to take a pane and convert it
into a window and vice versa. It is, however, not possible to display
a window in a pane, without converting it to a pane.&lt;/p&gt;

&lt;p&gt;Tmux does, however, natively support both horizontal &lt;strong&gt;and&lt;/strong&gt; vertical
splits, without the need for a custom patch, as is the case with
screen.
&lt;img src="/img/tmux_screen/tmux_splits.png" alt="screen status_bar" /&gt;&lt;/p&gt;

&lt;p&gt;Additionally, tmux has presets for pane arrangements, eliminating the
need for arranging splits by hand.&lt;/p&gt;

&lt;h4 id="missing-features"&gt;Missing Features&lt;/h4&gt;

&lt;p&gt;As mentioned earlier, there is in fact a feature missing in tmux:
built-in serial and telnet support, while screen is able to directly
connect to for example a serial null modem. Even more so, tmux will
probably never include that feature, because the developer considers
it bloat and says, that other, specialized tools should be used for
that task instead.&lt;/p&gt;

&lt;h3 id="final-words"&gt;Final words&lt;/h3&gt;

&lt;p&gt;I hope that this article is giving you enough reasons to at least try
tmux. Of course there might be users who are just happy with screen or
even users who need its support for serial consoles, but most of you
should be able to at least give it a try. I can assure you that you
will not regret it.&lt;/p&gt;

&lt;p&gt;I also recommend reading the
&lt;a href="http://wisconsinlinux.org/tmux-manpage-from-cvs/tmux.1.txt"&gt;man pages of tmux&lt;/a&gt;,
which are written in a very clear and readable way, and just playing
with some of the options.&lt;/p&gt;

&lt;h3 id="links"&gt;Links&lt;/h3&gt;
&lt;dl&gt;
  &lt;dt&gt;Wikipedia article about GNU Screen&lt;/dt&gt;
  &lt;dd&gt;&lt;a href="http://en.wikipedia.org/wiki/GNU_Screen"&gt;http://en.wikipedia.org/wiki/GNU_Screen&lt;/a&gt;&lt;/dd&gt;
  &lt;dt&gt;tmux&lt;/dt&gt;
  &lt;dd&gt;&lt;a href="http://sourceforge.net/projects/tmux/"&gt;http://sourceforge.net/projects/tmux/&lt;/a&gt;&lt;/dd&gt;
  &lt;dt&gt;man pages of tmux&lt;/dt&gt;
  &lt;dd&gt;&lt;a href="http://wisconsinlinux.org/tmux-manpage-from-cvs/tmux.1.txt"&gt;http://wisconsinlinux.org/tmux-manpage-from-cvs/tmux.1.txt&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2010-08-04:/posts/2010/08/newton_and_cinch_____one_awesome_framework___/</id>
    <title type="html">Newton and Cinch – One awesome framework</title>
    <published>2010-08-03T23:45:20Z</published>
    <updated>2010-08-03T23:45:20Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2010/08/newton_and_cinch_____one_awesome_framework___/"/>
    <content type="html">&lt;p&gt;A lot of time (3 months, actually) has passed since I’ve last blogged
about
&lt;a href="/posts/2010/05/are_lightweight_irc_frameworks_too_lightweight_/"&gt;Ruby and available IRC frameworks for writing bots&lt;/a&gt;.
Back then I planned to fork Isaac or Cinch, in order to add proper
abstraction and object-orientation to them. Well, I did fork Isaac,
realized that it was, in all honesty, quite a mess and instead wrote
my own framework, mostly from scratch. I did, however, call it
“Newton”, completly ignoring the fact that Isaac was named after Isaac
Hayes and not Isaac Newton. I still thought it was a suiting name for
what was supposed to be a fork.&lt;/p&gt;

&lt;p&gt;Well, in my obviously biased opinion,
&lt;a href="http://github.com/dominikh/newton"&gt;Newton&lt;/a&gt; is the finest Ruby
framework for writing IRC bots. It has it all:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a nice DSL&lt;/li&gt;
  &lt;li&gt;proper debug output&lt;/li&gt;
  &lt;li&gt;threads&lt;/li&gt;
  &lt;li&gt;support for all relevant parts of the various IRC RFCs, including support for ISUPPORT&lt;/li&gt;
  &lt;li&gt;support for plugins (in a
&lt;a href="http://github.com/dominikh/newton/tree/plugins"&gt;separate branch&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is, however, one thing that Newton is missing: Users. Shockingly
enough (*cough*), good code (remember? biased opinion…) and
features alone won’t attract a lot of users. Good advertisment does,
though, and since you probably have never heard of Newton before, in
all those months, there doesn’t seem to be any good advertisment to be
going on.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt; is coming into
play. Cinch has remarkably many users, even though I think that not
even its developer knows how that’s possible. Anyway, influenced by
Newton (and a funserious rivalry between Cinch and Newton), the
developer of Cinch decided to adapt “some” of my ideas, including more
abstraction, tracking changes in state (joining/leaving users etc.)
and developing a plugin system (admittedly, he did it first, Newton
stole that idea). Threading was also on his to-do list.&lt;/p&gt;

&lt;p&gt;And what’s the second most obvious thing to do, if two projects share
the same ideals and both desire attributes of the other project?
Right, consider merging the two projects (the most obvious thing is
starting a huge flame war, of course).&lt;/p&gt;

&lt;p&gt;And this is why there won’t be any new Newton releases. Instead, most
of the current codebase of Cinch will be replaced by Newton, while
some features of Cinch (its pattern matcher, mostly) will be
backported to Newton. Yes, this will mean that all existing Cinch bots
will not be compatible to the upcoming version, but on the other side,
new and updated bots will be able to profit from a lot of new awesome
features, which will be documented in a later post, and of course an
official README. The current work on the merge can be seen in the
&lt;a href="http://github.com/injekt/cinch/tree/merge"&gt;merge branch&lt;/a&gt;, which will
become the master branch in a few weeks.&lt;/p&gt;

&lt;p&gt;Lastly, for real facts on why the merge is good for Cinch and Newton:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Good for Cinch, because…&lt;/th&gt;
      &lt;th&gt;Good for Newton, because…&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Awesome new features (threading, OO, plugins)&lt;/td&gt;
      &lt;td&gt;A new name, known by a lot of people&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Two developers instead of one&lt;/td&gt;
      &lt;td&gt;Reworked documentation, which will be friendlier to newbies&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;Two developers instead of one&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;That’s it for this article, stay tuned…&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2010-05-01:/posts/2010/05/are_lightweight_irc_frameworks_too_lightweight_/</id>
    <title type="html">Are lightweight IRC frameworks too lightweight?</title>
    <published>2010-05-01T19:07:07Z</published>
    <updated>2010-05-01T19:07:07Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2010/05/are_lightweight_irc_frameworks_too_lightweight_/"/>
    <content type="html">&lt;p&gt;Recently I’ve been looking for a small framework for writing IRC bots
in Ruby. Admittedly, I have been successfully running a bot based on
&lt;a href="http://butler.rubyforge.org/manual/quickstart.html"&gt;Butler&lt;/a&gt; for quite some time now, but I have always been
looking for a more lightweight solution, which does not come with a
predefined plugin or authentication structure.&lt;/p&gt;

&lt;p&gt;Now there are probably three major players in the field of IRC bots,
namely &lt;a href="http://github.com/RISCfuture/autumn"&gt;Autumn&lt;/a&gt;, &lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt; and just recently &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I won’t further examine &lt;a href="http://github.com/RISCfuture/autumn"&gt;Autumn&lt;/a&gt; here, as it is to IRC bots what Rails
is to web development: Anything but lightweight.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt; and &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt; are quite similar: They both feature
a small DSL for quickly developing bots, while &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt; puts
more emphasis on the idea of plugins (&lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt; is more about
parsing messages in general) and its own pattern language to match
input.&lt;/p&gt;

&lt;p&gt;But there is another thing they have in common: No proper
object-oriented interface… Instead of passing around channel and user
objects, all the developer sees are strings. This also means that
instead of doing something as intuitive as&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;
&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"some reason"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="c1"&gt;# retrieve the topic&lt;/span&gt;
&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"new topic"&lt;/span&gt; &lt;span class="c1"&gt;# set a new topic&lt;/span&gt;
&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;span class="n"&gt;some_user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;one will have to fall back to stuff like this (the examples are based
on &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt; but will be similar for &lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt;):&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# now this still makes sense&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"some reason"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# not too nice anymore&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# plain wrong&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"new topic"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# plain wrong&lt;/span&gt;
&lt;span class="c1"&gt;# there simply is no method of retrieving a user's hostname,&lt;/span&gt;
&lt;span class="c1"&gt;# except from doing a WHOIS and parsing the output yourself&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course one might argue that those frameworks/DSLs are lightweight
after all and that the user could write helper methods if he really
wanted to have a rich interface, but that would also mean that I had
to use those helper methods every other line, just to deal with proper
objects.&lt;/p&gt;

&lt;p&gt;It is quite questionable if “lightweight” is even allowed to mean “not
properly abstracted” or if abstraction is something that can be taken
for granted if working with Ruby.&lt;/p&gt;

&lt;p&gt;Either way, as nice as the DSLs of &lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt; and &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt;
look, they are still pretty useless to me in their current state.
Instead of reinventing the wheel, however, I will probably fork
&lt;a href="http://github.com/ichverstehe/isaac"&gt;Isaac&lt;/a&gt; or &lt;a href="http://github.com/injekt/cinch"&gt;Cinch&lt;/a&gt; and create a “still lightweight”
framework based on that. In the end, I am planning to have an API
which effectively allows code like the following:&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="ss"&gt;:channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/^print my host$/&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# in this example, we will work with an instance of User,&lt;/span&gt;
  &lt;span class="c1"&gt;# instead of a plain string with just a nickname. Same goes for `channel`&lt;/span&gt;
  &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="s2"&gt;"Your host is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="ss"&gt;:channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/!annoy (.+)$/&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# indeed a helper for cases in which we have to deal with strings&lt;/span&gt;
  &lt;span class="no"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;victim&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;victim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="s2"&gt;"hi, you have been annoyed!"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-11-26:/posts/2009/11/ruby_benchmarks/</id>
    <title type="html">Ruby benchmarks</title>
    <published>2009-11-26T22:00:00Z</published>
    <updated>2009-11-26T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/11/ruby_benchmarks/"/>
    <content type="html">&lt;p&gt;The following is a list of benchmarks done with the Ruby programming
language, mostly showing that different ways of doing the same thing
actually can have quite an impact on the overall performance of your
code. And because this list is by no means “complete” or “rich” yet,
you are asked to post your own benchmarks, which will then be added to
this article.&lt;/p&gt;

&lt;p&gt;These benchmarks were all made on a same system with the following
setup:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;System&lt;/dt&gt;
  &lt;dd&gt;Gentoo, 2.6.29, Pentium 4, 3.20GHZ&lt;/dd&gt;
  &lt;dt&gt;Ruby&lt;/dt&gt;
  &lt;dd&gt;ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;
  &lt;strong&gt;Last update: 2009/11/27&lt;/strong&gt;
&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Subject&lt;/th&gt;
      &lt;th&gt;Link&lt;/th&gt;
      &lt;th&gt;Conclusion&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Check if a string contains a certain character&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208025"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;include? is the most natural and fastet way.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Does slicing an array really cost us much?&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208027"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;No.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Single-quoted vs. double-quoted strings&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208029"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;When no interpolation is used, both kind of strings are equally fast.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Split: Regexp vs. String&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208032"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Strings are faster.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Replacing a single character: gsub vs. tr&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208033"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;tr is way faster.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Deleting a single character: gsub vs. tr vs. delete&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208081"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;No difference between delete and tr, gsub is again slower.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Deleting multiple characters: gsub vs. tr vs. delete&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208915"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;A chain of deletes isn’t only ugly, but slow as well. tr wins again over gsub, isn’t any faster than delete though.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gsub: Regexp vs String&lt;/td&gt;
      &lt;td&gt;Derived from the tests with replacing a character&lt;/td&gt;
      &lt;td&gt;gsub is faster when used with regexps.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Construcing regexps&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208067"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;When possible use literal regexps.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;String interpolation in regexps&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/210975"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Regexp.new seems to be slightly faster, if you need it to be interpolated every run.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Matching regexps&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208069"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;=~ is faster than match, because it does not have to create a MatchData object.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Structs: Inheritance vs. assignment&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gist.github.com/208034"&gt;gist&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;No noticeable difference.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A comparison of YAML and Marshal&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://significantbits.wordpress.com/2008/01/29/yaml-vs-marshal-performance/"&gt;Link&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-10-11:/posts/2009/10/dynamically_defining_a_method_on_a_single_instance_in_ruby/</id>
    <title type="html">Dynamically defining a method on a single instance in Ruby</title>
    <published>2009-10-10T22:00:00Z</published>
    <updated>2009-10-10T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/10/dynamically_defining_a_method_on_a_single_instance_in_ruby/"/>
    <content type="html">&lt;p&gt;Given the following initial code…&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bark&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"woof"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;charlie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Charlie"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lucas&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lucas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;… one might want to teach one of the dogs a new trick, while
the others shouldn’t automatically learn it. One possible
solution could look like the following:&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;charlie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jump&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"wee, &lt;/span&gt;&lt;span class="si"&gt;#@name&lt;/span&gt;&lt;span class="s2"&gt; is jumping around"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another way would be to provide a teach_trick method, which
dynamically defines a new method:&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;teach_trick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;define_method&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;charlie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Charlie"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lucas&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lucas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;charlie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teach_trick&lt;/span&gt; &lt;span class="ss"&gt;:dance&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#@name&lt;/span&gt;&lt;span class="s2"&gt; is dancing around!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;charlie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dance&lt;/span&gt; &lt;span class="c1"&gt;# &amp;gt;&amp;gt; Charlie is dancing around!&lt;/span&gt;
&lt;span class="n"&gt;lucas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dance&lt;/span&gt;   &lt;span class="c1"&gt;# ~&amp;gt; -:23:in `&amp;lt;main&amp;gt;': undefined method `dance' for #&amp;lt;Dog:0x9a62e70 @name="Lucas"&amp;gt; (NoMethodError)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this does is it defines a new method on the eigenclass of the
instance of a dog, so when the called method, &lt;em&gt;dance&lt;/em&gt; in
this case, is not found in the instance methods of the class Dog, it
searches in the eigenclass of the instance instead.&lt;/p&gt;

&lt;p&gt;One advantage of this solution is that the actual implementation of
how new tricks are taught is hidden, the user does not need to know he
is defining a method anymore, he is just teaching his dog a new trick.
Another example is when you have to define a bunch of methods
depending on some input, like a hash, which is completly dynamic.&lt;/p&gt;

&lt;p&gt;One disadvantage, on the other hand, is that calling methods defined
by define_method is a bit slower than those defined by def, but the
factor is so small that you probably won’t notice it in real
applications:&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bmbm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"eigenclass:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"instance def:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; Rehearsal -------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; eigenclass:     0.440000   0.000000   0.440000 (  0.453996)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; instance def:   0.320000   0.000000   0.320000 (  0.322817)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; ---------------------------------------- total: 0.760000sec&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt;                     user     system      total        real&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; eigenclass:     0.450000   0.000000   0.450000 (  0.451315)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;gt;&amp;gt; instance def:   0.310000   0.000000   0.310000 (  0.308632)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-10-05:/posts/2009/10/about_getting_help_on_irc/</id>
    <title type="html">About getting help on IRC</title>
    <published>2009-10-04T22:00:00Z</published>
    <updated>2009-10-04T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/10/about_getting_help_on_irc/"/>
    <content type="html">&lt;p&gt;There is one thing that either we, the helping people, or those that
search for help with their code don’t get, and that’s what
kind of answers are to be expected.&lt;/p&gt;

&lt;p&gt;Every too often I see people joining certain channels, in particular
#ruby and #ruby-lang, asking questions about why their code
doesn’t work or how to implement feature XY. And of course they
show others their existing code, which usually isn’t too great,
looking like a direct port from another language or simply like the
one of a newbie (not that being a newbie is bad in any way, we all
started as one).&lt;/p&gt;

&lt;p&gt;Usually what follows isn’t a straight forward answer like
“write this to get your feature” or “change that on
line X to get it working” but a general discussion about the
whole piece of code, how one shouldn’t write it like that at all
and that, if it was done right, the problem wouldn’t have
occured at all.&lt;/p&gt;

&lt;p&gt;The purpose of this definitely is not to offend, discriminate or
degrade anyone, but to teach the people how to code properly, how they
can save time, nerves and money, and what it takes to become a good
programmer. Programming isn’t about just hacking together a few
lines that, by chance, end up doing what you expected them to do, but
to create a well designed application, that can be maintained and
extended at need.&lt;/p&gt;

&lt;p&gt;Nevertheless we can see two completly different kinds of reaction. The
first one is the person being thankful for all the great tips by the
“pros”, even though he might be confused because of all
the information at first. The other one though gets angry and tells
everyone how he “wanted to fix a problem, not rewrite the whole
damn thing from scratch”, generally feeling offended by all the
well-meant advices.&lt;/p&gt;

&lt;p&gt;So, the question is, who is right? Are we supposed/allowed to comment
on the overall quality of the publicly posted code, or do we only
exist to provide copy&amp;amp;paste solutions to people desinterested in
quality of design? In my opinion, most if not all of those that spend
their time helping others, want to make a change, want to
&lt;strong&gt;educate&lt;/strong&gt;, as opposed to just providing solutions that
work in the given context, not fixing the bigger, the real problems.&lt;/p&gt;

&lt;p&gt;I think that if the majority of help seeking people wanted us to stay
shut about the code in a whole and just expected us to provide help
with what exactly they asked, we would end up with not many people
helping anymore.&lt;/p&gt;

&lt;p&gt;So, what can &lt;strong&gt;you&lt;/strong&gt; do in case you need help with a
problem but do not want any help with your design and patterns? Well,
the easiest option clearly is not to join those channels and try to
figure it out by yourself. But I think another, not too bad, option is
to actually seek help in those channels, but by explicitly saying that
you only &lt;strong&gt;want&lt;/strong&gt; (need is a bad word, because you
probably do need) help with a certain problem and that you either have
no time for or no interest in other advices. While this might put off
some people you eventually will end up with one or another helping you
with your particular problem, not wasting his, her or your time with
information other than the ones you need.&lt;/p&gt;

&lt;p&gt;In my opinion it definitely is wrong to ignore those advices made by
professionals, but it is even more wrong to get angry about them.
They’re well-meant, usually correct and you should respect them
if you want to program in a proper manner. Yet, if you do not care
about any of that, at least be so fair and tell us in advance so we
can save our time.&lt;/p&gt;

&lt;h4 id="update-as-of-20091007"&gt;Update, as of 2009/10/07&lt;/h4&gt;

&lt;p&gt;Okay, I’ve read all the comments about my article (both the ones
posted on my blog and the ones on
&lt;a href="http://www.reddit.com/r/programming/comments/9rhf7/getting_help_on_irc_why_people_criticize_your_code/"&gt;reddit&lt;/a&gt;)
and it looks like I made one major mistake when writing this article:
I was only thinking of the two main Ruby channels on FreeNode. While
my article, in my opinion, totally holds true for those two channels
it might as well be true that certain other channels are literally
polluted by people who actively try to bash and piss off newbies.
Alternatively, other channels seem to have a high amount of people
with no deeper knowledge, who, nevertheless, try to force their
opinion upon others, maybe not even backing it up.&lt;/p&gt;

&lt;p&gt;So, what are people with problems supposed to do then? Avoid IRC
alltogether? Hope to be lucky to have picked a language with a decent
community? Only try to get help on IRC if you are able to tell apart
bollocks from qualified help? I don’t know, but maybe you got
the ultimate solution? And if so, maybe you don’t mind sharing
it with us? Comments appreciated!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-08:/posts/2009/08/getting_rid_of_google_analytics/</id>
    <title type="html">Getting rid of Google Analytics</title>
    <published>2009-08-07T22:00:02Z</published>
    <updated>2009-08-07T22:00:02Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/getting_rid_of_google_analytics/"/>
    <content type="html">&lt;p&gt;Ever since I started using Google Analytics, I felt bad about using
it. Yes, I belong to those kind of people that think that Google is
collecting way too much information about us and especially Google
Analytics is making it terribly easy to track us, seeing how many
websites are using it.&lt;/p&gt;

&lt;p&gt;So I finally got my ass up and decided to search for a self-hosted,
open source alternative. And that wasn’t even too hard, after just a
couple of minutes I came across Piwik, a PHP+MySQL
solution, which didn’t even look too bad.&lt;/p&gt;

&lt;p&gt;Piwik has almost all the features that Google Analytics has, plus a
plugin architecture which allows you to easily extend it (now try
doing that with Google Analytics). It has support for a load of search
engines, one can add new ones, it has a “Live!” widget for
live display of visitors (yeah, absolutely unneeded but still a nice
gadget) and one can update the reports at any given time (whereas
Google Analytics is updated every hour).&lt;/p&gt;

&lt;p&gt;It also has a more detailed list of installed plugins, even though it
lacks specific version numbers in the reports.&lt;/p&gt;

&lt;p&gt;There are some drawbacks though:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No custom date ranges&lt;/li&gt;
  &lt;li&gt;“Unique visitors” only work by day, not week/month (even though this
might be fixed already, but then the FAQ is outdated)&lt;/li&gt;
  &lt;li&gt;I am currently facing a bug in the report generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But all those problems are nothing compared to the huge advantage of
having all the data on your own server, not giving away any of it.&lt;/p&gt;

&lt;p&gt;So for now I am using both Google Analytics and Piwik, and if it turns
out to indeed run well, I will remove the Google Analytics code
alltogether.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-08:/posts/2009/08/apache_behind_a_remote_lighttpd_proxy_and_the_caveats/</id>
    <title type="html">Apache behind a remote lighttpd proxy and the caveats</title>
    <published>2009-08-07T22:00:01Z</published>
    <updated>2009-08-07T22:00:01Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/apache_behind_a_remote_lighttpd_proxy_and_the_caveats/"/>
    <content type="html">&lt;h4 id="background"&gt;Background&lt;/h4&gt;

&lt;p&gt;The subdomain I use belongs to a friend, who isn’t able to
set A or CNAME entries, so he uses lighttpd + mod_proxy to redirect it
to my server.&lt;/p&gt;

&lt;h4 id="the-problem"&gt;The Problem&lt;/h4&gt;

&lt;p&gt;And that’s where the problems started. Because of the proxy,
the HTTP REMOTE_ADDR isn’t the one of the visitor anymore but
the one of the proxy, which in turns collides with log analysis, GeoIP
and alike.&lt;/p&gt;

&lt;h4 id="the-solution"&gt;The Solution&lt;/h4&gt;

&lt;p&gt;In general, a simple solution would be to use the Apache module
“rpaf”, which uses the X-Forwarded-For header to properly
set REMOTE_ADDR.&lt;/p&gt;

&lt;p&gt;In my case, that wasn’t the whole solution though. Instead of
an IPv4 address, the lighttpd installation of my friend transmitted an
IPv6 one, which then again didn’t work with GeoIP either, as it
only supports IPv4. In this case, the solution was to run a local
lighttpd, which itself uses mod_extforward to make use of
X-Forwarded-For, and then properly forward the request to Apache, this
time using IPv4.&lt;/p&gt;

&lt;p&gt;Oh, also important: rpaf has to be loaded before GeoIP, otherwise
the latter uses the wrong IP for lookups.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-08:/posts/2009/08/intention_over_implementation_details/</id>
    <title type="html">Intention over implementation details</title>
    <published>2009-08-07T22:00:00Z</published>
    <updated>2009-08-07T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/intention_over_implementation_details/"/>
    <content type="html">&lt;p&gt;Amos Wenger has a
&lt;a href="http://amoswenger.tumblr.com/post/157845512/dot-syntax"&gt;nice post&lt;/a&gt;
about why hiding the implementation details (how something is done)
isn’t wrong at all and how/why it is one of the main characteristics
of high level languages.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-07:/posts/2009/08/ready-for-a-change_/</id>
    <title type="html">Ready for a change?</title>
    <published>2009-08-06T22:00:00Z</published>
    <updated>2009-08-06T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/ready-for-a-change_/"/>
    <content type="html">&lt;p&gt;Yesterday, after facing more and more problems with my Debian
installation on my VPS, I decided it was a good idea to try out
something new, namely Gentoo on a server.&lt;/p&gt;

&lt;p&gt;Well, to make a very long story short: After 6 hours of updating 60
packages and noticing how poor the I/O on the VPS is, I decided to
give up and installed Debian again… Gentoo definitely shouldn’t be
your choice when on an overcrowded VPS.&lt;/p&gt;

&lt;p&gt;Oh, and since I am already writing a post, here is a script that is
useful when setting up servers (and using public key auth):&lt;/p&gt;

&lt;pre class="sh"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env sh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deploying public key on $1"&lt;/span&gt;
scp ~/.ssh/id_rsa.pub &lt;span class="nv"&gt;$1&lt;/span&gt;:
ssh &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s1"&gt;'mkdir ~/.ssh; chmod 700 ~/.ssh; cat ~/id_rsa.pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; rm ~/id_rsa.pub'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition, as of 2009/10/07:&lt;/p&gt;

&lt;p&gt;zenspider was so friendly to provide me with an even better way of
deploying the public key, not requiring you to use scp which in turn
means only one password prompt (it also does not need the use of chmod
nor any temporary file):&lt;/p&gt;

&lt;pre class="sh"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env sh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deploying public key on $1"&lt;/span&gt;
ssh &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s1"&gt;'umask 0077; mkdir -p ~/.ssh; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys'&lt;/span&gt; &amp;lt; ~/.ssh/id_dsa.pub
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-07:/posts/2009/08/only_call_super_when_possible/</id>
    <title type="html">Only call super when possible</title>
    <published>2009-08-06T22:00:00Z</published>
    <updated>2009-08-06T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/only_call_super_when_possible/"/>
    <content type="html">&lt;p&gt;Today we were faced with an interesting question in #ruby-lang:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&amp;lt;Judofyr&amp;gt; is there a way to find out if it’s safe to call “super”?&lt;br /&gt;
&amp;lt;Judofyr&amp;gt; aka. it’s defined on the superclass&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After some ugly solutions (like self.class.ancestors.any? and super rescue nil) apeiros came up with a nicer one:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&amp;lt;apeiros_&amp;gt; super if defined? super&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre class="ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Test&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Test2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Test&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;defined?&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;defined?&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Test2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-04:/posts/2009/08/_smalltalk_best_practice_patterns__reviewed/</id>
    <title type="html">"Smalltalk Best Practice Patterns" reviewed</title>
    <published>2009-08-03T22:00:00Z</published>
    <updated>2009-08-03T22:00:00Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/_smalltalk_best_practice_patterns__reviewed/"/>
    <content type="html">&lt;p&gt;Today I read the first volume of Smalltalk Best Practice Patterns, or
to be precise, a draft I found on Google. While I am a Ruby programmer
and never even touched Smalltalk in my life, it is an undeniable fact
that Ruby and Smalltalk have many things in common, or to put it in
another way, that Ruby (or any real OO language really) was inspired
by Smalltalk.&lt;/p&gt;

&lt;p&gt;The book is, like the title already says, about the “best
practice patterns”, which covers naming conventions, coupling,
splitting up methods and much more.&lt;/p&gt;

&lt;p&gt;The book starts with an introduction into what patterns are, what they
are needed for and how those in the book were developed and describes
the intention of the book by one simple sentence:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This book is about making code that works for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It then, basically, consists of a long list of different patterns,
which are described by a title, patterns preceding and following it,
the problem stated as a question, possible problems with the pattern,
the solution and a discussion of the solution.&lt;/p&gt;

&lt;p&gt;Two important things about the patterns in this book, that distinguish
them from other collections of patterns, are that they are discussed
(instead of simply saying that they are the way to go) and that they
are put into context, as most patterns can’t work if not
combined with others.&lt;/p&gt;

&lt;p&gt;Having read the book, I can say, that most if not all of the patterns
covered in the book are also applicable to the Ruby world, even though
some of them had to be slightly adjusted due to differences between
Ruby and Smalltalk. But those changes only affected details, like the
names of methods, and not the idea behind them.&lt;/p&gt;

&lt;p&gt;It was kind of hard for me to decide if and to whom I should recommend
this book. But I think this puts it the best way: If you are already
familiar with the language you are using and also interested in proper
design patterns, you should absolutely read this book, provided that
you are able to adapt some Smalltalk specific terminology to the ones
that suit the language you use. And even if you don’t want to
pick up the author’s patterns, the first 40 pages of the book
still help you defining your own patterns.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:dominik.honnef.co,2009-08-03:/posts/2009/08/debian_and_the_problem_with_precompiled_packages/</id>
    <title type="html">Debian and the problem with precompiled packages</title>
    <published>2009-08-02T22:00:01Z</published>
    <updated>2009-08-02T22:00:01Z</updated>
    <link rel="alternate" href="http://dominik.honnef.co/posts/2009/08/debian_and_the_problem_with_precompiled_packages/"/>
    <content type="html">&lt;p&gt;On my desktop I use Gentoo. Not because I believe in the
performance gain of compiling the packages, but because I like the
freedom of choosing exactly what components I need, which is, thanks
to USE flags, surprisingly easy in Gentoo.&lt;/p&gt;

&lt;p&gt;The only problem: Compiling stuff takes its time, and especially on
servers I don’t like having to wait minutes up to hours on
installing a new package. (Not mentioning all the stuff about stable,
running releases and so on, thats another topic). So I use Debian on
my server, and most of the time, the precompiled packages
weren’t too bad, either.&lt;/p&gt;

&lt;p&gt;But today I faced a rather weird choice of the responsible people.
It looks like they compiled the php-gd extension in a way, that
doesn’t allow you to use the imageantialias() function.&lt;/p&gt;

&lt;p&gt;After some short googling I found
&lt;a href="http://blog.pirsig.net/apiBlog/entry/compile_php5_gd"&gt;a blog post&lt;/a&gt;
which explains how to get the sources (which, even in Debian, is
possible), change the rules (configure/build flags) and compile it on
your own.&lt;/p&gt;

&lt;p&gt;But that doesn’t explain their choice to not include the
function in the first place, not even providing an alternate
package.&lt;/p&gt;
</content>
  </entry>
</feed>
