<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Bruno Vecchi</title>
    <description>I write software for a living.</description>
    <link>http://brunov.org/</link>
    <atom:link href="http://brunov.org/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Throttler: a Clojure library for rate limiting</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/brunoV/throttler&quot;&gt;Throttler&lt;/a&gt; is a little Clojure library I wrote a few weeks ago. As the
name suggests, it limits the throughput or speed of something: either functions
or &lt;a href=&quot;https://github.com/clojure/core.async&quot;&gt;core.async&lt;/a&gt; channels.&lt;/p&gt;

&lt;p&gt;Here’s an example, straight from the library docs:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;c1&quot;&gt;; A slow + function&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throttle-fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; =&amp;gt; 2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &quot;Elapsed time: 4245.121 msecs (47/second)&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The new function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+#&lt;/code&gt; is equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;, except that it runs at a measly 50
invocations per second.&lt;/p&gt;

&lt;p&gt;The same goes for core.async channels. &lt;a href=&quot;http://brunov.org/throttler/throttler.core.html#var-throttle-chan&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throttle-chan&lt;/code&gt;&lt;/a&gt; takes
an input channel and a goal rate, and returns an output channel that will emit
all messages sent to the input channel at the desired rate:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;chan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slow-out&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throttle-chan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;gt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; =&amp;gt; true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;lt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slow-out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; =&amp;gt; :hi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;gt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;lt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slow-out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;  =&amp;gt; &quot;Elapsed time: 4893.739 msecs (10.2 msgs/sec)&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is equivalent to &lt;a href=&quot;http://clojure.github.io/core.async/#clojure.core.async/pipe&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.aysnc/pipe&lt;/code&gt;&lt;/a&gt;, but with a controlled output
rate.&lt;/p&gt;

&lt;h2 id=&quot;shared-throttling&quot;&gt;Shared throttling&lt;/h2&gt;

&lt;p&gt;You can also limit the &lt;em&gt;combined rate&lt;/em&gt; of a group of functions. Let’s say you
want to throttle your own usage of an external service that you don’t control.
You’d want to limit the number of API calls you make, making sure you stay
within budget and/or your paid quota.&lt;/p&gt;

&lt;p&gt;Here’s how you can throttle a whole API with Throttler:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;c1&quot;&gt;; Create the api throttler with a goal rate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api-throttler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fn-throttler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; Wrap all API methods with the same api-throttler:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some.api&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get-slow&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;api-throttler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api/get-user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put-slow&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;api-throttler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api/put-user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;del-slow&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;api-throttler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api/del-user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get-slow&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;RuPaul&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; -&amp;gt; { :name &quot;RuPaul&quot; :coolness ∞ :age &quot;Don't you dare&quot; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What happened here? We created a &lt;em&gt;function throttler&lt;/em&gt; with a goal rate,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;api-throttler&lt;/code&gt;, and applied it to the three functions in the API. Now you can
call the slow versions of &lt;em&gt;any&lt;/em&gt; of the three functions, in any proportion, and
their &lt;em&gt;overall&lt;/em&gt; rate will never be beyond what you specified.&lt;/p&gt;

&lt;p&gt;The same can be achieved with channels, using the &lt;a href=&quot;http://brunov.org/throttler/throttler.core.html#var-chan-throttler&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chan-throttler&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;h2 id=&quot;burstiness&quot;&gt;Burstiness&lt;/h2&gt;

&lt;p&gt;Sometimes an average goal rate is not enough. Let’s say you want to make no
more than 10,000 calls per day to a service. That would be around 0.11 calls
per second, or about one call every 8 seconds.&lt;/p&gt;

&lt;p&gt;If you haven’t called the service in a while, but suddenly you need to call it
twice, the second request would have to wait for 8 seconds. So both of your calls
would take no less than 8 seconds to finish! This is because, by default,
Throttler enforces the goal rate with a millisecond granularity. At any moment
you can pick a random time interval, and the number of calls in that time range
will be at most the goal rate.&lt;/p&gt;

&lt;p&gt;In this case though, we’d like to just keep ourselves under the maximum number
of requests per day without caring too much about occasional request bursts.&lt;/p&gt;

&lt;p&gt;What we need is a &lt;em&gt;bursty throttler&lt;/em&gt;. The intuition is, if you haven’t used a
throttled function or channel in a while, then you get “credits”, or “tokens”.
Later, if you need to make some calls in quick succession, you use these
credits and the calls execute right away. This is the main idea behind the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Token_bucket&quot;&gt;Token-Bucket algorithm&lt;/a&gt;, which is how Throttler supports
burstiness.&lt;/p&gt;

&lt;p&gt;To create a bursty function or channel, you simply pass an extra argument
stating how many &lt;em&gt;tokens&lt;/em&gt; you are allowed to save up:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bursty-api&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throttle-fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:day&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; Save up to 1000 unused tokens&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bursty-api&lt;/code&gt; may be called up to 1000 times in rapid succession,
provided there are enough tokens saved from previous periods of
quiescence.&lt;/p&gt;

&lt;p&gt;Let’s see how a bursty function behaves in a benchmark. The function we’ll test
simply prints out a timestamp:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;System/nanoTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now-bursty&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throttle-fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:second&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The throttled version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;now&lt;/code&gt; will print at most 10 times per second, with
bursts of up to 20. Let’s exercise it with the following plan:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;now-bursty&lt;/code&gt; 30 times. This should take 3 seconds.&lt;/li&gt;
  &lt;li&gt;Sleep for 2 seconds. This should fill up the bucket with 20 tokens (10 per
second, the average rate).&lt;/li&gt;
  &lt;li&gt;Call the function 50 times. This should result in a burst of 20 messages,
followed by 30 messages at 10 msg/second. In total all 50 calls should take
about 3 seconds.&lt;/li&gt;
  &lt;li&gt;Sleep for 1 second. This should save up 10 tokens.&lt;/li&gt;
  &lt;li&gt;Call the function 50 more times. We should see a smaller burst of 10
messages, followed by 40 messages at 10 msg/second. This last phase should
take 4 seconds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In code, this looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; 1. Call fn 30 times&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Thread/sleep&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; 2. Sleep for 2 seconds&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; 3. Call fn 50 times&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Thread/sleep&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; 4. Sleep for 1 second&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; 5. Call fn 50 times&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;now-bursty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is what the &lt;a href=&quot;/assets/bursty.txt&quot;&gt;data&lt;/a&gt; looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/bursty.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the bursty function saves up tokens during inactive periods and
is able to rapid fire after that. The invocations right after sleeping (steps 3
and 5) are executed at the maximum speed possible because the bucket has
unused tokens at those points. This way, the overall goal is still honored.&lt;/p&gt;

&lt;p&gt;Had we chosen a smaller bucket size, or slept for more time, we wouldn’t have
been able to catch up entirely.  Just how much burstiness is allowed is up to
you.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/brunoV/throttler&quot;&gt;Throttler&lt;/a&gt; makes it easy for you to flexibly control the throughput of
functions and channels. It’s lightweight, &lt;a href=&quot;https://github.com/brunoV/throttler#throughput-accuracy-over-a-wide-range-of-rates&quot;&gt;precise over a very wide range of
goal rates&lt;/a&gt; and fully asynchronous (it does not require dedicated OS
threads nor it assumes that the wrapped function takes negligible time to run).
And thanks to &lt;a href=&quot;https://github.com/clojure/core.async&quot;&gt;core-async&lt;/a&gt;, the implementation is &lt;a href=&quot;https://github.com/brunoV/throttler/blob/master/src/throttler/core.clj&quot;&gt;quite short&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comments? Let me know on &lt;a href=&quot;https://twitter.com/BrunoVi&quot;&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Wed, 14 May 2014 00:00:00 +0000</pubDate>
        <link>http://brunov.org/clojure/2014/05/14/throttler/</link>
        <guid isPermaLink="true">http://brunov.org/clojure/2014/05/14/throttler/</guid>
      </item>
    
      <item>
        <title>New Blog</title>
        <description>&lt;p&gt;I decided to start blogging again. A lot of stuff has happened since I &lt;a href=&quot;http://zerothorder.blogspot.com&quot;&gt;last
tried&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

</description>
        <pubDate>Tue, 13 May 2014 00:00:00 +0000</pubDate>
        <link>http://brunov.org/2014/05/13/new-blog/</link>
        <guid isPermaLink="true">http://brunov.org/2014/05/13/new-blog/</guid>
      </item>
    
      <item>
        <title>Embedding images in POD</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
&lt;a href=&quot;http://szabgab.com/blog/2009/11/1259059996.html&quot;&gt; Gabor's post&lt;/a&gt; lamenting the lack of image examples in image-related modules (like charting) reminded me that once I bumped into a module that &lt;em&gt;did&lt;/em&gt; show images in its documentation. They weren't links to images, but actual images, showing there in the CPAN search page.&lt;br /&gt;&lt;br /&gt;I couldn't find that module again to see how it was done, but after a little googling and talking to some freenode #perl folks, we came up with a way to do it.&lt;br /&gt;&lt;br /&gt;Behold:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;=head Title&lt;br /&gt;&lt;br /&gt;This module is awesome because it deals with pretty pictures, like this one:&lt;br /&gt;&lt;br /&gt;=begin html&lt;br /&gt;&lt;br /&gt;&amp;lt;img&lt;br /&gt;    src=&quot;data:image/gif;base64,[gibberish here]&quot;&lt;br /&gt;    alt=&quot;foo&quot; width=&quot;42&quot; height=&quot;42&quot;&lt;br /&gt;/&gt;&lt;br /&gt;&lt;br /&gt;=end html&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;So the trick involves escaping the image source for non-html readers of pod (surrounding the img tag with &lt;tt&gt;=begin html&lt;/tt&gt; and &lt;tt&gt;=end html&lt;/tt&gt;), and using a base64 version of the image. I found this &lt;a href=&quot;http://www.motobit.com/util/base64-decoder-encoder.asp&quot;&gt;service&lt;/a&gt; to convert binary images into their base64 representation, which even lets you choose the column width of the resulting string.&lt;br /&gt;&lt;br /&gt;It's a workaround, but having an example picture or two in some of the many plotting and charting modules out there might be very well worth the effort.&lt;br /&gt;&lt;br /&gt;Here's a complete example, with an actual image. Copy it to a pod file, run &lt;tt&gt;pod2html&lt;/tt&gt;, and see the resulting .html document in your browser:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;=head Title&lt;br /&gt;&lt;br /&gt;This module is awesome because it deals with pretty pictures, like this one:&lt;br /&gt;&lt;br /&gt;=begin html&lt;br /&gt;&lt;br /&gt;&amp;lt;img src=&amp;quot;data:image/gif;base64,&lt;br /&gt;R0lGODlhTwBGAOf/AEsvHV8/KXNML3lKMm1NOXFNNH1PLoVPMXZTOXZTQINSOINTPotRPX5ZP31a&lt;br /&gt;R5tVQIpcOZNaO5VZRJFdQ49eSYVhTYliR7FZRIZlVa5cRYVmW6dfRoFqSpFmX8BcR8NfP6VoR85c&lt;br /&gt;SN5YR6JpUpptRLhlS5JvX75kS5FvZZhvWZlwUIx0U5BzV5BxbbRqTrdrRcxlTYt6U5h4TYx8TtFp&lt;br /&gt;SdlmUuRkUd1nTbN1U515cqh6SaV6W7h3RqV6ZKN+RKF+SpSCSbF3Ybh3Tax6U6R6bM5yV52DRa5+&lt;br /&gt;R5KGS9hwV8R4RZiFRpOFVaSDQJmEV8V4VpWIR8J5YZuIQvNrYJ+GTvFwXpuOTKGNTbaHUaOOSMaD&lt;br /&gt;UvF2VcKDYa6MQ/B2W5+QSLuGXOR6XpiRW6+MTbeIZcCHVqmPTO94ZNSBYL2KTayOWqORV6GRXrSQ&lt;br /&gt;QKqPaaCUV6+TR6yVSKqVT6WXTuODYp6YYKiYScOQTLOWRLqPeciOfPWFXtiMdciVUK+eT6qgT9WS&lt;br /&gt;XfSIZbKdXK2fV7ubWNOSbsmVbr2cUuOPabafUfaJcMebTbafWL+eSaiiac2YYbydZ7OgZs6bTq+j&lt;br /&gt;ZbikT7alVbWlXLGnVbCnXK2naPeUcburYdmkVr+sVb6sXLmuXcOrX82pW/eaddalb9CnbsCsb9Sp&lt;br /&gt;UtekfLaxXsmqbLyubuKhgbawb9+laMiuVrKycOKmY76yWbu1W/GhiMa0VcezXMWzY8C1YvWjfO6o&lt;br /&gt;dc+xjdutl/Oomc26ad20etS6ZO6tmsq+XtC8ZeyyeO2zbsq+a9K9X/Svi8y/ZtS+WeqykMy+edm9&lt;br /&gt;Ydq6ft66c9a9ctO9fc3Bdf24ifu4keTFW/i4ptTJfNzIcNvGh+DHfvy+idvJfuDKZ+fEkdHNfuvF&lt;br /&gt;huTJddXOdPjCidbNhtzObdvOdNvMi9XPjubJofvFmvTGqfbKf9rSl+TUc+TVfOvUdN7VoePXid7W&lt;br /&gt;qObWqu7SvN7YsOXYsvzVmOTZufzZpf/atf3cre/huv/lvv7v0v324ywAAAAATwBGAAAI/gDt4Rto&lt;br /&gt;T6DBeQUT2pOn0B7Chg3rwbNmzZvFixSXWVu2TJWqSKVCelQ1iY0TJo4meWTF6lUmVpliOqpTZ95A&lt;br /&gt;ghBz6iz4sKA8eByjVfRG8WK4aCNDqiylMhKbp0ycsFHF8lXLmK9czsSGTyC+evbA7lTYM6HYemCD&lt;br /&gt;CqXItqK1kR5DhoxE96lUJ5GoZmXpKJPVrI66ehWcsGu9roTFIpT3E548sGKjcVwWjWhRipJVLZML&lt;br /&gt;qbOazyZXiObAsmrLrFZjol19GGfYsPXKOoTHjh3t2o4Z11Mb7Wi0tUSjyS21ShSiMDROuNixggMH&lt;br /&gt;0ayolv4LM5MjeV+/rn4N8WHP2uDP/olnJ55yr9+Vf7u11iukL16i4geiAQPGiQbOnUfXi9qvdUeQ&lt;br /&gt;HcbaTYKhRVhYjN0mnnjjbNQLZb9ZNBRmpaQCDC+ziKJJIGEkUZ8HGVCQH1UrWQXTK305cs5jrG0n&lt;br /&gt;kIs8FVZPbQui14s15WAWTlvWNFjNj7jgsuF8NcDgwZEPWMCBE2qQNElVVjkipSPuOIYWYwv9xBBP&lt;br /&gt;tPU0zzw/nUPjONss88w22TjjTJpqNgNNM80oUw2G8W24xw031BDCkR6cAAJdkUwyiZSnsTITTe64&lt;br /&gt;YxtD8+BG3jlgngOPeF96N4852GQKZzNtqumpM774kgsus2SoyamB7LGFFzXoeeQF/hm4AAZdgqry&lt;br /&gt;Ekw05eoOOKVAY45tC46z4DnmnCPsr+x8iQ463Wwaqi/OcKpmqKOMMoyQpyqCaiCBrGpDq3t6cMED&lt;br /&gt;LgwRaK1TZpJrHY6AQ0hn48Qrr7DCMjiON+Ng2mwz3XTji7/PBlxtK4iIosjBCCuyxx5eqLrFt3te&lt;br /&gt;MO4DJ6hxbkqT/CdlrirIoEaiicYTzrzD4ovvm80E7Eu1LA9MhyYHn6HIGTSf4cXNXlSRsw3fivvA&lt;br /&gt;AxIsMAEk5wo66JQ0iVEHyEyDPG+81oQTTzlEobzyyi1XG0bNXE9Rxddg4+xFz+NKEPQCFgyyBsZG&lt;br /&gt;C6pu0om+I/fc7bSTaI/jJBrO/t7hlFPOM3BinTUaZ2w9hddfIw52zVXwvCfQC0S+AAWRrMGGlEZH&lt;br /&gt;N4nSNNU99+fv1A2y6H6XDg44zpBCStaPJJFEDWdUcfjssiv+Nc96XiABBZIz8AADMlAhFRtPsqRK&lt;br /&gt;HWKwIYbnoIPezuft+F136c+kkorqqnNRRBH11WDDFDRXETvYX99c5AknlJDBBR6EwL7EEm8wQwxi&lt;br /&gt;RDfI5mKIEfrzzcudKP+hK4c7pue3YvQiFYQghPUKgYYioA99rvNCGLZGM9e5rkMdcl0NcraF+hhJ&lt;br /&gt;AgTgQAxiwIRJWOJ+SaubCpm3vwGucIXkCEc7yFGOYkSiF89wxvUQ0cASuKAE/tsrwgTDgAY00AEN&lt;br /&gt;T3iCEOnwMkXcbAsdLAHQKIAAJ5CQCWx4wyTewAbkvfCLdmNaOcixP3KY0Yx7K4YaK3SKIj7BBXAc&lt;br /&gt;hjgQgYgn7GAHKtgBGcCQj370Qx/5EMcwGAiCBBCgAAVowAhPwoTkaRF5ywujDN2xNxyVboxjJCM3&lt;br /&gt;ZohJGpbjGmq0HiiiwIVS4kCO/crFGcpgARXkkQz78Ic/+pGPfejCAmiwACILsIIYzGAGTAimI7Po&lt;br /&gt;xXbwbW9+QwYyLmnGd5ixbjEMxzWmWY5wqLEXhKDHKcgwhCHkQhz36IYgEZGLVr7yHrL0xz74YQE3&lt;br /&gt;DKOXwQzm/ICJxTq8gYv5/lMhDcOBDDUWQ5nXmKHcuMGNM55RmWq05j/poU0cuFIc4shHLb8xjHK6&lt;br /&gt;EgyFQOcs8/EPCLjTijNg5Ah/ScKn5C+foeNGP6+JjGAgQxi/uMY7CkpQg/KzGLe4BUsZCowgpMAC&lt;br /&gt;udBGRCUKziHIYAhk6KM//tEPdKqgGesAQxmwIAMs/EAGIgzmCPPXSDEQlBvGEEYvrikMY7xUGNfg&lt;br /&gt;xjWQcQ1joJGfK7WFLXrRC2EwVA/ASEEDSPDNe+zDj/sQhzTE8del/oMMuvCHMu6xDm0MYxiteAQg&lt;br /&gt;0oBVX86vq2J4gzBgGlax0vWlytwsMuiKVmWaFqHFkKst7KoOPazCAg1I/kADvvnXfuxDH7dN5z/c&lt;br /&gt;wAIW+OIb90iHUAXZCkAA4ggyIOkVxYAEzW52swYUxmjrutlr0BUUtlCmS0/rT9LSo7V6gC0CCoBL&lt;br /&gt;wt7Wj/2Q5T/+gQAWEIAAvpDGNLRB38cWVws8YAISfgnMNwxiEL2oBWhXigzV2uIXv7AFKBgBClD0&lt;br /&gt;4hahjXAv5tqL7+phFztAwHjJiwZcpEMf+vCjev+hAfceEhfSkAZ9iQsI/K4BCPRkwhswgYlbyPWf&lt;br /&gt;ZxWGXD3hCdVughEMBoUnQHHWHIvVrhY+RQN2iQAVzAIXIA6xbivAggBYmQDHmIaKHZuLFvPACoNA&lt;br /&gt;whrWwIEZ11iuEH6u/o49sYlN9JjNQG7wkIcMis0agxnG+IUw8EGPPKTAAQXYcAEogAhcTAPEf9SH&lt;br /&gt;LHVRZSsHgAu4OIY0HtviFwhhEPccMxNojAk0m3bCO+Zxm9ssiDgLmcdD/gUzVs2MX6SCDD8dr6AX&lt;br /&gt;EAVReDgduFa0LFkAAEcHIEjSyEUuEPGCFxBiEFZ4wxoGQeNNfALNBka1qEf9YyAzws1upnMoWn2K&lt;br /&gt;PLAAAw6ogAMWMIByD0ByhZ4GrnOtj2EUwNdo4CEaXLABELgZE3NI9htQ8QlUoKIWt6iFwKU97U1Y&lt;br /&gt;wuBAFkSpPWGJgzcYFKE4RQ9MQPEKWHwC5Ca3AiJH6EhP4+Mfl8YT/t4dgASMYARmWwAVBOGJT1hi&lt;br /&gt;Dsr+b78DLnBb1ILg2W64wS3BCIUzouENBzIhTpECiqMABRjAQA8moIANMGABDGDAxikQ70gHCReI&lt;br /&gt;cEEEJhCAa3/i6wxv+SeQDWZm8/sWsRB4LWwRdlEDfeeDsPbPB9Fwup+C4hhAQQs0gIEUBCECEdjA&lt;br /&gt;z34n9cm54AlFdOMGJKADHtP4Epf4RORjIYtLMBsTMr/FJ2q+doZXohJuroQlQB/3hNO97oMQBCQm&lt;br /&gt;nvSj8x0FQdjAD0uwgQycgPAKQIAFKDCCCUgABEGTM+Qhjwl/y0IWn8DEJWg8B0x8Au015/HoQf95&lt;br /&gt;hm+i9NYG+n8H/uEGiyddA+DvQAeCAMcSKGcDMPhABh4wgQE4+AckCAAExvALIVdC8sqPPCqOj3x+&lt;br /&gt;f6LNX1cLneAJogd001cJBFgJjCAHpSYIdDd3CtcDFZB0FUBxGtABJhB76AMDtAcDN+A+G4AF2OUJ&lt;br /&gt;oVCCJShknEZj/oYKkId8X+d/XzeACsgI//V5lkCAQLeAgkAKNJh9CpcCSYcBFWABKYAC4NcDP+QB&lt;br /&gt;9uECJ4AnHlACQgAKaucKJoiCjzd8qKB8/faC/tZvBOgJ1jYIfuAHCFgJpUcI30AMrdAKsFBqOigI&lt;br /&gt;eCeEGGB0KGACI+ACMBACe3ICHpgcF4BdNlYLriBnXNiFl4AK/n8AeZ8QC7cgCyt4CWVYCYlAg4kg&lt;br /&gt;hnEnB4yQQJBlXI+QBoSgcIKgBnlgAkGoAXVoAhqQgRtQAnkIIh5wAzSgfkJ2Cy2Hap3wfPvXf5CX&lt;br /&gt;iIsYC5S3gpjweYkwjMNICIlACJmYQIRACsWlBEogBGRgCKCYB3mAdOBnikdHihQQBCNQAnuSAa9I&lt;br /&gt;Ax6wAaBwf2zHdjz2db7oiCwIeZWQdrTQUshwCywoicSYCIcACoegjAl0B5KFXziAVGRwCgSZB0Rg&lt;br /&gt;hNeIjaRocSkgARIDjjAgjhngCYnQY+fYYwPoi5TniJAYC7TADckQDCIZDJJnj4fQCI2wCIewj2OA&lt;br /&gt;BS6JBVog/gRCAAJ4pEdkQAYGmQNHt3fXiHTg5gAJEDk/YwN4EgInkAEgMASmNARgMAQ6QAhoJwsb&lt;br /&gt;KQuV0AnMQA3UkAxaKZKXQIyh4AqmEAqmsAiEkAYvWQZCgAM4sAMpoAI98JY9cJB61wI8yXfgB24J&lt;br /&gt;kACIdG4hIAIisIc4UEqCCQZNOQQaSXkaSQtYmZXJAJLBgArDeAhiOZaScAdpYJYuWQZqSZNt+ZZF&lt;br /&gt;ZwIokAN0WZfgJm4OQAB6iUgR4AF+aQMcKJhcUAiGQJjdVAuH6Yu0kAyrBpIh6VKQiY+HsAiS0AeW&lt;br /&gt;eZkuqQVqiQOcmQIpMHEmkAPQOZrX+JN5+V4bBgIX0Jch/gADaFAIXMAHq6AMpzCbtXl8GlkLWmkM&lt;br /&gt;6TmSjjiJcDAGLXmZ8okFSJRET4ADQRAERBCXRACd/ima4AeUQJmXhnRICvACg3cCRcAHfDALwAAM&lt;br /&gt;yhChswkGthkMtICbzJAM6kkLHHqhX+cHiWAG8HkEWDCfQmCfUZCiQcCf/fmf0Il0A4oAh5SXMpoA&lt;br /&gt;GBc5CsAAGxAFfMALP1IN6qAMhQAGOmCbHJqYHeoKtNAJTAp5cQefP/ADJFqiZeACIOACOICl+ZkD&lt;br /&gt;JkAERECKc3h0MFqg1pkAGoaaOsA7DtAAk8OjvOCjP6IMhjBVSnqhvtgJscCkneAKrkAJnTB8YpgF&lt;br /&gt;UPoD/jpAojwAAoiaqCPAnEE4geHmAEk3oEwWaBqWAFEqbgS6jW7qo8BwDIVQBoewanbaCZTwjrHg&lt;br /&gt;p33qB3+wqnMwB1dgBCIapYUKeBGAqBNwqxYnbpiaAA7QqwPaAAggA4ekYRaAACupAr2alw7Ae/nZ&lt;br /&gt;o7wADKvwqaHqCnjKpJRwraRaqpWgqqsqB3KQBbA6Bj4wrjoAARBAqwrAdBVAoDTargjQABYAASvZ&lt;br /&gt;CIfwA2PACZKwCF1gAQMabhVAAQDrpqVSCFhwCJTQp56gp9dKhts6htwqB3FgBllgBkbgA7IaARBw&lt;br /&gt;AICnAApAAcCqYbIWaIFmAT9ACIdAjCspnJJgCl3Q/gC+2qsLsHELMAINOrA6MIx+6o6VcLAOu6o+&lt;br /&gt;+wffegVZ8KpjIKsQoAAHYAAQYAACYK4kQAJmELVjIJmNQAnEKIkgGpyLYApc2wcWMIEVEDkDoADn&lt;br /&gt;NjmI6pSJMIbbegkO27N+MAis+gd2MAdDewV2ewXj6gPmagBK67Q+MIwmOa+UoLYOmwiUsAiIu7KL&lt;br /&gt;oAIWF5Qc+7gcOwEkoAMOewk+C7djeLlzwKpzmwWeK7SfKwdNoLfm6rRQGwdycI/32LZjOIwpibiL&lt;br /&gt;ULTwKjQTwAAHcADlBgEkcARjaAd/ALeY8LN/oKqD0KpzYAfIS7ef67meGwfOGwcWqwM+YAbeWr1+&lt;br /&gt;/hAHxGi1Yzi4hbuS3ksIYwABtxp1SGsAAwACPDAGDuu7/2UHcPu7rGq8yBsHyCu0S7AEzHsFz5sI&lt;br /&gt;zisHc+CtcTAHqGsHqpu2vVu4/AsHChwHY0AC51q+fAsCZUC9g4C8duAHxsutrVq88ju/eEAFV3C/&lt;br /&gt;Qku3EDuGcmAH3nq8reqtKIzCcsC6x+sHyHu9EOutWfADe2sAGssDR8AIrXrBczu3xvsHxlvEx2sH&lt;br /&gt;cYAHjbAEIczEWSAHX4DE9Iu6KrzCLbzC/3vBY/jDFty/NnwFJMC3EfAC6QsHc/AFVtCqX2DEbHzG&lt;br /&gt;R2wHStwIVGAEInwFb+zC34rFRVy9P9y7XxDF/snbqp57xhNrri9wBF1Av3+cxvkGBWv8w/5bxGk8&lt;br /&gt;vyjZCEBwv5h8BV/wrVmAxpp8t3ZsxGicBcqLxn/8yIRsBX/suWYwvZF8xmhsBVAwy468yXEAB86b&lt;br /&gt;BVawy2ccB5W8CEYQzJjMxEuwyFbQxMjMyPm2y6rMzFBQzMrLvJ38BdL8x8bLzLIMBbsstGYABygZ&lt;br /&gt;B8ZMzd5cycEszPcrBec8zEBwyezszLLczNqMyU8csZ5LzaesyqdszNk8y7I8sXCAB3ggscycBQpc&lt;br /&gt;yY3QBAhtzsOMyevc0EgABEiAzZdMy7O8BFDQvJ67y6bMzPl8yrSczVYgBWbQBXgAB/U8y1nQwAVt&lt;br /&gt;YNBd0AUJTcfDDAUPDdEzDdEQLdPPrM1QIAUUTc3SzNPYjM/6TNE6jb9RKwVZQNEETdKVrNIvfb+0&lt;br /&gt;vAQNDWMOjQRQAAQ6TdQfTc1IndS7rM2yjMY8TctIUNYyDdK6/AVEfQVN0AX/3Agt7dJNANM4/cxS&lt;br /&gt;DdEzYNM3bdZaTdG7LAVIrdZfIAWLvNNEXdZ83dezjASY3AQiGtcI/dQ5fb9T/dBmjdh9LdW0DNhZ&lt;br /&gt;QNiKTdagLdNWfdh8fcnl3AQBAQA7&amp;quot;/&amp;gt;&lt;br /&gt;&lt;br /&gt;=end html&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update:&lt;/em&gt; &lt;a href=&quot;http://twitter.com/confound&quot;&gt;confound&lt;/a&gt; told me that apparently data tags don't work with IE6, so if you are planning to do this in your module, take it into consideration.
&lt;/div&gt;
</description>
        <pubDate>Wed, 25 Nov 2009 15:18:00 +0000</pubDate>
        <link>http://brunov.org/2009/11/embedding-images-in-pod.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/11/embedding-images-in-pod.html</guid>
      </item>
    
      <item>
        <title>Baby Haskell and Good Old Perl</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
I finally drank the &lt;a href=&quot;http://blog.woobling.org/2009/11/functional-programming-and-unreasonable.html&quot;&gt;functional&lt;/a&gt;, &lt;a href=&quot;http://blog.woobling.org/2009/05/immutable-data-structures.html&quot;&gt;immutable&lt;/a&gt; and &lt;a href=&quot;http://blog.woobling.org/2009/11/restricted-perl.html&quot;&gt; pure&lt;/a&gt; koolaid and started reading &lt;a href=&quot;http://www.iro.umontreal.ca/~lapalme/Algorithms-functional.html&quot;&gt;some&lt;/a&gt; Haskell &lt;a href=&quot;http://learnyouahaskell.com/chapters&quot;&gt;books&lt;/a&gt;. And to exercise a bit, I began to tackle some of the problems from &lt;a href=&quot;http://projecteuler.net/&quot;&gt;project Euler.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Problem 10 states: &quot;Find the sum of all primes less than 2,000,000&quot;.&lt;br /&gt;&lt;br /&gt;After finding out that it's only necessary to check for divisors less than the square root of the number, I blatantly stole this version from the &lt;a href=&quot;http://www.haskell.org/haskellwiki/Haskell&quot;&gt;Haskell Wiki&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/241964.js?file=gistfile1.hs&quot;&gt;&lt;/script&gt;&lt;br /&gt;If this doesn't give you a nerdgasm, I don't know what will. It creates an infinite list of primes by filtering an infinite list of odd numbers with the isPrime function. This function, in turn, uses the primes list itself to look for potential divisors. So basically, the list is defined recursively. &lt;br /&gt;&lt;br /&gt;The solution then boils down to getting all primes smaller than two million from the infinite list, summing them and outputting the result.&lt;br /&gt;&lt;br /&gt;Anyway, this beautiful solution got me wondering how the perl version would look. Here is my first attempt:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/241965.js?file=gistfile1.pl&quot;&gt;&lt;/script&gt;&lt;br /&gt;Ugh. I mean, it's not &lt;em&gt;that&lt;/em&gt; bad, it has some interesting things going on like having an infinite stream of primes, but after being embelished by the Haskell version, this seems uninspired at best.&lt;br /&gt;&lt;br /&gt;But then I thought that being CPAN (and not syntax) Perl's strength, I should take a look there. After no more than 30 seconds of searching, I found &lt;a href=&quot;http://search.cpan.org/~bubaflub/Math-Primality-0.04/lib/Math/Primality.pm&quot;&gt;Math::Primality&lt;/a&gt;. Look how the Perl 5 version looks now:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/241968.js?file=gistfile1.pl&quot;&gt;&lt;/script&gt;&lt;br /&gt;This put a smile on my face. Perl may not be the most beautiful language around, but it has a JFDI attitude that I have yet to find elsewhere.
&lt;/div&gt;
</description>
        <pubDate>Tue, 24 Nov 2009 16:14:00 +0000</pubDate>
        <link>http://brunov.org/2009/11/after-drinking-functional-immutable-and.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/11/after-drinking-functional-immutable-and.html</guid>
      </item>
    
      <item>
        <title>Do What I Mean: Moose Types and Type Coercions</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
API's should be simple. I hate it when a module that solves a non-trivial problem requires the user to make non-trivial decisions about every single detail in the domain problem.&lt;br /&gt;&lt;br /&gt;In my opinion, a class should be smart enough to make all the reasonable assumptions so as to require the least possible amount of input from the user.&lt;br /&gt;&lt;br /&gt;This might seem a little dangerous, and can certainly be if the approach is taken too far (&lt;a href=&quot;http://search.cpan.org/%7Eingy/IO-All-0.39/lib/IO/All.pod&quot;&gt;IO::All&lt;/a&gt; is for some people an example of too a DWIMmy API), but there's a healthy middle-point in which the user is not only able to rely on the module to solve the problem at hand, but is also spared of most of the cognitive load that solving that problem requires.&lt;br /&gt;&lt;br /&gt;It is very probable that someone looking for an already-cooked solution in the CPAN is not only not willing to code it up for himself, but also doesn't know enough about the problem to do so (at least not initially). This person is going to rely on the module's wisdom, and the least that it's asked of him, the better.&lt;br /&gt;&lt;br /&gt;One of the &lt;a href=&quot;http://github.com/brunoV/bio-tools-evolver/tree/master&quot;&gt;modules that I'm working&lt;/a&gt;&lt;a href=&quot;http://github.com/brunoV/bio-tools-evolver/tree/master&quot;&gt; on&lt;/a&gt; deals with protein sequence optimization using genetic algorithms. The user has a collection of protein sequences phylogenetically related, and wants to produce an optimized sequence for a custom trait (solubility, hydrophobicity, digestibility, etc) that still belongs to the original protein family.&lt;br /&gt;&lt;br /&gt;Under the hood, the algorithm that I implemented requires a &lt;a href=&quot;http://en.wikipedia.org/wiki/Multiple_sequence_alignment&quot;&gt;multiple protein alignment&lt;/a&gt; as input, or profile. Naturally, the methods that do the heavy-lifting expect a &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/SimpleAlign.pm&quot;&gt;Bio::SimpleAlign&lt;/a&gt; object. But the complication is that protein alignments can come in lots of different formats, many of which are also shared with plain protein, RNA and DNA file formats. Also, the user actually shouldn't be &lt;em&gt;aware&lt;/em&gt; that the module requires a protein alignment. Of course it should be allowed to provide one, but if the only thing he has is a bunch of sequences in a flat file, it shouldn't be bothered with opening (how?), parsing (what format? What is its specification?) and aligning (with what algorithm? Gap penalty who?) them to cater to my particular implementation. All he should need to give is a simple filename as a string.&lt;br /&gt;&lt;br /&gt;So to maximize for user convenience, I decided that the module should accept either of:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;sequence files of as many formats known,&lt;/li&gt;&lt;li&gt;alignment files of as many formats possible,&lt;/li&gt;&lt;li&gt;collection of sequence objects (subclasses of &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/examples/root/lib/Bio/Seq.pm&quot;&gt;Bio::Seq&lt;/a&gt;, also &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/SeqIO.pm&quot;&gt;Bio::SeqIO&lt;/a&gt; objects), or&lt;/li&gt;&lt;li&gt;alignment objects (&lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/SimpleAlign.pm&quot;&gt;Bio::SimpleAlign&lt;/a&gt; or &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/AlignIO.pm&quot;&gt;Bio::AlignIO&lt;/a&gt; objects).&lt;/li&gt;&lt;/ul&gt;In the case that there is ambiguity about whether the user supplied an alignment file or a sequence file (eg., fasta format is both an alignment and a sequence format), I'll make an educated guess and assume that it's an unaligned sequence. In the worst case scenario, It'll just realign an alignment. There is also an extra layer of guessing involved in determining what the format actually is in case that the file has an unknown extension or no extension at all (this is done by &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/Tools/GuessSeqFormat.pm&quot;&gt;Bio::Tools::GuessSeqFormat&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;All of this adds to the simplicity of the API in detriment of the simplicity of the underlying code. Luckily, &lt;a href=&quot;http://search.cpan.org/%7Edrolsky/Moose-0.82/lib/Moose.pm&quot;&gt;Moose&lt;/a&gt; has the tools to make this as straightforward and clean as possible, using Types and Type coercions. The coercion map looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://3.bp.blogspot.com/_dJsDskOH5ac/Sj_i7sO7d5I/AAAAAAAAABY/jx5pi1w8ZRg/s1600-h/Diagrama1.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 265px; height: 320px;&quot; src=&quot;http://3.bp.blogspot.com/_dJsDskOH5ac/Sj_i7sO7d5I/AAAAAAAAABY/jx5pi1w8ZRg/s320/Diagrama1.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5350244397453375378&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And the code that implements this is simply the following:&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/134158.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;What's better is that all these types and type coercions are defined separately in a type library that uses &lt;a href=&quot;http://search.cpan.org/%7Erkitover/MooseX-Types-0.12/lib/MooseX/Types.pm&quot;&gt;MooseX::Types&lt;/a&gt;. They deal with both the input sanity checking and the type coercions. This way, not only this complexity is hidden from the user, it's also hidden from the main application. This is really helpful, since now most of the code in the module's main file describes the class behavior and it's not coupled with nor hidden by the juggling of all the possible user input types and input validation code.&lt;br /&gt;&lt;br /&gt;Now future users of this module (most probably only myself) won't have to check the API's documentation &lt;em&gt;that&lt;/em&gt; often; whatever representation of a collection of protein sequences they might have will serve as a valid input. I believe this to be a nice design choice.
&lt;/div&gt;
</description>
        <pubDate>Mon, 22 Jun 2009 19:57:00 +0000</pubDate>
        <link>http://brunov.org/2009/06/do-what-i-mean-moose-types-and-type.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/06/do-what-i-mean-moose-types-and-type.html</guid>
      </item>
    
      <item>
        <title>Superloading Devel::REPL</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
Today I bumped into &lt;a href=&quot;http://search.cpan.org/%7Eadamk/Class-Autouse-1.29/lib/Class/Autouse.pm&quot;&gt;Class::Autouse&lt;/a&gt;, pointed by &lt;a href=&quot;http://search.cpan.org/%7Erjbs/App-Cmd-0.203/lib/App/Cmd.pm&quot;&gt;App::Cmd&lt;/a&gt;'s docs. Essentially, it lets you defer the importing of a module until the code actually tries to use it. So, for instance, if you have:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/117747.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;The program will load Deps 1..10 before executing Dep:2's constructor. However, with&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/117748.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;Only Dep::2 will be use-d before the instantiation of &lt;span style=&quot;font-family:courier new;&quot;&gt;$thing&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This can be very useful in cases where an application's flow can take several different routes, and might not use all of its functionality in a single invocation. &lt;a href=&quot;http://padre.perlide.org/wiki&quot;&gt;Padre&lt;/a&gt;, the Perl IDE, for example, makes extensive use of this module exactly for this reason.&lt;br /&gt;&lt;br /&gt;But another cool feature of this library is its '&lt;span style=&quot;font-weight: bold;&quot;&gt;:superloader&lt;/span&gt;' option. It allows you to import dependencies on the fly without explicitly saying so. For example:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/117749.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;Here, we don't predeclare any class in particular, we just use it. Notice that I said &quot;class&quot; and not &quot;module&quot;; this only works for object oriented libraries, ie., classes.&lt;br /&gt;&lt;br /&gt;What's most useful about this is that it can be very convenient in cases where you don't know beforehand what classes you will be needing. In particular, I think this is a perfect addition to my &lt;a href=&quot;http://search.cpan.org/%7Eoliver/Devel-REPL-1.003006/lib/Devel/REPL.pm&quot;&gt;Devel::REPL&lt;/a&gt; configuration file:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/117750.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;and then:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/117751.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;Since I'm mostly doing exploration and debugging when using the REPL, correctness is not an issue, and not having to load things beforehand increases the whipuptitude and overall improves the coding experience.
&lt;/div&gt;
</description>
        <pubDate>Mon, 25 May 2009 20:55:00 +0000</pubDate>
        <link>http://brunov.org/2009/05/superloading-develrepl.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/05/superloading-develrepl.html</guid>
      </item>
    
      <item>
        <title>A sequence translator folder using POE::Component::DirWatch::Object</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
So, I admit it. I hate coding GUIs. Probably because I don't have much experience doing it, but I hate it nevertheless. So when I bumped into &lt;a href=&quot;http://search.cpan.org/%7Egroditi/POE-Component-DirWatch-Object-0.10/lib/POE/Component/DirWatch/Object.pm&quot;&gt;POE::Component::DirWatch::Object&lt;/a&gt; and grasped some of the potential it had for &lt;span style=&quot;font-style: italic;&quot;&gt;kind of&lt;/span&gt; replacing a GUI in some &lt;span style=&quot;font-style: italic;&quot;&gt;simple&lt;/span&gt; scripts, I just had to try it.&lt;br /&gt;&lt;br /&gt;What &lt;a href=&quot;http://search.cpan.org/%7Egroditi/POE-Component-DirWatch-Object-0.10/lib/POE/Component/DirWatch/Object.pm&quot;&gt;POE::Component::DirWatch::Object&lt;/a&gt; basically does is keep an eye on a folder, and act upon an event regarding it. For instance, using &lt;a href=&quot;http://search.cpan.org/%7Egroditi/POE-Component-DirWatch-Object-0.10/lib/POE/Component/DirWatch/Object/NewFile.pm&quot;&gt;::NewFile&lt;/a&gt;, it will trigger a user-defined function whenever a file is created in that directory. This might seem old news for the compsci people, but for me it was quite a new concept and I really liked it.&lt;br /&gt;&lt;br /&gt;So to test-drive it, I decided that I'd code for a simple script (not too different than the module's synopsis, in retrospect) that would translate any DNA sequence that was created in it. This way, the user would just have to copy or move her desired sequence files to the &quot;translate&quot; (as I very imaginatively called it) folder, and they would automagically translate themselves.&lt;br /&gt;&lt;br /&gt;The core of the script is:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/113591.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;Simple, right? Here, &lt;span style=&quot;font-family:courier new;&quot;&gt;$watcher&lt;/span&gt; will execute the &lt;span style=&quot;font-family:courier new;&quot;&gt;translate&lt;/span&gt; subroutine whenever a new file is created in the &lt;span style=&quot;font-family:courier new;&quot;&gt;/home/brunov/translate&lt;/span&gt; folder. The last line is needed to make POE do its magic. The script runs a daemon that never exits, and could be configured to start when you log in to your session.&lt;br /&gt;&lt;br /&gt;The translate routine is pretty straightforward. It uses &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/Seq.pm&quot;&gt;Bio::Seq&lt;/a&gt; for the translation part, and &lt;a href=&quot;http://search.cpan.org/%7Ecjfields/BioPerl-1.6.0/Bio/SeqIO.pm&quot;&gt;Bio::SeqIO&lt;/a&gt; for the file reading and writing. What it does is read the input file, translate all the translatable sequences that are in it, and write the results in a temporary file,&lt;br /&gt;which is later used to replace the original one.&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/113587.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;That's all that is needed (minus a little error checking that I chose to leave out for the sake of bloggability).&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Adding neat notifications&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The script runs fine as it is, but it's kind of dull. Since there are no newly created files nor visible output, you are tempted to reopen the translated file to actually check that your DNA has been translated into protein. This is why I thought that adding system notifications would be appropiate.&lt;br /&gt;&lt;br /&gt;Actually, bullshit. I just can't get enough of Ubuntu's&lt;a href=&quot;http://www.markshuttleworth.com/archives/265&quot;&gt; sexy notification system&lt;/a&gt;, so I figured it'd be nice if a bubble popped up saying the outcome of the translation.&lt;br /&gt;&lt;br /&gt;So doing some more CPAN digging, I found &lt;a href=&quot;http://search.cpan.org/%7Eflora/Gtk2-Notify-0.05/lib/Gtk2/Notify.pm&quot;&gt;Gtk2::Notify&lt;/a&gt;. With a few extra lines of code, I got a chatty, ribosomy (get it?) folder. Here's the modified &lt;span style=&quot;font-family:courier new;&quot;&gt;translate&lt;/span&gt; sub (minus old comments) and the new &lt;span style=&quot;font-family:courier new;&quot;&gt;notify&lt;/span&gt; one:&lt;br /&gt;&lt;br /&gt;&lt;script src=&quot;http://gist.github.com/113590.js&quot;&gt;&lt;/script&gt;&lt;br /&gt;And that's it! Now whenever you drop a file in the &quot;translate&quot; folder, all DNA sequences that are in it get translated (and those who are not are left untouched). This could allow for cute chained actions; one could have a whole hierarchy of live folders with things such as &quot;reverse translate&quot;, &quot;blast it&quot;, &quot;predict solubility&quot;, &quot;digest it&quot; and so on. It is certainly not as flexible as good old CLI scripts, but it reaches a nice compromise between the user friendliness of a GUI and the batch processing capabilities of command-line fu.&lt;br /&gt;&lt;br /&gt;Here's how it looks:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://2.bp.blogspot.com/_dJsDskOH5ac/ShGG8NZOldI/AAAAAAAAAAw/kVANteA6t4E/s1600-h/screenshot_w_arrow.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 320px;&quot; src=&quot;http://2.bp.blogspot.com/_dJsDskOH5ac/ShGG8NZOldI/AAAAAAAAAAw/kVANteA6t4E/s400/screenshot_w_arrow.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5337195402356495826&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can see the real-life script &lt;a href=&quot;http://gist.github.com/113594&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;P.S: And just &lt;a href=&quot;http://use.perl.org/~Alias/journal/38991?from=rss&quot;&gt;to spite TIOBE people&lt;/a&gt;: Perl Programming rocks! And also &lt;a href=&quot;http://www.rapideuphoria.com/&quot;&gt;Euphoria Programming&lt;/a&gt; and &lt;a href=&quot;http://www.audiosynth.com/&quot;&gt;SuperCollider Programming&lt;/a&gt;, of course.
&lt;/div&gt;
</description>
        <pubDate>Mon, 18 May 2009 16:02:00 +0000</pubDate>
        <link>http://brunov.org/2009/05/so-i-admit-it.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/05/so-i-admit-it.html</guid>
      </item>
    
      <item>
        <title>Chopping proteins with Moose</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
It comes a time in the life of a wet lab geek when one has to simulate the outcome of a proteolytic degradation of a protein of known sequence (those who said that haven't are lying).&lt;br /&gt;&lt;br /&gt;So for a problem this common, I did what I always do first: google for an already made solution. Surprisingly, after ten minutes or so, I came out empty-handed.&lt;br /&gt;&lt;br /&gt;Now don't get me wrong: there &lt;em&gt;were&lt;/em&gt; solutions out there, like &lt;a href=&quot;http://www.expasy.ch/tools/peptidecutter/&quot;&gt;PeptideCutter&lt;/a&gt;, &lt;a href=&quot;http://pops.csse.monash.edu.au/&quot;&gt;PoPS&lt;/a&gt;, or &lt;a href=&quot;http://emboss.sourceforge.net/&quot;&gt;EMBOSS&lt;/a&gt;' digest, but none of them were easily usable as a library. The first two only offered a web front-end, and that is OK for a quick digestion of one or two sequences, but I needed batch-processing capabilities and much more flexibility (ie, being able to predict partial digests, for instance). The last one was indeed available as a command line utility, but it offered very few enzyme specificities, it forced an interactive mode, and writing a wrapper for it would have involved more logic that the one implemented in the application (not to mention the ugly reading/writing of temporary files that would have been required to deal with the app's inflexible interface, and that would have created a nice and shiny IO bottleneck in every downstream application that used it).&lt;br /&gt;&lt;br /&gt;So, there. Homework done, I decided to code for a solution myself. Luckily, &lt;a href=&quot;http://www.expasy.ch/tools/peptidecutter/&quot;&gt;PeptideCutter&lt;/a&gt; had a pretty comprehensive explanation of how their algorithm works, and it is simple enough to be coded quickly.&lt;br /&gt;&lt;br /&gt;Basically, a protease specificity is modeled as a regular expression that returns true or false on a sequence sliding window. This sliding window is six residues long in &lt;a href=&quot;http://www.expasy.ch/tools/peptidecutter/&quot;&gt;PeptideCutter&lt;/a&gt;, I did it 8 residues long to account for potentially more specific proteases. When the substrate matches the regular expression, the sequence should be cut at the &lt;em&gt;siscile bond&lt;/em&gt;. Simple enough.&lt;br /&gt;&lt;br /&gt;The module is up at my &lt;a href=&quot;http://github.com/brunoV/bio-protease/tree/master&quot;&gt;github repo&lt;/a&gt; (I called it Bio::Protease for a lack of better name), you can download it/fork it/follow it to your liking. It has quite a robust test suite, I checked every single specificity against PeptideCutter's results on the same input.&lt;br /&gt;&lt;br /&gt;I used Perl and &lt;a href=&quot;http://www.iinteractive.com/moose/&quot;&gt;Moose&lt;/a&gt; for it. One of the things that I like the most about Moose is how easy it is to make really DWIMmy APIs with it.&lt;br /&gt;For instance, in Bio::Protease, you can do:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;&amp;nbsp;= Bio::Protease-&amp;gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt;(&lt;font color=&quot;#ff1493&quot;&gt;specificity &lt;/font&gt;=&amp;gt; &lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;trypsin&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;);&lt;br&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;This will coerce the string 'trypsin' into an internal representation of the trypsin specificity, which is implemented as a code reference. (Currently, there are more than thirty different specificities to choose from, you can list them by doing &lt;code&gt;say Bio::Protease-&gt;Specificities&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Also, you could say:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$cutting_pattern&lt;/font&gt;&amp;nbsp;= Bio::Tools::SeqPattern-&amp;gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&lt;font color=&quot;#ff1493&quot;&gt;SEQ &lt;/font&gt;=&amp;gt; &lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;XXXW[^P]RSX&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;, -&lt;font color=&quot;#ff1493&quot;&gt;TYPE &lt;/font&gt;=&amp;gt; &lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;Amino&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;&lt;br /&gt;);&lt;br /&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;&amp;nbsp;= Bio::Protease-&amp;gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt;(&lt;font color=&quot;#ff1493&quot;&gt;specificity &lt;/font&gt;=&amp;gt; &lt;font color=&quot;#005f5f&quot;&gt;$cutting_pattern&lt;/font&gt;);&lt;br&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;to get a custom regex-based specificity. The one above would cut sequences between the fourth and fifth residues if they match that pattern.&lt;br /&gt;&lt;br /&gt;You could object that the regex-specificity model is too simplistic for your personal use, and you'd be right. Enzymic cleavage of peptide bonds does not share the deterministic character of restriction enzymes, and sometimes protein's structural characteristics get in the way and play an important part in cleavage. So, to account for an arbitrarily complex specificity model, the 'specificity' attribute also accepts a code reference:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$nobel_prize_winning_specificity_model&lt;/font&gt;&amp;nbsp;=&lt;font color=&quot;#005f5f&quot;&gt;&amp;nbsp;&lt;/font&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/font&gt;&lt;font color=&quot;#005f5f&quot;&gt;&amp;nbsp;&lt;/font&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$peptide&lt;/font&gt;&amp;nbsp;= &lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/font&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#0000cd&quot;&gt;# decide whether to cut $peptide or not&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;&amp;nbsp;= Bio::Protease-&amp;gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=&quot;#ff1493&quot;&gt;specificity &lt;/font&gt;=&amp;gt; &lt;font color=&quot;#005f5f&quot;&gt;$nobel_prize_winning_specificity_model&lt;/font&gt;;&lt;br /&gt;);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Internally, the module passes a sliding window of peptides to the code reference; if it returns true, it marks the siscile bond as cut.&lt;br /&gt;&lt;br /&gt;So back to the original problem, to actually make the cuts, you can do:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;@products&lt;/font&gt;&amp;nbsp;= &lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;-&amp;gt;digest(&lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;MAAEEELLKKVVIKP&lt;/font&gt;&lt;font color=&quot;#ff1493&quot;&gt;'&lt;/font&gt;); &lt;/font&gt;&lt;br /&gt;&lt;br /&gt;The products of a full digestion of the argument sequence will be returned as a list. On the other hand, if you want to get the siscile bonds, you'd say:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;@cut_sites&lt;/font&gt;&amp;nbsp;= &lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;-&amp;gt;cleavage_sites(&lt;font color=&quot;#005f5f&quot;&gt;$seq&lt;/font&gt;);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;And, for partial digests, you can use the method 'cut', that will return the products of a single cleavage if you provide a siscile bond as an argument:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;monospace&quot; size=3&gt;&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;my&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;@products&lt;/font&gt;&amp;nbsp;= &lt;font color=&quot;#005f5f&quot;&gt;$protease&lt;/font&gt;-&amp;gt;cut(&lt;font color=&quot;#005f5f&quot;&gt;$seq&lt;/font&gt;, &lt;font color=&quot;#005f5f&quot;&gt;$cut_sites&lt;/font&gt;[&lt;font color=&quot;#a52a2a&quot;&gt;&lt;b&gt;rand&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color=&quot;#005f5f&quot;&gt;@cut_sites&lt;/font&gt;]);&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;In the above expression, &lt;code&gt;$cut_sites[rand @cut_sites]&lt;/code&gt; will choose a random cleavage site from &lt;code&gt;@cut_sites&lt;/code&gt;, and cut &lt;code&gt;$seq&lt;/code&gt; there. This is the basis for a bigger module (and the reason for coding this one), which could make it to a separate blog post in the future.&lt;br /&gt;&lt;br /&gt;The take home lesson is: use &lt;a href=&quot;http://www.iinteractive.com/moose/&quot;&gt;Moose&lt;/a&gt;. I am too lazy to have done all of this had not been so easy. Without it, I would have probably whipped up a half-assed script (not a shiny, reusable module) that took a sequence and a specificity as input from the command line, and that barfed a table with the cleavage sites as output, and not much more (sounds familiar?). But all of the above functionality was implemented in a hundred-or-so lines of clean, declarative, object-oriented code, and I don't ever have to worry about this problem again (and neither do you).
&lt;/div&gt;
</description>
        <pubDate>Mon, 27 Apr 2009 13:40:00 +0000</pubDate>
        <link>http://brunov.org/2009/04/chopping-proteins-with-moose.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/04/chopping-proteins-with-moose.html</guid>
      </item>
    
      <item>
        <title>The Enlightened Perl Iron Man Competition</title>
        <description>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
Matt Trout just made a blogpost announcing the &lt;a href=&quot;http://www.shadowcat.co.uk/blog/matt-s-trout/iron-man/&quot;&gt;Iron Man Competition&lt;/a&gt;, sponsored by the &lt;a href=&quot;http://www.enlightenedperl.org/&quot;&gt;Englightened Perl Organization&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I personally think this is a very good idea and a great way to tackle one of Perl's problem of today: perception. The language and its community may well be alive (&lt;a href=&quot;http://www.slideshare.net/Tim.Bunce/perl-myths-200802&quot;&gt;Tim Bunce&lt;/a&gt; did a great job proving this), but few people outside the &lt;a href=&quot;http://desert-island.me.uk:8888/~castaway blog/looking-for-perl-signals.html&quot;&gt; echo chamber&lt;/a&gt; know about it, and constantly make claims that &lt;a href=&quot;http://www.google.com/search?q=perl+is+dead&quot;&gt;Perl is dead&lt;/a&gt;. As &lt;a href=&quot;http://schwern.org/&quot;&gt;Schwern&lt;/a&gt; very well put it in one of his &lt;a href=&quot;http://schwern.org/talks/Perl%20is%20unDead%20-%20YAPC-NA-2008.pdf&quot;&gt;talks&lt;/a&gt;, this perception issue is far from harmless and should not be taken lightly.&lt;br /&gt;&lt;br /&gt;Given that today's communication routes among the newer generations are mainly blogs, Matt's proposal to &quot;make noise&quot; by blogging (as opposed to just writing excellent code, which should be enough) is the right way to help increase Perl awareness in the programming community.&lt;br /&gt;&lt;br /&gt;I have been playing with the idea of starting a blog myself for a while. This might have been the push I needed to make up my mind and &lt;a href=&quot;http://www.urbandictionary.com/define.php?term=jfdi&quot;&gt;JFDI&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note: This is a repost of a &lt;a href=&quot;http://www.perlmonks.org/?node_id=759153&quot;&gt;meditation&lt;/a&gt; of mine in &lt;a href=&quot;http://www.perlmonks.org&quot;&gt;PerlMonks&lt;/a&gt;. I am hoping that it counts as my first Iron Man blog entry.
&lt;/div&gt;
</description>
        <pubDate>Sat, 25 Apr 2009 16:03:00 +0000</pubDate>
        <link>http://brunov.org/2009/04/enlightened-perl-iron-man-competition.html</link>
        <guid isPermaLink="true">http://brunov.org/2009/04/enlightened-perl-iron-man-competition.html</guid>
      </item>
    
  </channel>
</rss>
