<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;C04BQ385eip7ImA9WxBSEU8.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004</id><updated>2009-12-18T01:39:12.122-06:00</updated><title>clipboarded</title><subtitle type="html">minutes of a programmer</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Clipboarded" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;C0UAQX85eSp7ImA9WxNaGEw.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-2919971192753929808</id><published>2009-12-02T21:22:00.011-06:00</published><updated>2009-12-02T21:34:00.121-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-02T21:34:00.121-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="words" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>urban dictionary's greatest hits</title><content type="html">&lt;p&gt;I was curious about what words were the most popular on &lt;a href="http://urbandictionary.com/"&gt;urbandictionary.com&lt;/a&gt;. So I scraped the &lt;i&gt;popular&lt;/i&gt; section for each letter in the alphabet and came up with the following table where the ranking is based on the number of upvotes. I didn't want to have my blog associated with any of the words below and I didn't want to give backlinks to the urban dictionary so here's an image of my results.&lt;/p&gt;

&lt;div style="text-align:center"&gt;
&lt;a href="http://3.bp.blogspot.com/_c-z10zbSfTE/SxctePmVmgI/AAAAAAAAAGk/hN14beGHwjs/s1600/results.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_c-z10zbSfTE/SxctePmVmgI/AAAAAAAAAGk/hN14beGHwjs/s1600/results.png" /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;
Here is the code I used to get to the information. It scrapes all the links provided in the popular section for each letter and writes a dump of all entries. The dumps can later be used to study the data.&lt;/p&gt;
&lt;pre&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;rubygems&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;hpricot&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;open-uri&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;entry&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;net/http&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;json&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;

&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;retrieve_votes&lt;/span&gt;(doc)
  &lt;span class="Comment"&gt;# in-browser, votes are retrieved through an ajax call after the web page is loaded&lt;/span&gt;
  (doc/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;td.tools&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;tools&lt;/span&gt;|
    id = tools[&lt;span class="Constant"&gt;:id&lt;/span&gt;]
    uncacheable_id = id.scan(&lt;span class="Special"&gt;/&lt;/span&gt;&lt;span class="Special"&gt;\d&lt;/span&gt;&lt;span class="Special"&gt;+&lt;/span&gt;&lt;span class="Special"&gt;/&lt;/span&gt;)[&lt;span class="Constant"&gt;0&lt;/span&gt;]

    json_response = &lt;span class="Type"&gt;Net&lt;/span&gt;::&lt;span class="Type"&gt;HTTP&lt;/span&gt;.post_form(&lt;span class="Type"&gt;URI&lt;/span&gt;.parse(&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;&lt;a href="http://www.urbandictionary.com/uncacheable.php"&gt;http://www.urbandictionary.com/uncacheable.php&lt;/a&gt;&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;), {&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;ids&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;=&amp;gt; uncacheable_id})
    thumbs = &lt;span class="Type"&gt;JSON&lt;/span&gt;.parse(json_response.body)[&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;thumbs&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;][&lt;span class="Constant"&gt;0&lt;/span&gt;]
    &lt;span class="Statement"&gt;return&lt;/span&gt; [thumbs[&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;thumbs_up&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;], thumbs[&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;thumbs_down&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;]]
  &lt;span class="Statement"&gt;end&lt;/span&gt;
&lt;span class="PreProc"&gt;end&lt;/span&gt;

&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;retrieve_links&lt;/span&gt; letter
  anchors = []

  doc = Hpricot(open(letter))
  (doc/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;table#columnist//tr&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;row&lt;/span&gt;|
    (row/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;td&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;cell&lt;/span&gt;|
      (cell/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;ul&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;li&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;li&lt;/span&gt;|
        (li/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;a&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;anchor&lt;/span&gt;|
          anchors &amp;lt;&amp;lt;  anchor.get_attribute(&lt;span class="Constant"&gt;:href&lt;/span&gt;)
        &lt;span class="Statement"&gt;end&lt;/span&gt;
      &lt;span class="Statement"&gt;end&lt;/span&gt;
    &lt;span class="Statement"&gt;end&lt;/span&gt;
  &lt;span class="Statement"&gt;end&lt;/span&gt;

  anchors
&lt;span class="PreProc"&gt;end&lt;/span&gt;

&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;build_entry&lt;/span&gt;(doc)
    word = &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;no words found&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;
    definition = &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;no definitions found&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;

    up, down = retrieve_votes(doc)
    (doc/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;td.word&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;wrd&lt;/span&gt;|
      word = wrd.to_plain_text
      &lt;span class="Statement"&gt;break&lt;/span&gt;
    &lt;span class="Statement"&gt;end&lt;/span&gt;
    (doc/&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;div.definition&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;).each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;defined&lt;/span&gt;|
      definition = defined.to_plain_text
      &lt;span class="Statement"&gt;break&lt;/span&gt;
    &lt;span class="Statement"&gt;end&lt;/span&gt;

    &lt;span class="Type"&gt;Entry&lt;/span&gt;.new(word, definition, up, down)
&lt;span class="PreProc"&gt;end&lt;/span&gt;

&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;.each_char &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;letter&lt;/span&gt;|
  links = retrieve_links(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&lt;a href="http://www.urbandictionary.com/popular.php?character="&gt;http://www.urbandictionary.com/popular.php?character=&lt;/a&gt;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;letter&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;)
  entries = []
  links.each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;link&lt;/span&gt;|
    sleep &lt;span class="Constant"&gt;5&lt;/span&gt;
    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;fetching &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;link&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;
    doc = Hpricot(open(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&lt;a href="http://www.urbandictionary.com"&gt;http://www.urbandictionary.com&lt;/a&gt;&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt; + link))
    entries &amp;lt;&amp;lt; build_entry(doc)
  &lt;span class="Statement"&gt;end&lt;/span&gt;

  &lt;span class="Type"&gt;File&lt;/span&gt;.open(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;letter&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;letter&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt;.dump&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;,&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;w&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;){|&lt;span class="Identifier"&gt;file&lt;/span&gt;|
    file.write(&lt;span class="Type"&gt;Marshal&lt;/span&gt;.dump(entries))
  }
&lt;span class="Statement"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The Entry class is defined like so.&lt;/p&gt;
&lt;pre&gt;
&lt;span class="PreProc"&gt;class&lt;/span&gt; &lt;span class="Type"&gt;Entry&lt;/span&gt;
  &lt;span class="Statement"&gt;attr_accessor&lt;/span&gt; &lt;span class="Constant"&gt;:word&lt;/span&gt;, &lt;span class="Constant"&gt;:definition&lt;/span&gt;, &lt;span class="Constant"&gt;:up&lt;/span&gt;, &lt;span class="Constant"&gt;:down&lt;/span&gt;
  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;initialize&lt;/span&gt; word, definition, up, down
    &lt;span class="Identifier"&gt;@word&lt;/span&gt; = word
    &lt;span class="Identifier"&gt;@definition&lt;/span&gt; = definition
    &lt;span class="Identifier"&gt;@up&lt;/span&gt; = up
    &lt;span class="Identifier"&gt;@down&lt;/span&gt; = down
  &lt;span class="PreProc"&gt;end&lt;/span&gt;

  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;&amp;lt;=&amp;gt;&lt;/span&gt;(other)
    (other.up - other.down) - (&lt;span class="Identifier"&gt;@up&lt;/span&gt; - &lt;span class="Identifier"&gt;@down&lt;/span&gt;)
  &lt;span class="PreProc"&gt;end&lt;/span&gt;

  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;to_s&lt;/span&gt;
    &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;word&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; (&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;up&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; up, &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;down&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; down): &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;definition&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="PreProc"&gt;end&lt;/span&gt;
&lt;span class="PreProc"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In order to get some kind of greatest hits, I used the following script. I had to filter out entries with too many down votes to get rid of the most childish entries.&lt;/p&gt;
&lt;pre&gt;
&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;entry&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;

entries = []
&lt;span class="Type"&gt;Dir&lt;/span&gt;[&lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;letter*.dump&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;].sort.each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;filename&lt;/span&gt;|
  entries.concat(&lt;span class="Type"&gt;Marshal&lt;/span&gt;.load(&lt;span class="Type"&gt;File&lt;/span&gt;::open(filename).read))
&lt;span class="Statement"&gt;end&lt;/span&gt;

entries.sort!
entries.reject! {|&lt;span class="Identifier"&gt;entry&lt;/span&gt;| entry.down &amp;gt; &lt;span class="Constant"&gt;1000&lt;/span&gt;}
html=&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="Constant"&gt;50&lt;/span&gt;.times &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;i&lt;/span&gt;|
  i = i + &lt;span class="Constant"&gt;1&lt;/span&gt;
  html += &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;i&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td style='padding: 0 2em 0 2em;'&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;entries[i].word&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;a href=\&amp;quot;&lt;a href="http://www.urbandictionary.com/define.php?term="&gt;http://www.urbandictionary.com/define.php?term=&lt;/a&gt;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;entries[i].word&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt;\&amp;quot;&amp;gt;read more&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="Statement"&gt;end&lt;/span&gt;
html+=&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;

puts html
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-2919971192753929808?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/2919971192753929808/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=2919971192753929808" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/2919971192753929808?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/2919971192753929808?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2009/12/urban-dictionarys-greatest-hits.html" title="urban dictionary's greatest hits" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_c-z10zbSfTE/SxctePmVmgI/AAAAAAAAAGk/hN14beGHwjs/s72-c/results.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUAHQn84fCp7ImA9WxNaFUg.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7674100625661024960</id><published>2009-11-29T23:08:00.001-06:00</published><updated>2009-11-29T23:08:53.134-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-29T23:08:53.134-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="pairing" /><title>pair programming prep</title><content type="html">What can we do &lt;b&gt;before&lt;/b&gt; pairing to make it more effective?&lt;ul&gt;&lt;li&gt;Make sure both peers focus on productivity to get the ego and flowery phrases out of the way&lt;/li&gt;&lt;li&gt;Agree on a game plan. What problem are we solving? What type of pairing is this going to be? (ball and board or coder/navigator or ping pong)&lt;/li&gt;&lt;li&gt;Understand the benefits/costs of pairing&lt;/li&gt;&lt;li&gt;Negotiation: Roy Miller of RoleModel Software offers a suggestion: &lt;blockquote&gt;One of the best tricks I've ever used when pairing is to start each pairing session with some 'negotiation.' I lay out what I like and don't like when I pair with someone, things I do well and things I don't do well, things I need help on, things that bug me to death. Then I listen while the other person does the same. This takes less than five minutes, usually, but the results are staggering. Both members of the pair then can use the pairing session as a time to get work done and to help the other person. I think 'pairing as negotiation' is a key concept.&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Read more: &lt;a href="http://safari.informit.com/0201745763"&gt;Pair Programming Illuminated&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7674100625661024960?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7674100625661024960/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7674100625661024960" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7674100625661024960?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7674100625661024960?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2009/11/pair-programming-prep.html" title="pair programming prep" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DE4HQH0yeyp7ImA9WxVWGE4.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-6114830518544141304</id><published>2009-02-28T10:02:00.000-06:00</published><updated>2009-02-28T10:02:11.393-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-28T10:02:11.393-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social actions" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="change the web" /><title>change the web challenge</title><content type="html">&lt;p&gt;
The not-for-profit &lt;a href="http://www.socialactions.com/"&gt;Social Actions&lt;/a&gt; just launched the &lt;a href="http://www.socialactions.com/changetheweb"&gt;Change the Web Challenge&lt;/a&gt;. The idea is to come up with the greatest application you can think of that leverages their API.
&lt;/p&gt;
&lt;p&gt;
Their API allows you to search a database of social actions -- things like volunteering opportunities, fundraising events, petitions -- aggregated from contributors like &lt;a href="http://kiva.org"&gt;kiva.org&lt;/a&gt; or &lt;a href="http://idealist.org"&gt;idealist.org&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
For a quick peek at what you have access to, you can try my very own &lt;a href="http://www.quicksandboxer.com/socialactions"&gt;search for opportunities&lt;/a&gt;. The code for it is available as a &lt;a href="http://github.com/matstc/search-for-opportunities/tree"&gt;git repository&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-6114830518544141304?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/6114830518544141304/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=6114830518544141304" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6114830518544141304?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6114830518544141304?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2009/02/change-web-challenge.html" title="change the web challenge" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CE8DQXY6eSp7ImA9WxRbEEo.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-6815885852009202592</id><published>2008-11-30T12:20:00.000-06:00</published><updated>2008-11-30T13:21:10.811-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-30T13:21:10.811-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="test" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>test-first VS writing a test harness</title><content type="html">&lt;p&gt;There is a common understanding that code written using a test-first approach (as in TDD-style) ends up being more maintainable than code that has been harnessed with tests later on. I would justify that understanding as follows:
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;TDD simplifies original design&lt;/b&gt;. This one is easy. By driving the design through small unit tests, we never write code that is unnecessary and experienced TDDers know to make the tests pass with the simplest thing that works. Further, because we gain immediately from writing testable code, the code usually ends up loosely coupled with no implicit dependencies and few explicit dependencies.&lt;br/&gt;
Another thing is that by writing the code that exercises the implementation, we design both sides of the API, client code and implementation at the same time. I blogged about &lt;a href="http://clipboarded.blogspot.com/2008/07/ideal-client-code-as-design.html"&gt;client code as design&lt;/a&gt; some time ago.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The tests once failed for lack of functionality&lt;/b&gt;. To make sure the test is bug-free -- and actually testing the upcoming functionality -- it is imperative to make it fail before making it pass. If you're testing first, that's easy. If you're writing a test harness, you might have to comment out a bit of code to get the red bar, but then will it still compile? Will it still be coherent at runtime? A test harness is forever dubious.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;TDD gives you fine-grained coverage&lt;/b&gt;. With very little overhead, TDD gives you fine-grained coverage since you're writing the simplest test that brings you forward, all the time. In the words of &lt;a href="http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Addison-Wesley/dp/0131495054/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1228071465&amp;sr=8-1"&gt;Gerard Meszaros&lt;/a&gt;, this gives you better &lt;i&gt;Defect Localization&lt;/i&gt;. When writing a test harness, we usually emphasize the higher level functionality and forget about the smaller 'units' of work. These smaller units might be hard to test because they are implicit, hidden/encapsulated, or even unfathomable.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Test/Specification mismatch&lt;/b&gt;. The tests are the requirements for the code. The BDD people have taken this to the next level, but it remains true with TDD. Test code is the most useful documentation to a fellow developer: it's working, up to date, terse, and it serves as an example of client code.
When developing TDD-style, the tests become the developers' understanding of the stories -- the ultimate reference.&lt;br/&gt;
If writing tests later on, we need to match the functional requirements with the actual codebase, like pieces of a puzzle. Except there will be mismatches, where the developers were not really clear about the requirements. What are we to do then? For this reason alone, test harnessing a big codebase is just really, &lt;i&gt;really&lt;/i&gt; hard.
&lt;/p&gt;

Interestingly, most of the benefits derived from test-first development are gone even if you write the tests right after new code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-6815885852009202592?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/6815885852009202592/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=6815885852009202592" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6815885852009202592?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6815885852009202592?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/11/test-first-vs-writing-test-harness.html" title="test-first VS writing a test harness" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;CUANQX4-fCp7ImA9WxRWEEk.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-6787836232150397551</id><published>2008-10-26T12:53:00.000-05:00</published><updated>2008-10-26T12:56:30.054-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-26T12:56:30.054-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="free culture" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>about free culture</title><content type="html">&lt;p&gt;I just finished reading The &lt;a href="http://www.the-future-of-ideas.com/"&gt;Future Of Ideas&lt;/a&gt; and &lt;a href="http://www.free-culture.cc/"&gt;Free Culture&lt;/a&gt;. I read both books avidly and I would recommend them to pretty much anyone -- programmer or not. What's more, they are both available for free online, under a creative commons license.
&lt;/p&gt;
&lt;p&gt;In both books, &lt;a href="http://lessig.org"&gt;Lessig&lt;/a&gt; dissects the state and the fate of the commons in american society. The commons are to be cherished and cared for as they lead to innovation, creativity, and a free culture.
&lt;/p&gt;
&lt;p&gt;The Future Of Ideas is mostly concerned about explaining the concept of commons and the one of layers. The idea of layers is taken from &lt;a href="http://en.wikipedia.org/wiki/Yochai_Benkler"&gt;Yochai Benkler&lt;/a&gt; and divides the network in three parts: the physical layer, the code, and the content. Lessig then explains how the balance of control at each layer affects innovation and creativity. The example stories include Napster, MP3.com, UNIX, and deCSS.
&lt;/p&gt;
&lt;p&gt;Free Culture is mostly concerned about the effects of excessive control on culture. Lessig discusses copyright law, intellectual property, and the concentration of the media. The example stories include the infamous RIAA lawsuits and the &lt;a href="http://en.wikipedia.org/wiki/Eldred_v._Ashcroft"&gt;Eldred v. Ashcroft&lt;/a&gt; case.
&lt;/p&gt;
&lt;p&gt;A few things strike me about this free culture debate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is no clear stakeholder in the 'new'. The new innovators and creators that free culture helps aren't yet established. This makes the fight incredibly hard to win. It's another case of special interests violating the people.&lt;/li&gt;
&lt;li&gt;There is no obvious way to disagree with Lessig unless you have a stake in the 'old'. Lessig explains his case rationally and is smart enough to include the whole political spectrum with his arguments.&lt;/li&gt;
&lt;li&gt;Prolonging the term of existing copyrights is absurd. The objective of copyrights is to give an incentive to innovators. Once the innovation has seen the light of day, prolonging the term of copyrights delays their introduction in the public domain where they could give rise to even more innovation. Thus, prolonging the term of copyrights goes against their prime objective.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a side note, another book from Lessig just came out: &lt;a href="http://remix.lessig.org/"&gt;Remix&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-6787836232150397551?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/6787836232150397551/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=6787836232150397551" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6787836232150397551?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6787836232150397551?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/10/about-free-culture.html" title="about free culture" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C04GQnwyeyp7ImA9WxRXGUs.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-8552901317582491526</id><published>2008-09-15T11:58:00.002-05:00</published><updated>2008-10-25T14:12:03.293-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-25T14:12:03.293-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="rake" /><title>skip dependencies in Rake</title><content type="html">&lt;p&gt;Here is a handy rake task to skip dependencies whenever you want to:&lt;/p&gt;

&lt;pre&gt;
desc &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;Skip dependencies of subsequent tasks&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;
task &lt;span class="Constant"&gt;:skip&lt;/span&gt; &lt;span class="Statement"&gt;do&lt;/span&gt;
  &lt;span class="Type"&gt;Rake&lt;/span&gt;::&lt;span class="Type"&gt;Task&lt;/span&gt;.tasks.each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;t&lt;/span&gt;|
    t.clear_prerequisites
  &lt;span class="Statement"&gt;end&lt;/span&gt;
&lt;span class="Statement"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-8552901317582491526?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/8552901317582491526/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=8552901317582491526" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/8552901317582491526?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/8552901317582491526?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/09/skip-dependencies-in-rake.html" title="skip dependencies in Rake" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEAHSXk6fCp7ImA9WxRSFEw.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-598773929337347691</id><published>2008-09-14T13:13:00.005-05:00</published><updated>2008-09-14T13:25:38.714-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-14T13:25:38.714-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="pyweek" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>pyweek 7 is over</title><content type="html">&lt;a href="http://www.pyweek.org/"&gt;PyWeek&lt;/a&gt; just went by. A python programming challenge where participants have one week to make a game.
&lt;br/&gt;&lt;br /&gt;
Here is our project page: &lt;a href="http://code.google.com/p/strlen/"&gt;google code strlen&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;
Or you can check it out like so:
&lt;br /&gt;
&lt;div class="code"&gt;svn checkout http://strlen.googlecode.com/svn/trunk/ strlen&lt;/div&gt;
&lt;br /&gt;
&lt;img border="0" src="http://2.bp.blogspot.com/_c-z10zbSfTE/SM1V2yW7kvI/AAAAAAAAADE/Xl9gOtSwo94/s320-R/screenshot-strlen.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-598773929337347691?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/598773929337347691/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=598773929337347691" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/598773929337347691?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/598773929337347691?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/09/pyweek-7-is-over.html" title="pyweek 7 is over" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_c-z10zbSfTE/SM1V2yW7kvI/AAAAAAAAADE/Xl9gOtSwo94/s72-Rc/screenshot-strlen.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkUEQXg6eip7ImA9WxdaF08.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-6498951766304353044</id><published>2008-08-23T11:08:00.005-05:00</published><updated>2008-08-25T22:10:00.612-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-25T22:10:00.612-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="society" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>being more than programmers</title><content type="html">&lt;p&gt;
There is a recurrent theme that I see in blogs and books where it is stated that programmers have to open up, broaden their horizons and become more interested in the business perspective of software. Kent Beck dedicating Extreme Programming Explained goes: "Without you, this book would still be about programmers hiding in a corner. Without you, I would still be one of those programmers."
&lt;/p&gt;&lt;p&gt;
Dave Thomas, with usually very utilitarian views on our careers as software developers, also consistently encourages his audience to take into account the big picture and invest in our personal education and knowledge.
&lt;/p&gt;&lt;p&gt;
I'm sure this trend is nothing new but it's been very visible recently in the agile movement in general. A recent book along this trend is Chad Fowler's &lt;a href="http://www.pragprog.com/titles/mjwti/my-job-went-to-india"&gt;My Job Went To India&lt;/a&gt;. Its second chapter bears the title "Coding Don't Cut It Anymore".
This idea of opening up is a good one and is usually well received. However, I feel that the direction in which we need to open up is often implicit in most texts. This is unfortunate as I believe this direction should be the result of a conscious decision.
&lt;/p&gt;&lt;p&gt;
There is no question that we need to be more than programmers. The mere will to write &lt;i&gt;useful&lt;/i&gt; software needs us to be more than coders. However, I need more than the proposed, and dare I say obvious, solution. I would paraphrase this solution like so: we need to build a bigger role for ourselves by learning a few things from the way our organizations work and pay more attention to the customer's needs and the business value of our product: software.
&lt;/p&gt;&lt;p&gt;
Chad Fowler wants us to ask ourselves these questions:
&lt;/p&gt;
&lt;blockquote&gt;
"How much value did you produce last year? What was your positive impact on the company's bottom line? What did you give back? How much money did you cause the company to save? How much more in revenues did you contribute?"
&lt;/blockquote&gt;
&lt;p&gt;
or to follow the wave in search of the next big thing:
&lt;/p&gt;
&lt;blockquote&gt;
"Ten years ago, you would have been surprised to find out just how big object-oriented languages with garbage collection would become. But, there were definitely signs if you were watching. Ten years from now, who knows what the Next Big Thing will be? You've got to keep your eyes and ears open."
&lt;/blockquote&gt;
&lt;p&gt;
The shortcoming of these propositions is that their benefits are not distributed equally. Really, those solutions turn out to be very good for your company and your personal gain is only marginal. How to align the employees' incentives so that their actions benefit the company is a special case of the &lt;a href="http://en.wikipedia.org/wiki/Principal-agent_problem"&gt;principal-agent problem.&lt;/a&gt; This is the one big problem we should be working on inside our organizations. Here is the spoiler though: this problem is only truly solved if you start your own company.
&lt;/p&gt;&lt;p&gt;
Short of doing that, there are lots of ways to pick up the slack and "open up" outside of our organizations. Open-source projects are an easy solution, you're not an "agent" when you labor out of love. This point is actually discussed in Chad's book so I will skip it.
Community-oriented services are another solution: projects like the &lt;a href="http://laptop.org/"&gt;OLPC&lt;/a&gt; are using technology to respond to social problems and engaging programmers in their communities.
Other than that, lots of issues are being publicly debated and it is our duty to understand them, if not take part in them. The copyright laws are completely out of touch with our everyday behaviors, how can we convince the politicians to work with us? The creative commons and copyleft licenses are trying to address problems with the usual licenses, how are they succeeding? How are they failing? Network neutrality boosts each citizen's right to unbiased and unrestricted information, that's a good thing but how do we do that without stifling investment and availability? &lt;a href="http://kiva.com"&gt;Kiva.com&lt;/a&gt; offers microfinanced loans to people in need, how else can we harness massive audiences for the good of the poorest?
&lt;/p&gt;&lt;p&gt;
Another way to open things up and become more well-rounded is to mix disciplines. Common sense and general resourcefulness dramatically increases with the number of fields we can master or even just be interested in. This approach has known a lot of successes and will know many more. For instance, applying concepts from biology to programming problems led to genetic algorithms, ant colony optimization, agent-based modeling, etc. What else can we mix and match to increase the value of the whole?
&lt;/p&gt;&lt;p&gt;
If we do value individuals over processes and collaboration over contracts, I believe we should pay more attention to how software affects our communities. I believe we should pay more attention to how we can transform our organizations to the employee's benefits, not the other way around. Over the span of our careers, we will have many jobs and many employers. I'm only 25 and I've had 5 employers -- double that number if we are counting jobs outside the IT industry. This kind of track record is now the norm. As software experts and citizens, the only innate responsibility we have is to people and software.
&lt;/p&gt;
&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ted.com/index.php/talks/larry_lessig_says_the_law_is_strangling_creativity.html"&gt;Lawrence Lessig on the state of copyright law (Ted Talk)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas"&gt;Dave Thomas on developing expertise&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-6498951766304353044?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/6498951766304353044/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=6498951766304353044" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6498951766304353044?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/6498951766304353044?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/08/being-more-than-programmers.html" title="being more than programmers" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;AkQCRHg8fyp7ImA9WxdaEU0.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-1634589158246768298</id><published>2008-08-18T19:25:00.009-05:00</published><updated>2008-08-18T20:12:45.677-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-18T20:12:45.677-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="commit" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="check-in" /><title>for frequent commits</title><content type="html">&lt;p&gt;When I code, I always commit as often as possible. I try to bring myself to check code in at least every hour. Here is the case for frequent commits.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The psychological effects&lt;/b&gt; on me are just amazing. The rhythmic process becomes a dragonboat's drum that pushes me forward. If I fail to commit after an hour, I feel like I dropped the ball and end up working harder. The following points are more technical, but this one alone is enough to justify frequent commits.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Breaking down the tasks&lt;/b&gt; into small chunks becomes essential to make the next commit on time. When a task is hard to explode, I get creative and check in tiny bits of functionality at a time. Write a small test, make it pass, check it in. Refactor, check it in. It helps me to always stay in control, I can justify every step I take toward the goal.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Fewer integration conflicts&lt;/b&gt; result since less code is checked in at a time. This one is well understood. Conflicts are bad.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Flexibility&lt;/b&gt;. It makes it easier if I want to pair, go solo, or switch pair. I can "change state" every hour if my heart so desires. Also, if someone needs a piece of code from the story I'm working on, it might already be checked in. Sharing and integration cannot happen soon enough.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Thinner diffs between commits&lt;/b&gt; makes the problem of finding where a bug appeared/re-appeared easier. Once I found the build that "broke the feature", it's a lot easier to dig through a small change and pinpoint the dubious line. As a bonus, the log message for each check-in usually ends up very precise.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Backups.&lt;/b&gt; Every time I commit, I am also making a backup of my code. Losing my local work is never a problem.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Visibility.&lt;/b&gt; The commit log becomes a pulse on the state of each pair or each developer. It becomes another tool for the team or the manager to assess progress. Frequent commits become a sign of good health. How hard the current task is can now be estimated by the interval between commits. A slowdown in the commit rate might raise some questions during the stand-up meeting or the retrospective...
&lt;/p&gt;
&lt;br/&gt;
&lt;p&gt;Frequent commits are a good thing.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-1634589158246768298?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/1634589158246768298/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=1634589158246768298" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/1634589158246768298?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/1634589158246768298?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/08/for-frequent-commits.html" title="for frequent commits" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;CE4AR3oyfSp7ImA9WxdUF08.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-5694146915154211563</id><published>2008-08-02T17:56:00.008-05:00</published><updated>2008-08-02T19:22:26.495-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-02T19:22:26.495-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="smart shuffle" /><title>smart shuffle</title><content type="html">&lt;p&gt;Here's a feature I've always wanted when using an audio player: shuffle the playlist so that all the songs from the same artist are as spread out as possible. You can try it out with the &lt;a href="http://amarok.kde.org"&gt;amarok&lt;/a&gt; player (apt-get users can click &lt;a href="apt://amarok"&gt;this link&lt;/a&gt;), after you've installed &lt;a href="http://www.kde-apps.org/content/show.php/smart+shuffle?content=86483"&gt;this script&lt;/a&gt;. Just right-click the playlist and choose &lt;span style="font-family:Courier"&gt;Smart Shuffle -&gt; Shuffle&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;Here's the Ruby code that does the job, as long as the parameter to &lt;span style="font-family:Courier"&gt;#smart_shuffle&lt;/span&gt; is an array containing elements that respond to &lt;span style="font-family:Courier"&gt;#artist&lt;/span&gt;.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;utils&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;smart_shuffle&lt;/span&gt; playlist&lt;br /&gt;  playlist.shuffle!&lt;br /&gt;  groups = playlist.group_by {|&lt;span class="Identifier"&gt;item&lt;/span&gt;| item.artist}&lt;br /&gt;&lt;br /&gt;  groups.inject([]) {|&lt;span class="Identifier"&gt;decorated_playlist&lt;/span&gt;, &lt;span class="Identifier"&gt;group&lt;/span&gt;|&lt;br /&gt;    decorated_playlist + group.decorate {|&lt;span class="Identifier"&gt;item&lt;/span&gt;, &lt;span class="Identifier"&gt;index&lt;/span&gt;|&lt;br /&gt;      every_n = playlist.length.to_f / group.length.to_f&lt;br /&gt;      rank = every_n * (index + &lt;span class="Constant"&gt;1&lt;/span&gt;) - (every_n / &lt;span class="Constant"&gt;2&lt;/span&gt;.to_f)&lt;br /&gt;    }&lt;br /&gt;  }.sort_by_decoration.undecorate&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's the file it depends on, utils.rb:&lt;br /&gt;&lt;pre style="height:200px; overflow:scroll;"&gt;&lt;span class="PreProc"&gt;class&lt;/span&gt; &lt;span class="Type"&gt;Array&lt;/span&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;shuffle&lt;/span&gt;&lt;br /&gt;    sort_by { rand }&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;shuffle!&lt;/span&gt;&lt;br /&gt;    &lt;span class="Constant"&gt;self&lt;/span&gt;.replace shuffle&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;module&lt;/span&gt; &lt;span class="Type"&gt;Enumerable&lt;/span&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;group_by&lt;/span&gt; &amp;amp;block&lt;br /&gt;    groups = &lt;span class="Type"&gt;Hash&lt;/span&gt;.new(){|&lt;span class="Identifier"&gt;hash&lt;/span&gt;, &lt;span class="Identifier"&gt;key&lt;/span&gt;| hash[key] = []}&lt;br /&gt;    each {|&lt;span class="Identifier"&gt;item&lt;/span&gt;|&lt;br /&gt;      retval = block.call(item)&lt;br /&gt;      retval = &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Unknown&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt; &lt;span class="Statement"&gt;if&lt;/span&gt; retval == &lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt; || retval.nil?&lt;br /&gt;      groups[retval.to_sym] &amp;lt;&amp;lt; item&lt;br /&gt;    }&lt;br /&gt;    groups.values&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;decorate&lt;/span&gt; &amp;amp;block&lt;br /&gt;    decorated = []&lt;br /&gt;    each_with_index {|&lt;span class="Identifier"&gt;item&lt;/span&gt;, &lt;span class="Identifier"&gt;index&lt;/span&gt;|&lt;br /&gt;      decorated &amp;lt;&amp;lt; [block.call(item, index), item]&lt;br /&gt;    }&lt;br /&gt;    decorated&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;sort_by_decoration&lt;/span&gt;&lt;br /&gt;    sort {|&lt;span class="Identifier"&gt;this&lt;/span&gt;, &lt;span class="Identifier"&gt;that&lt;/span&gt;|&lt;br /&gt;      this[&lt;span class="Constant"&gt;0&lt;/span&gt;] &amp;lt;=&amp;gt; that[&lt;span class="Constant"&gt;0&lt;/span&gt;]&lt;br /&gt;    }&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;undecorate&lt;/span&gt;&lt;br /&gt;    map {|&lt;span class="Identifier"&gt;item&lt;/span&gt;| item[&lt;span class="Constant"&gt;1&lt;/span&gt;]}&lt;br /&gt;  &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I'm using a simple &lt;a href="http://en.wikipedia.org/wiki/Decorate-sort-undecorate"&gt;DSU&lt;/a&gt; algorithm where the decoration is given in those two lines:&lt;div class="code"&gt;every_n = playlist.length.to_f / group.length.to_f&lt;br /&gt;rank = every_n * (index + 1) - (every_n / 2.to_f)&lt;/div&gt;&lt;br /&gt;&lt;p&gt;The variable &lt;span style="font-family:Courier"&gt;every_n&lt;/span&gt; is the interval between two songs by the same artist -- a song from this artist should come back every n songs. I calculate the rank based on that, adding one to the index to prevent useless cancellation when it is zero. I subtracted &lt;span style="font-family:Courier"&gt;(every_n / 2.to_f )&lt;/span&gt; simply because it was giving me better results.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-5694146915154211563?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/5694146915154211563/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=5694146915154211563" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5694146915154211563?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5694146915154211563?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/08/smart-shuffle_02.html" title="smart shuffle" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0YEQHY4fip7ImA9WxdUF08.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-826633339372882382</id><published>2008-07-24T22:59:00.016-05:00</published><updated>2008-08-02T18:51:41.836-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-02T18:51:41.836-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quiz" /><category scheme="http://www.blogger.com/atom/ns#" term="command line" /><title>command line quizzes part 3</title><content type="html">&lt;h6&gt;Q: Given that &lt;span style="font-family:Courier"&gt;svn log -q | grep '^r'&lt;/span&gt; gives you a list of all commits and their owners, one per line. Figure out the percentage of commits done by a particular user, since that user's first commit.&lt;/h6&gt;&lt;br /&gt;As an example, we can use the following list of 100 changes to the trunk of the subversion project:&lt;br /&gt;&lt;div class="code" style="height: 190px; overflow:scroll;"&gt;r32295 | xsteve | 2008-07-24 16:54:02 -0500 (Thu, 24 Jul 2008)&lt;br /&gt;r32293 | kfogel | 2008-07-24 11:41:25 -0500 (Thu, 24 Jul 2008)&lt;br /&gt;r32288 | hwright | 2008-07-23 23:15:10 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32286 | hwright | 2008-07-23 18:31:33 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32285 | hwright | 2008-07-23 18:29:10 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32284 | hwright | 2008-07-23 18:27:22 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32279 | xsteve | 2008-07-23 15:48:55 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32277 | xsteve | 2008-07-23 15:37:21 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32276 | jensseidel | 2008-07-23 14:34:01 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32275 | jensseidel | 2008-07-23 14:18:29 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32270 | arfrever | 2008-07-23 11:49:13 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32268 | blair | 2008-07-23 11:13:03 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32255 | sbutler | 2008-07-23 01:45:22 -0500 (Wed, 23 Jul 2008)&lt;br /&gt;r32237 | pburba | 2008-07-22 14:41:23 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32236 | pburba | 2008-07-22 12:32:59 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32235 | jensseidel | 2008-07-22 10:44:15 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32233 | julianfoad | 2008-07-22 10:39:24 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32231 | hwright | 2008-07-22 10:33:18 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32227 | jensseidel | 2008-07-22 10:10:19 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32218 | jensseidel | 2008-07-22 06:33:12 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32217 | julianfoad | 2008-07-22 05:43:39 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32216 | jensseidel | 2008-07-22 03:52:44 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32215 | jensseidel | 2008-07-22 03:32:05 -0500 (Tue, 22 Jul 2008)&lt;br /&gt;r32211 | clkao | 2008-07-21 16:00:05 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32210 | clkao | 2008-07-21 15:47:16 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32209 | cmpilato | 2008-07-21 14:21:13 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32208 | clkao | 2008-07-21 14:20:40 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32207 | kfogel | 2008-07-21 14:07:10 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32206 | cmpilato | 2008-07-21 13:28:25 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32205 | kfogel | 2008-07-21 13:09:46 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32204 | kfogel | 2008-07-21 13:04:59 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32203 | hwright | 2008-07-21 11:16:36 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32202 | danielsh | 2008-07-21 10:44:01 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32199 | julianfoad | 2008-07-21 10:04:14 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32198 | hwright | 2008-07-21 09:59:35 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32194 | julianfoad | 2008-07-21 06:28:47 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32193 | julianfoad | 2008-07-21 06:25:16 -0500 (Mon, 21 Jul 2008)&lt;br /&gt;r32191 | stsp | 2008-07-19 12:37:12 -0500 (Sat, 19 Jul 2008)&lt;br /&gt;r32187 | cmpilato | 2008-07-18 15:10:06 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32185 | hwright | 2008-07-18 14:31:10 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32181 | cmpilato | 2008-07-18 13:28:54 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32179 | cmpilato | 2008-07-18 12:52:41 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32175 | julianfoad | 2008-07-18 08:23:12 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32172 | julianfoad | 2008-07-18 04:53:10 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32171 | clkao | 2008-07-18 00:45:06 -0500 (Fri, 18 Jul 2008)&lt;br /&gt;r32169 | hwright | 2008-07-17 21:47:38 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32166 | clkao | 2008-07-17 14:58:36 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32164 | hwright | 2008-07-17 14:49:29 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32163 | clkao | 2008-07-17 14:46:36 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32162 | xsteve | 2008-07-17 14:30:18 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32160 | cmpilato | 2008-07-17 14:04:39 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32158 | cmpilato | 2008-07-17 10:10:01 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32153 | cmpilato | 2008-07-17 09:10:23 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32152 | fabien | 2008-07-17 08:33:19 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32150 | stsp | 2008-07-17 03:45:04 -0500 (Thu, 17 Jul 2008)&lt;br /&gt;r32147 | kfogel | 2008-07-16 15:35:21 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32146 | xsteve | 2008-07-16 14:44:06 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32145 | kfogel | 2008-07-16 14:17:44 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32144 | kfogel | 2008-07-16 13:59:02 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32142 | pburba | 2008-07-16 13:01:05 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32135 | stylesen | 2008-07-16 03:04:25 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32134 | stylesen | 2008-07-16 02:34:15 -0500 (Wed, 16 Jul 2008)&lt;br /&gt;r32133 | blair | 2008-07-15 19:15:52 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32132 | kfogel | 2008-07-15 14:41:22 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32131 | xsteve | 2008-07-15 14:33:20 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32130 | xsteve | 2008-07-15 13:50:33 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32127 | hwright | 2008-07-15 10:38:22 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32123 | sunny256 | 2008-07-15 05:13:49 -0500 (Tue, 15 Jul 2008)&lt;br /&gt;r32089 | stylesen | 2008-07-14 07:01:32 -0500 (Mon, 14 Jul 2008)&lt;br /&gt;r32088 | julianfoad | 2008-07-14 03:33:46 -0500 (Mon, 14 Jul 2008)&lt;br /&gt;r32084 | nmiyo | 2008-07-13 08:25:00 -0500 (Sun, 13 Jul 2008)&lt;br /&gt;r32083 | stsp | 2008-07-13 04:25:52 -0500 (Sun, 13 Jul 2008)&lt;br /&gt;r32082 | stsp | 2008-07-13 04:21:27 -0500 (Sun, 13 Jul 2008)&lt;br /&gt;r32080 | stsp | 2008-07-13 04:02:42 -0500 (Sun, 13 Jul 2008)&lt;br /&gt;r32079 | danielsh | 2008-07-13 00:53:33 -0500 (Sun, 13 Jul 2008)&lt;br /&gt;r32078 | nmiyo | 2008-07-12 23:19:08 -0500 (Sat, 12 Jul 2008)&lt;br /&gt;r32077 | julianfoad | 2008-07-12 17:10:12 -0500 (Sat, 12 Jul 2008)&lt;br /&gt;r32076 | xsteve | 2008-07-11 15:32:33 -0500 (Fri, 11 Jul 2008)&lt;br /&gt;r32075 | kmradke | 2008-07-11 11:23:45 -0500 (Fri, 11 Jul 2008)&lt;br /&gt;r32074 | nmiyo | 2008-07-11 04:09:13 -0500 (Fri, 11 Jul 2008)&lt;br /&gt;r32071 | arfrever | 2008-07-10 13:00:24 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32068 | arfrever | 2008-07-10 12:13:59 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32066 | julianfoad | 2008-07-10 11:43:14 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32065 | julianfoad | 2008-07-10 11:13:06 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32063 | julianfoad | 2008-07-10 10:42:41 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32060 | julianfoad | 2008-07-10 10:13:20 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32059 | julianfoad | 2008-07-10 09:18:26 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32056 | kameshj | 2008-07-10 07:47:37 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32055 | kameshj | 2008-07-10 06:07:48 -0500 (Thu, 10 Jul 2008)&lt;br /&gt;r32048 | sbutler | 2008-07-09 16:56:32 -0500 (Wed, 09 Jul 2008)&lt;br /&gt;r32043 | julianfoad | 2008-07-08 18:09:40 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32041 | epg | 2008-07-08 16:45:29 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32039 | kfogel | 2008-07-08 15:43:37 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32038 | lgo | 2008-07-08 15:31:04 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32037 | stylesen | 2008-07-08 13:50:49 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32036 | arfrever | 2008-07-08 13:41:29 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32032 | xsteve | 2008-07-08 12:21:58 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32030 | xsteve | 2008-07-08 12:07:16 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32029 | pburba | 2008-07-08 10:02:29 -0500 (Tue, 08 Jul 2008)&lt;br /&gt;r32028 | hwright | 2008-07-07 23:14:38 -0500 (Mon, 07 Jul 2008)&lt;br /&gt;&lt;/div&gt;&lt;p&gt;We want to know the percentage of commits done by the user 'julianfoad' (randomly chosen) since his first commit -- 10th line from the bottom.&lt;/p&gt;&lt;p&gt;The following lines do the trick:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;svn log &lt;span class="Special"&gt;-q&lt;/span&gt; &lt;span class="Special"&gt;--limit&lt;/span&gt; &lt;span class="Constant"&gt;100&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; grep &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;^r&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; cat &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sort &lt;span class="Special"&gt;-nr&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sed &lt;span class="Special"&gt;-ne&lt;/span&gt; &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;/julianfoad/,$ p&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sort &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; wc &lt;span class="Special"&gt;-l&lt;/span&gt;&lt;br /&gt;svn log &lt;span class="Special"&gt;-q&lt;/span&gt; &lt;span class="Special"&gt;--limit&lt;/span&gt; &lt;span class="Constant"&gt;100&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; grep &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;^r&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; cat &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sort &lt;span class="Special"&gt;-nr&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sed &lt;span class="Special"&gt;-ne&lt;/span&gt; &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;/julianfoad/,$ p&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; sort &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; grep julianfoad &lt;span class="Statement"&gt;|&lt;/span&gt; wc &lt;span class="Special"&gt;-l&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;The first line gives the overall number of commits since julianfoad's first: 91.&lt;/p&gt;&lt;p&gt;The second line gives his personal number of commits: 15.&lt;/p&gt;So the percentage is &lt;span style="font-family:Courier"&gt;echo '15/91 * 100' | bc -q&lt;/span&gt;. In english: 16.48%.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-826633339372882382?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/826633339372882382/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=826633339372882382" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/826633339372882382?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/826633339372882382?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/07/command-line-quizzes-part-3.html" title="command line quizzes part 3" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0cDRXs5eCp7ImA9WxdVEUo.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-757756229917444977</id><published>2008-07-14T11:12:00.024-05:00</published><updated>2008-07-15T22:31:14.520-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-15T22:31:14.520-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>the ideal client code as design</title><content type="html">It is still an open question how to approach most programming problems: what to do first? how much design is enough? Some methodologies are trying to answer these questions. TDD comes to mind, or bottom-up programming, or domain-driven design. What I've been trying to discipline myself to do these last few months is to ask myself: what would the perfect interface be?
&lt;br&gt;&lt;br&gt;
I don't code, I don't test. I just ponder about the best possible interface for this new feature. What would ideal code using this feature look like? I'm thinking about the method names and what is the least amount of information that I must give in order to implement the desired behavior. For example, I want to create a window with a given title. Then I want to add a button to it that quits the application, but only quits if the current document does not have outstanding changes.
&lt;br&gt;&lt;br&gt;
I think the following code would look great:
&lt;div class="code"&gt;create_window("title") and add_button do
&amp;nbsp; quit if unchanged
end&lt;/div&gt;

It doesn't matter what functions or classes already exist or how the hell am I going to get a handle to a thousand objects. I try to build the ideal client code. I am using ruby syntax at the moment but I could also use pseudocode -- it might even be more educational using pseudocode.
&lt;br&gt;&lt;br&gt;
As another example, I want to create an email from a string and send it to Bob at 3pm:
&lt;div class="code"&gt;at 3.pm do
&amp;nbsp; create_email("body").send_to(:bob)
end&lt;/div&gt;

The underlying assumption is that if the client code makes sense to the domain expert, the domain code will have to bend over backwards to represent the domain better. For instance we could also fancy sending an email like this:
&lt;div class="code"&gt;send_email("body").to(:bob) | 3.pm&lt;/div&gt;

The two forms look nice to me but if the application represents a clock triggering actions at specific times, I would choose the first one. If the application feels more like an email client, I might choose the second form. The point is that I am free to think about what makes sense in the domain, free from the current codebase, free from scope rules or whatever stupid design decision I made yesterday.
&lt;br&gt;&lt;br&gt;
The way to go from "ideal code" to the actual implementation is usually easy. I like to write the ideal code in a test file, make it compile by whatever means, and increment slowly to hook the code up to the rest of the application. Sometimes a revelation will come and prevent the ideal code from happening and that's fine, although too many of these might be a smell.
&lt;br&gt;&lt;br&gt;
This "client code as design" is of course nothing new. It's in the same cluster as &lt;a href="http://en.wikipedia.org/wiki/Domain_Specific_Language"&gt;DSLs&lt;/a&gt;, and &lt;a href="http://en.wikipedia.org/wiki/User_centered_design"&gt;UCD&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-757756229917444977?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/757756229917444977/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=757756229917444977" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/757756229917444977?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/757756229917444977?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/07/ideal-client-code-as-design.html" title="the ideal client code as design" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkEGQ30zfyp7ImA9WxZaEkw.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-8831448489451816909</id><published>2008-04-26T06:24:00.004-05:00</published><updated>2008-04-26T06:50:22.387-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-26T06:50:22.387-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="email" /><title>postfix / procmail / courier-imap for dummies</title><content type="html">To install a mail server on a unix machine, you can use the following stack:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.postfix.org/"&gt;postfix&lt;/a&gt; : listens for incoming emails and delegates to...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.procmail.org/"&gt;procmail&lt;/a&gt; : delivers emails to each user's mailbox&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.courier-mta.org/imap/"&gt;Courier-IMAP&lt;/a&gt; : listens for pop and imap requests and serves emails&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This is just a high-level installation procedure for a mail server where the users are simply the local users.&lt;br /&gt;&lt;br /&gt;Install postfix and make sure it delegates to procmail by adding the following line to the appropriate section in postfix's main.cf:&lt;br /&gt;&lt;div class="code"&gt;mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=$HOME/Maildir/&lt;/div&gt;&lt;br /&gt;After you make any changes to main.cf, you should run: &lt;div class="code"&gt;postfix reload&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Make sure /etc/procmailrc or $HOME/.procmailrc contains the following lines:&lt;br /&gt;&lt;div class="code"&gt;MAILDIR=$HOME/Maildir&lt;br /&gt;VERBOSE=on&lt;br /&gt;LOGFILE=$MAILDIR/from&lt;br /&gt;&lt;br /&gt;:0&lt;br /&gt;new&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Next, build the maildir by issuing &lt;div class="code"&gt;maildirmake ~/Maildir&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;At this point, we should have a working system, that we can test with something like:&lt;br /&gt;&lt;div class="code"&gt;mail -s hello $USER&lt;br /&gt;Hi,&lt;br /&gt;This is a test&lt;br /&gt;^D&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If everything works fine, the email should be received by postfix, sent to procmail, and delivered to $HOME/Maildir/new.&lt;br /&gt;&lt;br /&gt;To access the emails through POP or IMAP, we need to install Courier-IMAP. Once this is done, start the authdaemond and the courier daemon. Finally, netstat -a should reveal everyone listening: one smtp connection, one POP connection and one IMAP connection.&lt;br /&gt;&lt;div class="code"&gt;tcp        0      0 *:smtp                  *:*                     LISTEN&lt;br /&gt;tcp        0      0 *:imaps                 *:*                     LISTEN&lt;br /&gt;tcp        0      0 *:pop3s                 *:*                     LISTEN&lt;br /&gt;tcp        0      0 *:pop3                  *:*                     LISTEN&lt;br /&gt;tcp        0      0 *:imap                  *:*                     LISTEN&lt;br /&gt;tcp        0      0 localhost.localdom:imap localhost.localdo:34187 ESTABLISHED&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;You can fire up thunderbird and create an account with the local hostname as the POP or IMAP server. You should then be able to send yourself emails.&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;Once this works, you can use and test the &lt;a href="http://www.slantwisedesign.com/rdoc/fetcher/"&gt;fetcher plugin&lt;/a&gt; for Ruby on Rails (more info &lt;a href="http://railspikes.com/2007/6/1/rails-email-processing"&gt;here&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-8831448489451816909?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/8831448489451816909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=8831448489451816909" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/8831448489451816909?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/8831448489451816909?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/04/postfix-procmail-courier-imap-for.html" title="postfix / procmail / courier-imap for dummies" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CU8AQ3syeCp7ImA9WxZWEkk.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-5523865664072875381</id><published>2008-03-10T05:52:00.006-05:00</published><updated>2008-03-11T08:57:22.590-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-11T08:57:22.590-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hugacity" /><category scheme="http://www.blogger.com/atom/ns#" term="hugamovie" /><category scheme="http://www.blogger.com/atom/ns#" term="hugamusic" /><title>hugamovie.com :: hugacity.com :: hugamusic.com</title><content type="html">My brother and I just deployed a couple of web apps that we built together.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.hugamovie.com"&gt;hugamovie.com&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.hugacity.com"&gt;hugacity.com&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.hugamusic.com"&gt;hugamusic.com&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.huganoodle.com"&gt;huganoodle.com&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;They all revolve around the same concept: random items are displayed and the user rates them from 1 to 5. We call it hugging or ditching. Once the users get bored, they can look at the top 10 or the other huga*.com sites.&lt;br/&gt;&lt;br /&gt;Hugacity.com makes use of pictures licensed under the creative commons. The other apps pulled their initial data from Amazon.&lt;br/&gt;&lt;br /&gt;All the sites share the same core of code and were built on top of Rails 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-5523865664072875381?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/5523865664072875381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=5523865664072875381" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5523865664072875381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5523865664072875381?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/03/hugamoviecom-hugacitycom-hugamusiccom.html" title="hugamovie.com :: hugacity.com :: hugamusic.com" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D0MNRno6eip7ImA9WxZQF0g.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-772079068567915736</id><published>2008-02-23T02:22:00.004-06:00</published><updated>2008-02-23T02:31:37.412-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-23T02:31:37.412-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="array" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>handy 'and' and 'or' in Ruby</title><content type="html">Here's a nice shortcut to verify if any member of an array satisfies a predicate, or to verify if all members of an array satisfy the predicate.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;#!/usr/bin/env ruby -w&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;module&lt;/span&gt; &lt;span class="Type"&gt;Enumerable&lt;/span&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;any&lt;/span&gt; sym&lt;br /&gt;        each {|&lt;span class="Identifier"&gt;item&lt;/span&gt;| &lt;span class="Statement"&gt;return&lt;/span&gt; &lt;span class="Constant"&gt;true&lt;/span&gt; &lt;span class="Statement"&gt;if&lt;/span&gt; item.send sym }&lt;br /&gt;        &lt;span class="Statement"&gt;return&lt;/span&gt; &lt;span class="Constant"&gt;false&lt;/span&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;all&lt;/span&gt; sym&lt;br /&gt;        each {|&lt;span class="Identifier"&gt;item&lt;/span&gt;| &lt;span class="Statement"&gt;return&lt;/span&gt; &lt;span class="Constant"&gt;false&lt;/span&gt; &lt;span class="Statement"&gt;if&lt;/span&gt; !item.send sym }&lt;br /&gt;        &lt;span class="Statement"&gt;return&lt;/span&gt; &lt;span class="Constant"&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;puts [&lt;span class="Constant"&gt;1&lt;/span&gt;, &lt;span class="Constant"&gt;2&lt;/span&gt;, &lt;span class="Constant"&gt;3&lt;/span&gt;, &lt;span class="Constant"&gt;0&lt;/span&gt;, &lt;span class="Constant"&gt;nil&lt;/span&gt;].any(&lt;span class="Constant"&gt;:nil?&lt;/span&gt;)&lt;br /&gt;puts [&lt;span class="Constant"&gt;1&lt;/span&gt;, &lt;span class="Constant"&gt;2&lt;/span&gt;, &lt;span class="Constant"&gt;3&lt;/span&gt;, &lt;span class="Constant"&gt;0&lt;/span&gt;].any(&lt;span class="Constant"&gt;:nil?&lt;/span&gt;)&lt;br /&gt;puts [&lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;].all(&lt;span class="Constant"&gt;:empty?&lt;/span&gt;)&lt;br /&gt;puts [&lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;dsa&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;].all(&lt;span class="Constant"&gt;:empty?&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;div class="code"&gt;true&lt;br /&gt;false&lt;br /&gt;true&lt;br /&gt;false&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-772079068567915736?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/772079068567915736/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=772079068567915736" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/772079068567915736?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/772079068567915736?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/handy-and-and-or-in-ruby.html" title="handy 'and' and 'or' in Ruby" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkEMQH4zeSp7ImA9WxZQFkg.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-5498731739777972371</id><published>2008-02-21T20:59:00.000-06:00</published><updated>2008-02-21T22:31:21.081-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-21T22:31:21.081-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="review" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>the craft of functional programming :: review</title><content type="html">I went through most of &lt;a href="http://www.amazon.com/Haskell-Craft-Functional-Programming-2nd/dp/0201342758/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1202699798&amp;sr=8-1"&gt;The Craft of Functional Programming&lt;/a&gt; by Simon Thompson. All in all it was a great learning experience.&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;The book is aimed at beginners and the text is very dense, which saves a lot of time. The exercises were very useful to me and sometimes even enlightening. The one thing I found annoying was the lack of transparency in the sample code snippets: the code given in the book sometimes needs an import from the standard library to function, or it shadows a name from the standard library. All the problems can be solved by referencing the source files or &lt;a href="http://www.haskell.org/hoogle/"&gt;hoogle&lt;/a&gt; but it's not as straightforward as it could be.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The book covers the basics fairly well but is very scarce on program complexity analysis, the type system, and monads.&lt;br/&gt;&lt;br /&gt;If I had to recommend a "track" for learning haskell, it would go like this:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Go through the &lt;a href="http://en.wikibooks.org/wiki/Haskell"&gt;haskell wikibook&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Read &lt;a href="http://www.amazon.com/Haskell-Craft-Functional-Programming-2nd/dp/0201342758/ref=pd_bbs_sr_1?ie=UTF8&amp;s=books&amp;qid=1202699095&amp;sr=8-1"&gt;The Craft of Functional Programming&lt;/a&gt; up to chapter 18&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Read &lt;a href="http://www.haskell.org/haskellwiki/IO_inside"&gt;IO inside&lt;/a&gt; on the haskell wiki&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Read the rest of the book&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Find other more advanced resources...&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;All the while, there are exercises in the wikibook, in the book, on the haskell wiki at &lt;a href="http://haskell.org/haskellwiki/99_Haskell_exercises"&gt;99 problems&lt;/a&gt;, and at &lt;a href="http://projecteuler.net"&gt;project euler&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-5498731739777972371?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/5498731739777972371/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=5498731739777972371" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5498731739777972371?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/5498731739777972371?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/craft-of-functional-programming-review.html" title="the craft of functional programming :: review" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkUFRXs-fSp7ImA9WxRUEEg.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-4231513000458112307</id><published>2008-02-17T20:22:00.018-06:00</published><updated>2008-11-18T17:16:54.555-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-18T17:16:54.555-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="statistics" /><category scheme="http://www.blogger.com/atom/ns#" term="news yc" /><category scheme="http://www.blogger.com/atom/ns#" term="scraping" /><title>news.yc statistics</title><content type="html">I was thinking idle thoughts about the community at &lt;a href="http://news.ycombinator.com"&gt;news.yc&lt;/a&gt; and I decided to pull out a few statistics. I found &lt;a href="http://ycombinator.com/newsnews.html"&gt;the following page&lt;/a&gt; with some stats on it but I wanted more.&lt;br/&gt;&lt;br /&gt;The following was deduced from a sample of about &lt;b&gt;130 users&lt;/b&gt;, including the 50 &lt;a href="http://news.ycombinator.com/leaders"&gt;leaders&lt;/a&gt;. This is a small sample and I can only access 180 posts per user, so this is not perfect, but still interesting. Note: for a few of those statistics, I only considered users with more than 8 posts.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Total number of posts: 8317&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Total number of points on those posts: 42458&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Minimum points per post ratio: 0.72&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Maximum points per post ratio: 20.2&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mean points per post ratio: 5.75&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Std deviation on the ratio: 3.22&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Overall points per post ratio: 5.10&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mean number of posts: 62.00&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Std deviation on the number of posts: 68.36&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;When a user has a high points per post ratio, he is probably representative of the community. All kinds of guidelines could be derived from this: if a user's points per post ratio is too low below the average, they probably are posting too much, or not a strong link in the community as a submitter. If the standard deviation on the mean ratio is low, then the community is rather cohesive: lots of people interact without leading or counting on others. If the standard deviation is high, than the users are possibly separated in two groups, one reading the posts of the other. These kinds of statistics might be useful as an early index of community 'dilution'.&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;Here's a graph showing the points per post against the number of posts.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_c-z10zbSfTE/R7kDuSANVXI/AAAAAAAAABo/qNs-6fv7Csg/s1600-h/plot_all.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_c-z10zbSfTE/R7kDuSANVXI/AAAAAAAAABo/qNs-6fv7Csg/s400/plot_all.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5168166141025932658" /&gt;&lt;/a&gt;&lt;br /&gt;We can see that it's very hard to maintain a good points per post ratio when the number of posts reaches about 40. Also, if a newcomer wanted to know what kind of users are on news YC, we should point them to paul, palish, sharpshoot, or pg.&lt;br /&gt;&lt;br /&gt;Here's the same graph but only showing the leaders.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_c-z10zbSfTE/R7j2ZCANVWI/AAAAAAAAABg/qv9TwgwkgKQ/s1600-h/plot_leaders.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_c-z10zbSfTE/R7j2ZCANVWI/AAAAAAAAABg/qv9TwgwkgKQ/s400/plot_leaders.png" alt=""id="BLOGGER_PHOTO_ID_5168151482302551394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zoom on the users with 180 posts:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_c-z10zbSfTE/R7juuSANVTI/AAAAAAAAABM/5DOZI9lIKhQ/s1600-h/plot_all_180.png"&gt;&lt;img style="cursor:pointer; cursor:hand;display:block; margin:0px auto 10px; text-align:center;" src="http://1.bp.blogspot.com/_c-z10zbSfTE/R7juuSANVTI/AAAAAAAAABM/5DOZI9lIKhQ/s400/plot_all_180.png"  alt=""id="BLOGGER_PHOTO_ID_5168143051281749298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zoom on the bottom left cluster for all users:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_c-z10zbSfTE/R7jujiANVSI/AAAAAAAAABE/Ru-S-RqRN8c/s1600-h/plot_all_cluster.png"&gt;&lt;img style="cursor:pointer; cursor:hand;display:block; margin:0px auto 10px; text-align:center;" src="http://2.bp.blogspot.com/_c-z10zbSfTE/R7jujiANVSI/AAAAAAAAABE/Ru-S-RqRN8c/s400/plot_all_cluster.png" alt=""id="BLOGGER_PHOTO_ID_5168142866598155554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Read the comments on this at &lt;a href="http://news.ycombinator.com/item?id=117938"&gt;news YC&lt;/a&gt;.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Here is the ruby code that I used. You can tweak it to find out your own points per post ratio.&lt;br/&gt;&lt;br /&gt;go.rb&lt;br /&gt;&lt;pre style="height:200px;"&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;#!/usr/bin/env ruby&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;require&lt;/span&gt; &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;open-uri&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Type"&gt;HOSTNAME&lt;/span&gt; = &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;&lt;a href="http://news.ycombinator.com/"&gt;http://news.ycombinator.com/&lt;/a&gt;&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="Type"&gt;LOG&lt;/span&gt; = &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;... &lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;compute&lt;/span&gt;(user, url, total_points, total_posts)&lt;br /&gt;    more_url = &lt;span class="Constant"&gt;nil&lt;/span&gt;&lt;br /&gt;    open(&lt;span class="Type"&gt;HOSTNAME&lt;/span&gt; + url) {|&lt;span class="Identifier"&gt;doc&lt;/span&gt;|&lt;br /&gt;        doc.read.each {|&lt;span class="Identifier"&gt;line&lt;/span&gt;|&lt;br /&gt;            more_url = find_more_url line &lt;span class="Statement"&gt;if&lt;/span&gt; more_url.nil?&lt;br /&gt;            line.scan(&lt;span class="Special"&gt;/&lt;/span&gt;&lt;span class="Constant"&gt;(\d*) point[s]{0,1}&amp;lt;\/span&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;/&lt;/span&gt;) &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;match&lt;/span&gt;|&lt;br /&gt;                &lt;span class="Comment"&gt;#puts &amp;quot;analysing match: #{match}&amp;quot;&lt;/span&gt;&lt;br /&gt;                total_points += (match[&lt;span class="Constant"&gt;0&lt;/span&gt;].to_i - &lt;span class="Constant"&gt;1&lt;/span&gt;) &lt;span class="Comment"&gt;#posts start at one point&lt;/span&gt;&lt;br /&gt;                total_posts += &lt;span class="Constant"&gt;1&lt;/span&gt;&lt;br /&gt;            &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="Statement"&gt;begin&lt;/span&gt;&lt;br /&gt;        sleep(&lt;span class="Constant"&gt;5&lt;/span&gt;)&lt;br /&gt;        puts &lt;span class="Type"&gt;LOG&lt;/span&gt; + &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;page done&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="Identifier"&gt;$stdout&lt;/span&gt;.flush&lt;br /&gt;        &lt;span class="Comment"&gt;#if there is a more button, follow it and recurse&lt;/span&gt;&lt;br /&gt;        total_points, total_posts = compute(user, more_url, total_points, total_posts) &lt;span class="Statement"&gt;unless&lt;/span&gt; more_url.nil?&lt;br /&gt;    &lt;span class="Statement"&gt;rescue&lt;/span&gt;&lt;br /&gt;        puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;caught &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;&lt;span class="Identifier"&gt;$!&lt;/span&gt;&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;stopped after &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_posts&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; posts for user &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;user&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;    &lt;span class="Statement"&gt;return&lt;/span&gt; [total_points, total_posts]&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;go&lt;/span&gt; users&lt;br /&gt;    users.each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;user&lt;/span&gt;|&lt;br /&gt;        puts &lt;span class="Type"&gt;LOG&lt;/span&gt; + &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;processing &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;user&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="Identifier"&gt;$stdout&lt;/span&gt;.flush&lt;br /&gt;        &lt;span class="Statement"&gt;begin&lt;/span&gt;&lt;br /&gt;            total_points, total_posts = compute(user, &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;submitted?id=&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;user&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;, &lt;span class="Constant"&gt;0&lt;/span&gt;, &lt;span class="Constant"&gt;0&lt;/span&gt;)&lt;br /&gt;            ratio = total_points.to_f / total_posts&lt;br /&gt;            puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;user&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_points&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_posts&lt;span                   class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;sprintf(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;%.2f&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;, ratio)&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="Statement"&gt;rescue&lt;/span&gt;&lt;br /&gt;            puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;caught &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;&lt;span class="Identifier"&gt;$!&lt;/span&gt;&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;            puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;user &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;user&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Constant"&gt; not processed&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;    &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;find_more_url&lt;/span&gt; line&lt;br /&gt;    &lt;span class="Statement"&gt;if&lt;/span&gt; line =~ &lt;span class="Special"&gt;/&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;a href=&amp;quot;([^&amp;quot;]*?)&amp;quot; rel=&amp;quot;nofollow&amp;quot;&amp;gt;More&amp;lt;\/a&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;/&lt;/span&gt;&lt;br /&gt;        &lt;span class="Identifier"&gt;$1&lt;/span&gt;&lt;br /&gt;    &lt;span class="Statement"&gt;else&lt;/span&gt;&lt;br /&gt;        &lt;span class="Constant"&gt;nil&lt;/span&gt;&lt;br /&gt;    &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;file2list&lt;/span&gt; file&lt;br /&gt;    users = []&lt;br /&gt;    &lt;span class="Type"&gt;File&lt;/span&gt;.open(file) {|&lt;span class="Identifier"&gt;f&lt;/span&gt;|&lt;br /&gt;        f.each {|&lt;span class="Identifier"&gt;line&lt;/span&gt;|&lt;br /&gt;            users.push line.chomp &lt;span class="Statement"&gt;unless&lt;/span&gt; line.nil?&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    users&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;extract_names&lt;/span&gt; users, url=&lt;span class="Special"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    more_url = &lt;span class="Constant"&gt;nil&lt;/span&gt;&lt;br /&gt;    open(&lt;span class="Type"&gt;HOSTNAME&lt;/span&gt; + url) {|&lt;span class="Identifier"&gt;doc&lt;/span&gt;|&lt;br /&gt;        puts &lt;span class="Special"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;transferring data&lt;/span&gt;&lt;span class="Special"&gt;'&lt;/span&gt;&lt;br /&gt;        doc.readlines.each {|&lt;span class="Identifier"&gt;line&lt;/span&gt;|&lt;br /&gt;            more_url = find_more_url line &lt;span class="Statement"&gt;if&lt;/span&gt; more_url.nil?&lt;br /&gt;            line.scan(&lt;span class="Special"&gt;/&lt;/span&gt;&lt;span class="Constant"&gt;&amp;lt;a href=&amp;quot;user\?id=([^&amp;quot;]*)&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class="Special"&gt;/&lt;/span&gt;) &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;match&lt;/span&gt;|&lt;br /&gt;                users.push match[&lt;span class="Constant"&gt;0&lt;/span&gt;] &lt;span class="Statement"&gt;unless&lt;/span&gt; users.include? match[&lt;span class="Constant"&gt;0&lt;/span&gt;]&lt;br /&gt;            &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    users = extract_names(users, more_url) &lt;span class="Statement"&gt;unless&lt;/span&gt; more_url.nil?&lt;br /&gt;    &lt;span class="Statement"&gt;return&lt;/span&gt; users&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#extract_names([]).each {|u| puts u}&lt;/span&gt;&lt;br /&gt;go(file2list(&lt;span class="Identifier"&gt;ARGV&lt;/span&gt;[&lt;span class="Constant"&gt;0&lt;/span&gt;]))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;extract.rb&lt;br /&gt;&lt;pre style="height:200px;"&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#[0] = name&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#[1] = points&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#[2] = posts&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#[3] = ratio&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;std_deviation&lt;/span&gt; data, mean, index&lt;br /&gt;    sq_errors = &lt;span class="Constant"&gt;0.0&lt;/span&gt;&lt;br /&gt;    data.each {|&lt;span class="Identifier"&gt;row&lt;/span&gt;|&lt;br /&gt;        sq_errors += (row[index] - mean)**&lt;span class="Constant"&gt;2&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Std deviation: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;&lt;span class="Type"&gt;Math&lt;/span&gt;::sqrt(sq_errors/data.length)&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;num_posts_metrics&lt;/span&gt; data&lt;br /&gt;    min = &lt;span class="Constant"&gt;99999&lt;/span&gt;&lt;br /&gt;    max = &lt;span class="Constant"&gt;0&lt;/span&gt;&lt;br /&gt;    total_posts = &lt;span class="Constant"&gt;0&lt;/span&gt;&lt;br /&gt;    data.each {|&lt;span class="Identifier"&gt;row&lt;/span&gt;|&lt;br /&gt;        total_posts += row[&lt;span class="Constant"&gt;2&lt;/span&gt;]&lt;br /&gt;        min = row[&lt;span class="Constant"&gt;2&lt;/span&gt;] &lt;span class="Statement"&gt;if&lt;/span&gt; row[&lt;span class="Constant"&gt;2&lt;/span&gt;] &amp;lt; min&lt;br /&gt;        max = row[&lt;span class="Constant"&gt;2&lt;/span&gt;] &lt;span class="Statement"&gt;if&lt;/span&gt; row[&lt;span class="Constant"&gt;2&lt;/span&gt;] &amp;gt; max&lt;br /&gt;    }&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Total posts: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_posts&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Min # posts: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;min&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Max # posts: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;max&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    mean_num_posts = total_posts/data.length&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Mean # posts: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;sprintf(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;%.2f&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;, mean_num_posts)&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    std_deviation(data, mean_num_posts, &lt;span class="Constant"&gt;2&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;ratio_metrics&lt;/span&gt; data&lt;br /&gt;    min = &lt;span class="Constant"&gt;9999&lt;/span&gt;&lt;br /&gt;    max = &lt;span class="Constant"&gt;0&lt;/span&gt;&lt;br /&gt;    total_posts = &lt;span class="Constant"&gt;0&lt;/span&gt;&lt;br /&gt;    total_points = &lt;span class="Constant"&gt;0&lt;/span&gt;&lt;br /&gt;    sum_ratio = &lt;span class="Constant"&gt;0.0&lt;/span&gt;&lt;br /&gt;    data.each {|&lt;span class="Identifier"&gt;row&lt;/span&gt;|&lt;br /&gt;        total_posts += row[&lt;span class="Constant"&gt;2&lt;/span&gt;]&lt;br /&gt;        total_points += row[&lt;span class="Constant"&gt;1&lt;/span&gt;]&lt;br /&gt;        min = row[&lt;span class="Constant"&gt;3&lt;/span&gt;] &lt;span class="Statement"&gt;if&lt;/span&gt; row[&lt;span class="Constant"&gt;3&lt;/span&gt;] &amp;lt; min&lt;br /&gt;        max = row[&lt;span class="Constant"&gt;3&lt;/span&gt;] &lt;span class="Statement"&gt;if&lt;/span&gt; row[&lt;span class="Constant"&gt;3&lt;/span&gt;] &amp;gt; max&lt;br /&gt;        sum_ratio += row[&lt;span class="Constant"&gt;3&lt;/span&gt;]&lt;br /&gt;    }&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Total posts: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_posts&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Total points: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;total_points&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Min ratio: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;min&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Max ratio: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;max&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    mean_ratio = sum_ratio/data.length&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Mean ratio: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;sprintf(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;%.2f&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;, mean_ratio)&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;    overall_ratio = total_points.to_f / total_posts&lt;br /&gt;    puts &lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;Overall ratio: &lt;/span&gt;&lt;span class="Special"&gt;#{&lt;/span&gt;sprintf(&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Constant"&gt;%.2f&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;, overall_ratio)&lt;span class="Special"&gt;}&lt;/span&gt;&lt;span class="Special"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    std_deviation(data, mean_ratio, &lt;span class="Constant"&gt;3&lt;/span&gt;)&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#munge munge&lt;/span&gt;&lt;br /&gt;data = []&lt;br /&gt;&lt;span class="Type"&gt;File&lt;/span&gt;.open(&lt;span class="Identifier"&gt;ARGV&lt;/span&gt;[&lt;span class="Constant"&gt;0&lt;/span&gt;]){|&lt;span class="Identifier"&gt;file&lt;/span&gt;|&lt;br /&gt;    file.each &lt;span class="Statement"&gt;do&lt;/span&gt; |&lt;span class="Identifier"&gt;line&lt;/span&gt;|&lt;br /&gt;        data &amp;lt;&amp;lt; line.chomp.split&lt;br /&gt;    &lt;span class="Statement"&gt;end&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;data = data.map {|&lt;span class="Identifier"&gt;row&lt;/span&gt;|&lt;br /&gt;    [row[0], row[1].to_i, row[2].to_i, row[3].to_f]&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#output&lt;/span&gt;&lt;br /&gt;ratio_metrics(data.select {|&lt;span class="Identifier"&gt;row&lt;/span&gt;|&lt;br /&gt;    row[&lt;span class="Constant"&gt;2&lt;/span&gt;] &amp;gt; &lt;span class="Constant"&gt;8&lt;/span&gt;&lt;br /&gt;})&lt;br /&gt;puts&lt;br /&gt;num_posts_metrics data&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-4231513000458112307?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/4231513000458112307/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=4231513000458112307" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/4231513000458112307?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/4231513000458112307?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/newsyc-statistics.html" title="news.yc statistics" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_c-z10zbSfTE/R7kDuSANVXI/AAAAAAAAABo/qNs-6fv7Csg/s72-c/plot_all.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0MARno_fip7ImA9WxZQEk0.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-2142387530038432860</id><published>2008-02-14T23:23:00.010-06:00</published><updated>2008-02-16T16:37:27.446-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-16T16:37:27.446-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quiz" /><category scheme="http://www.blogger.com/atom/ns#" term="command line" /><category scheme="http://www.blogger.com/atom/ns#" term="unix" /><title>command line quizzes part 2</title><content type="html">Here's part two of the command line quizzes. Part one can be found &lt;a href="http://clipboarded.blogspot.com/2008/02/command-line-quizzes-part-1.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;h6&gt;Q: Given that "top -b -n 1" gives the following output, write a script which kills all processes that use more than 25% of the processing power.&lt;/h6&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;Tasks:  85 total,   1 running,  84 sleeping,   0 stopped,   0 zombie&lt;br /&gt;Cpu(s):  4.7%us,  0.6%sy,  0.0%ni, 93.7%id,  0.8%wa,  0.2%hi,  0.1%si,  0.0%st&lt;br /&gt;Mem:    506372k total,   495416k used,    10956k free,    12364k buffers&lt;br /&gt;Swap:        0k total,        0k used,        0k free,   195588k cached&lt;br /&gt;&lt;br /&gt;  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND&lt;br /&gt; 6159 root      19  -1  357m  38m 5380 S  2.0  7.9   7:02.21 X&lt;br /&gt; 6271 mats      20   0  123m  38m  25m S  2.0  7.8   1:33.09 amarokapp&lt;br /&gt; 6287 mats      20   0 25840 9916 7324 S  2.0  2.0   0:29.45 gkrellm&lt;br /&gt;    1 root      20   0  1612  544  472 S  0.0  0.1   0:00.84 init&lt;br /&gt;    2 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 kthreadd&lt;br /&gt;    3 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 migration/0&lt;br /&gt;    4 root      15  -5     0    0    0 S  0.0  0.0   0:02.08 ksoftirqd/0&lt;br /&gt;    5 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 watchdog/0&lt;br /&gt;    6 root      15  -5     0    0    0 S  0.0  0.0   0:00.16 events/0&lt;br /&gt;    7 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 khelper&lt;br /&gt;   42 root      15  -5     0    0    0 S  0.0  0.0   0:00.11 kblockd/0&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Here's a solution.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#script to kill all processes which use more than 25% of the cpu&lt;/span&gt;&lt;br /&gt;top &lt;span class="Special"&gt;-b&lt;/span&gt; &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Constant"&gt;1&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; awk &lt;span class="Statement"&gt;'&lt;/        span&gt;&lt;span class="Constant"&gt;NR &amp;gt;= 8 &amp;amp;&amp;amp; $9 &amp;gt; 25 {print $1}&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; xargs &lt;span                 class="Special"&gt;-r&lt;/span&gt; &lt;span class="Statement"&gt;kill&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thanks to Ralph for this solution.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;h6&gt;Q: Given the following two CSS files, write a script to verify that every class is only defined once (catch duplicate declarations).&lt;/h6&gt;&lt;br /&gt;File 1: first.css&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Statement"&gt;body&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-family&lt;/span&gt;:Verdana;&lt;span class="Identifier"&gt;}&lt;/  span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.header&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-size&lt;/span&gt;:&lt;span class="Constant"&gt;90%&lt;/span&gt;;  &lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.article&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;line-height&lt;/span&gt;:&lt;span class="Constant"&gt;1.1em&lt;/   span&gt;;&lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.footer&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-size&lt;/span&gt;:&lt;span class="Constant"&gt;80%&lt;/span&gt;;  &lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.main&lt;/span&gt; &lt;span class="Identifier"&gt;.left&lt;/span&gt; &lt;span class="Identifier"&gt;#contents&lt;/span&gt; &lt;span                      class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;float&lt;/span&gt;:&lt;span class="Type"&gt;left&lt;/span&gt;;&lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;File 2: second.css&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;#article&lt;/span&gt; &lt;span class="Identifier"&gt;.title&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-size&lt;/span&gt;:&lt;span                  class="Constant"&gt;110%&lt;/span&gt;;&lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.header&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-weight&lt;/span&gt;:&lt;span class="Type"&gt;bold&lt;/span&gt;;&lt;span class="Identifier"&gt;}&lt;/  span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.email&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;font-family&lt;/span&gt;:Courier;&lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.address&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;line-height&lt;/span&gt;:&lt;span class="Constant"&gt;0.8em&lt;/span&gt;;&lt;span                   class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;.left&lt;/span&gt; &lt;span class="Identifier"&gt;{&lt;/span&gt;&lt;span class="Type"&gt;text-align&lt;/span&gt;:&lt;span class="Type"&gt;left&lt;/span&gt;;&lt;span class="Identifier"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's a solution.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#script to find out if two css files contain the same class name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#Use sed to filter out the css rules and put all the ids and classes on their own line&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#Use sed again to only keep the class names&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#Use sort and uniq to figure out the dups&lt;/span&gt;&lt;br /&gt;&lt;span class="Identifier"&gt;classnames&lt;/span&gt;=&lt;span class="PreProc"&gt;$(&lt;/span&gt;&lt;span class="Statement"&gt;sed&lt;/span&gt;&lt;span class="Special"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/    span&gt;&lt;span class="Constant"&gt;s/&lt;/span&gt;&lt;span class="Special"&gt;\(&lt;/span&gt;&lt;span class="Constant"&gt;[^{]*&lt;/span&gt;&lt;span class="Special"&gt;\)&lt;/span&gt;&lt;span class="Constant"&gt;.*/\1/g&lt;/      span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Special"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;s/ /\n/g&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/     span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="PreProc"&gt;$@&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span         class="Statement"&gt;sed&lt;/span&gt;&lt;span class="Special"&gt; -n -e &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;/\.\w\+/ p&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/         span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;sort&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span     class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; uniq -dc &lt;/span&gt;&lt;span class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;sort&lt;/span&gt;&lt;span     class="Special"&gt; -&lt;/span&gt;&lt;span class="Statement"&gt;r&lt;/span&gt;&lt;span class="PreProc"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;echo&lt;/span&gt;&lt;span class="Constant"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Special"&gt;\n&lt;/span&gt;&lt;span class="Constant"&gt;Duplicate   classes:&lt;/span&gt;&lt;span class="Special"&gt;\n&lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;echo&lt;/span&gt;&lt;span class="Constant"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span class="PreProc"&gt;$classnames&lt;/span&gt;&lt;span                        class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;echo&lt;/span&gt;&lt;span class="Constant"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Special"&gt;\n&lt;/span&gt;&lt;span class="Constant"&gt;Grepped     files:&lt;/span&gt;&lt;span class="Special"&gt;\n&lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#grep the files in argument for the class names found above&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;grep&lt;/span&gt; &lt;span class="Special"&gt;--color&lt;/span&gt; &lt;span class="Special"&gt;-n&lt;/span&gt; &lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span class="PreProc"&gt;$(&lt;/    span&gt;&lt;span class="Special"&gt;echo &lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span class="PreProc"&gt;$classnames&lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt;&lt;span              class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; awk &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;{print $2}&lt;/span&gt;&lt;span     class="Statement"&gt;'&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;|&lt;/span&gt;&lt;span class="Special"&gt; &lt;/span&gt;&lt;span class="Statement"&gt;sed&lt;/span&gt;&lt;span               class="Special"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;s/\./&lt;/span&gt;&lt;span class="Special"&gt;\\&lt;/span&gt;&lt;span class="Constant"&gt;./g&lt;/span&gt;&lt;span         class="Statement"&gt;'&lt;/span&gt;&lt;span class="Special"&gt; -e &lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;s/\n/\|/g&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span     class="PreProc"&gt;)&lt;/span&gt;&lt;span class="Statement"&gt;&amp;quot;&lt;/span&gt; &lt;span class="PreProc"&gt;$@&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It can be called like so.&lt;br /&gt;&lt;div class="code"&gt;./dupcss.sh first.css second.css&lt;/div&gt;&lt;br /&gt;And gives the following output.&lt;br /&gt;&lt;div class="code"&gt;Duplicate classes:&lt;br /&gt;&lt;br /&gt;      2 .left&lt;br /&gt;      2 .header&lt;br /&gt;&lt;br /&gt;Grepped files:&lt;br /&gt;&lt;br /&gt;first.css:2:.header {font-size:90%;}&lt;br /&gt;first.css:5:.main .left #contents {float:left;}&lt;br /&gt;second.css:2:.header {font-weight:bold;}&lt;br /&gt;second.css:5:.left {text-align:left;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Grepping the files and displaying the results is just a convenience to the user.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;I don't have any other quizzes on the back burner but I do have a few good links:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.cs.hmc.edu/qref/awk.html"&gt;Getting started with awk&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.grymoire.com/Unix/Sed.html"&gt;Sed - an intro and tutorial&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html"&gt;bash how-to&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://tnerual.eriogerg.free.fr/vim.html"&gt;vim cheat sheet&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.cheat-sheets.org"&gt;cheat-sheets.org&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-2142387530038432860?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/2142387530038432860/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=2142387530038432860" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/2142387530038432860?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/2142387530038432860?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/command-line-quizzes-part-2.html" title="command line quizzes part 2" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;DUUAQ38_fip7ImA9WxZQEEg.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7930590811063662765</id><published>2008-02-13T00:51:00.016-06:00</published><updated>2008-02-15T00:34:02.146-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-15T00:34:02.146-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quiz" /><category scheme="http://www.blogger.com/atom/ns#" term="command line" /><category scheme="http://www.blogger.com/atom/ns#" term="unix" /><title>command line quizzes part 1</title><content type="html">When I wanted to learn about bash and the unix command line tools, I looked for some easy quizzes and challenges but could not find any. Here's two for a start. (edit: part two can be found &lt;a href="http://clipboarded.blogspot.com/2008/02/command-line-quizzes-part-2.html"&gt;here&lt;/a&gt;)&lt;br /&gt;&lt;h6&gt;Q: Find the most common 4-letter word in the following text.&lt;/h6&gt;&lt;br /&gt;&lt;div style="font-size:80%; padding:2px 15px 15px 15px; border:1px #aaa solid; font-family:monospace;"&gt;&lt;br /&gt;Ruby is a pink to blood red gemstone, a variety of the mineral corundum (aluminium oxide). The common red color is caused mainly by the element        chromium. Its name comes from ruber, Latin for red. Other varieties of gem-quality corundum are called sapphires. It is considered one of the four     precious stones, together with the sapphire, the emerald and the diamond. Improvements used include color alteration, improving transparency by        dissolving rutile inclusions, healing of fractures (cracks) or even completely filling them.&lt;br /&gt;&lt;br /&gt;Prices of rubies are primarily determined by color (the brightest and best "red" called Pigeon Blood Red, command a huge premium over other rubies of  similar quality). After color follows clarity: similar to diamonds, a clear stone will command a premium, but a ruby without any needle-like rutile    inclusions will indicate the stone has been treated one way or another. Cut and carat (size) will also determine the price.&lt;br /&gt;&lt;br /&gt;Rubies have a hardness of 9.0 on the Mohs scale of mineral hardness. Among the natural gems only diamond is harder, with a Mohs 10.0 by definition.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Here's a solution.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#a script to find the most common 4-letter word in a text file&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;sed&lt;/span&gt; &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span class="Constant"&gt;s/ /\n/g&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; text.txt &lt;span class="Statement"&gt;|&lt;/span&gt; &lt;span class="Statement"&gt;grep&lt;/span&gt; &lt;span class="Special"&gt;-E&lt;/span&gt; &lt;span class="Statement"&gt;'&lt;/span&gt;&lt;span             class="Constant"&gt;^\w{4}$&lt;/span&gt;&lt;span class="Statement"&gt;'&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; &lt;span class="Statement"&gt;sort&lt;/span&gt; &lt;span             class="Statement"&gt;|&lt;/span&gt; uniq &lt;span class="Special"&gt;-c&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; &lt;span class="Statement"&gt;sort&lt;/span&gt; &lt;span             class="Special"&gt;-r&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; head &lt;span class="Constant"&gt;-1&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Giving the following output. The most common 4-letter word is 'will' with 3 occurrences.&lt;br /&gt;&lt;div class="code"&gt;3 will&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;h6&gt;Q: Write a 10x10 matrix with random integers from 0 to 9 to standard output.&lt;/h6&gt;&lt;br /&gt;Here's a solution.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;#a script to generate a 10x10 matrix with random numbers from 0 to 9&lt;/span&gt;&lt;br /&gt;&lt;span class="Statement"&gt;for&lt;/span&gt; i &lt;span class="Statement"&gt;in&lt;/span&gt; &lt;span class="Special"&gt;`seq &lt;/span&gt;&lt;span class="Constant"&gt;1&lt;/span&gt;&lt;span          class="Special"&gt; &lt;/span&gt;&lt;span class="Constant"&gt;10&lt;/span&gt;&lt;span class="Special"&gt;`&lt;/span&gt;&lt;span class="Statement"&gt;;&lt;/span&gt; &lt;span class="Statement"&gt;do&lt;/    span&gt;&lt;br /&gt; &lt;span class="Statement"&gt;for&lt;/span&gt; i &lt;span class="Statement"&gt;in&lt;/span&gt; &lt;span class="Special"&gt;`seq &lt;/span&gt;&lt;span class="Constant"&gt;1&lt;/span&gt;&lt;span         class="Special"&gt; &lt;/span&gt;&lt;span class="Constant"&gt;10&lt;/span&gt;&lt;span class="Special"&gt;`&lt;/span&gt;&lt;span class="Statement"&gt;;&lt;/span&gt; &lt;span class="Statement"&gt;do&lt;/span&gt; &lt;span class="Statement"&gt;expr&lt;/span&gt; &lt;span class="PreProc"&gt;$RANDOM&lt;/span&gt; % &lt;span class="Constant"&gt;10&lt;/span&gt;&lt;span class="Statement"&gt;;&lt;/span&gt; &lt;span class="Statement"&gt;done&lt;/span&gt; &lt;span class="Statement"&gt;|&lt;/span&gt; xargs&lt;br /&gt;&lt;span class="Statement"&gt;done&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Giving the following output.&lt;br /&gt;&lt;div class="code"&gt;3 1 0 3 8 5 7 7 0 8&lt;br /&gt;4 5 1 8 8 0 8 7 5 4&lt;br /&gt;6 1 1 3 6 4 8 8 0 9&lt;br /&gt;6 6 1 8 6 9 9 6 3 4&lt;br /&gt;5 1 7 2 1 4 5 4 8 5&lt;br /&gt;7 5 8 7 9 9 5 4 2 1&lt;br /&gt;7 0 8 2 9 4 6 2 7 8&lt;br /&gt;8 6 8 6 9 9 6 3 2 3&lt;br /&gt;8 1 9 3 9 6 7 3 5 8&lt;br /&gt;8 5 9 8 9 0 7 1 0 3&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7930590811063662765?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7930590811063662765/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7930590811063662765" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7930590811063662765?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7930590811063662765?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/command-line-quizzes-part-1.html" title="command line quizzes part 1" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DUIBQnoyeCp7ImA9WxZRGEU.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7937363482698924949</id><published>2008-02-09T22:27:00.001-06:00</published><updated>2008-02-13T01:25:53.490-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-13T01:25:53.490-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="project euler" /><category scheme="http://www.blogger.com/atom/ns#" term="haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="solutions" /><title>project euler in Haskell</title><content type="html">I was looking for a way to practice my lowly haskell skills and I found &lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt;. All my solutions can be found at Google Code: &lt;a href="http://code.google.com/p/myhseuler/"&gt;myhseuler&lt;/a&gt;. I solved a bit more than 30 problems as of this writing.&lt;br /&gt;&lt;br/&gt;You can check it out like so:&lt;br /&gt;&lt;div class="code"&gt;svn checkout http://myhseuler.googlecode.com/svn/trunk/ myhseuler-read-only&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7937363482698924949?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7937363482698924949/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7937363482698924949" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7937363482698924949?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7937363482698924949?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/project-euler-in-haskell.html" title="project euler in Haskell" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkYBR3Y7eyp7ImA9WxZRGE8.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-4734936324268080630</id><published>2008-02-03T18:40:00.000-06:00</published><updated>2008-02-12T06:42:36.803-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-12T06:42:36.803-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="composition" /><title>function composition in Ruby</title><content type="html">Here is an easy way to compose functions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;#!/usr/bin/env ruby&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Comment"&gt;# method composition example&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;# &amp;gt; require 'compose'&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;# &amp;gt; (method(:multwo) &amp;lt;&amp;lt; method(:multwo) &amp;lt;&amp;lt; method(:add)).call(2,3)&lt;/span&gt;&lt;br /&gt;&lt;span class="Comment"&gt;# =&amp;gt; 20&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;class&lt;/span&gt; &lt;span class="Type"&gt;Proc&lt;/span&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;&amp;lt;&amp;lt;&lt;/span&gt; g&lt;br /&gt;      &lt;span class="Statement"&gt;lambda&lt;/span&gt; {|*&lt;span class="Identifier"&gt;args&lt;/span&gt;| &lt;span class="Constant"&gt;self&lt;/span&gt;.call(g.call(*args)) }&lt;br /&gt;    &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;class&lt;/span&gt; &lt;span class="Type"&gt;Method&lt;/span&gt;&lt;br /&gt;    &lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;&amp;lt;&amp;lt;&lt;/span&gt; g&lt;br /&gt;      &lt;span class="Statement"&gt;lambda&lt;/span&gt; {|*&lt;span class="Identifier"&gt;args&lt;/span&gt;| &lt;span class="Constant"&gt;self&lt;/span&gt;.call(g.call(*args)) }&lt;br /&gt;    &lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;add&lt;/span&gt; left, right&lt;br /&gt;    left + right&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;def&lt;/span&gt; &lt;span class="Identifier"&gt;multwo&lt;/span&gt; arg&lt;br /&gt;    arg * &lt;span class="Constant"&gt;2&lt;/span&gt;&lt;br /&gt;&lt;span class="PreProc"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-4734936324268080630?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/4734936324268080630/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=4734936324268080630" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/4734936324268080630?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/4734936324268080630?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2008/02/function-composition-in-ruby.html" title="function composition in Ruby" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D04ERnY6fip7ImA9WB9VFUU.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7404543610495284947</id><published>2007-12-02T02:48:00.000-06:00</published><updated>2007-12-02T02:58:27.816-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-02T02:58:27.816-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="olpc" /><category scheme="http://www.blogger.com/atom/ns#" term="xo" /><title>olpc: XO-1</title><content type="html">I just tried out the XO-1 system on my laptop using the qemu emulator and I am impressed. It took me about 20 minutes to get it working.&lt;br/&gt;&lt;br /&gt;You need the &lt;a href="http://olpc.download.redhat.com/olpc/streams/development/LATEST/devel_ext3/olpc-redhat-stream-development-devel_ext3.img.bz2"&gt;development image&lt;/a&gt; and qemu with kqemu.&lt;br/&gt;&lt;br /&gt;If you want you can pinch those scripts and you should be good to go.&lt;br /&gt;&lt;h6&gt;start_olpc.sh&lt;/h6&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;su -c ./su_ops.sh &amp;&amp; qemu -m 256 -kernel-kqemu -soundhw es1370 -net user -net nic,model=rtl8139 -redir tcp:2222::22 -hda olpc-redhat-stream-development-devel_ext3.img&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h6&gt;su_ops.sh&lt;/h6&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;rmmod rtc_cmos&lt;br /&gt;modprobe rtc&lt;br /&gt;&lt;br /&gt;#optimiser&lt;br /&gt;modprobe kqemu&lt;br /&gt;&lt;br /&gt;#virtual memory&lt;br /&gt;umount /dev/shm&lt;br /&gt;mount -t tmpfs -o size=272m none /dev/shm&lt;br /&gt;&lt;br /&gt;echo 1024 &gt; /proc/sys/dev/rtc/max-user-freq&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7404543610495284947?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7404543610495284947/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7404543610495284947" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7404543610495284947?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7404543610495284947?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2007/12/olpc-xo-1.html" title="olpc: XO-1" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;A0MARHk8cCp7ImA9WB9VE04.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-597563691846019466</id><published>2007-11-29T06:29:00.001-06:00</published><updated>2007-11-29T06:30:45.778-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-11-29T06:30:45.778-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rant" /><category scheme="http://www.blogger.com/atom/ns#" term="small" /><category scheme="http://www.blogger.com/atom/ns#" term="windows" /><category scheme="http://www.blogger.com/atom/ns#" term="attention" /><title>small windows</title><content type="html">There's something about a computer hooked to the internet: it's really all about small windows. We open up a program, we get a new window. Change the settings, there's a new window. Check out a website, new window. We move them around, we swap, we toggle, looking for something real, something that will push our buttons.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;We say we are multitasking but that's a joke. Every window is there to hide everything else, and if we could see everything at once, we would never be able to work. And I'm not just turning the shirt backwards, we really need partitions, we need filters, we need structures to inject some sense in the randomness, to connect the dots. It's all about small windows.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;We share, we comment, we blog, we email, we receive news feeds, we monitor stories, we screen others. It's a wire tap on the world. It's big, it's fresh, it's empowering, but how much do we really share at one time? When we email or comment on a story, 5 or 6 lines is too long: no one has time to read it. We need to minimize the input and maximize the effect. So what do we do? What do we do? Whatever the answer to that is, there is a common thread: we want to make an impact, a difference. We need feedback. We are feedback whores. So what do we do? As the window shrinks, we have less time to impress others and we get violent. We get mean. Violence is a way to control. We need it, because it will lead us to feedback.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;When that happens we need to compress our thoughts. It's all about small windows. When we communicate, it's decision time, decisions decisions decisions. And nobody likes to be irrelevant. There is only so much time but we still aim to have an impact.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;And it's getting harder and harder. More people get online everyday and the more people there are the less time we have for one single person. That's led to people saying they have a short attention span and that keeps them from achieving more. I think that's completely off. Small windows make us smarter. It's the rarity problem: by having less time to dedicate, we are forced to choose what we will spend our time on next. A short attention span is an adaptation, embrace it.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Look around, explore, surf, discover the world one window at a time. Whatever we are looking for, it's out there. Let's try something new, we can afford to crash, the next window is just around the corner.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Forget about being too small a player and quality versus quantity, nothing is binary: quality will come straight from quantity. There cannot be too many people and there cannot be too many windows. Cause we can stack them up, one on top of another, across the board. Explore, examine, use, evaluate, come back, don't come back. It's your choice. You're the driver. You're rich, you've got windows. A lot of them. I say cultivate your short attention span, there's nothing like it.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;It's a scary world if we go against the grain. We need to admit it, we need to click: it's all about small windows.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-597563691846019466?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/597563691846019466/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=597563691846019466" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/597563691846019466?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/597563691846019466?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2007/11/small-windows.html" title="small windows" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEIMRXY7fip7ImA9WB9WEU8.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7309804679061632582</id><published>2007-11-15T04:26:00.000-06:00</published><updated>2007-11-15T04:29:44.806-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-11-15T04:29:44.806-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="decorators" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>python decorators</title><content type="html">&lt;pre&gt;&lt;br /&gt;&lt;font color="#008000"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;&lt;br /&gt;DECORATORS&lt;br /&gt;PEP 318&lt;br /&gt;Introduced in Python 2.4&lt;br /&gt;&amp;quot;&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;# simple decorator&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#2040a0"&gt;def&lt;/font&gt; &lt;font color="#2040a0"&gt;log&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;f&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; new_f&lt;/font&gt;&lt;font color="2040a0"&gt;(*args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#2040a0"&gt;f&lt;/font&gt;.&lt;font color="#2040a0"&gt;__name__&lt;/font&gt;, &lt;font color="#008000"&gt;': called'&lt;/font&gt;&lt;br /&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#2040a0"&gt;args&lt;/font&gt;, &lt;font color="#2040a0"&gt;kwargs&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;f&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;args&lt;/font&gt;, &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;kwargs&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#2040a0"&gt;f&lt;/font&gt;.&lt;font color="#2040a0"&gt;__name__&lt;/font&gt;, &lt;font color="#008000"&gt;': end of call'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;strong&gt;return&lt;/strong&gt; &lt;font color="#2040a0"&gt;new_f&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;Simple&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;    @&lt;font color="#2040a0"&gt;log&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; do&lt;/font&gt;&lt;font color="2040a0"&gt;(self, *args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#008000"&gt;'...done'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;# decorator without sugar&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;NoMagic&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; do&lt;/font&gt;&lt;font color="2040a0"&gt;(self, *args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#008000"&gt;'...done'&lt;/font&gt;&lt;br /&gt;    &lt;font color="#2040a0"&gt;do&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;log&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;do&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;# decorator with arguments&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#2040a0"&gt;def&lt;/font&gt; &lt;font color="#2040a0"&gt;prefix&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;text&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; fn&lt;/font&gt;&lt;font color="2040a0"&gt;(method)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;       &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; new_fn&lt;/font&gt;&lt;font color="2040a0"&gt;(*args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;            &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#2040a0"&gt;text&lt;/font&gt;,&lt;br /&gt;            &lt;font color="#2040a0"&gt;method&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;args&lt;/font&gt;, &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;kwargs&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;        &lt;font color="#444444"&gt;#rename the method to be the same as the decorated one&lt;/font&gt;&lt;br /&gt;        &lt;font color="#444444"&gt;#new_fn.__name__ = method.__name__&lt;/font&gt;&lt;br /&gt;        &lt;strong&gt;return&lt;/strong&gt; &lt;font color="#2040a0"&gt;new_fn&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;strong&gt;return&lt;/strong&gt; &lt;font color="#2040a0"&gt;fn&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;Args&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;    @&lt;font color="#2040a0"&gt;prefix&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;'wait for it: '&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; do&lt;/font&gt;&lt;font color="2040a0"&gt;(self, *args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#008000"&gt;'...done'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;# decorator with arguments and no sugar&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;NoMagicArgs&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; do&lt;/font&gt;&lt;font color="2040a0"&gt;(self, *args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#008000"&gt;'...done'&lt;/font&gt;&lt;br /&gt;    &lt;font color="#2040a0"&gt;do&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;prefix&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;'wait for it: '&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;do&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;# chaining decorators&lt;/font&gt;&lt;br /&gt;&lt;font color="#444444"&gt;#-----------------------------------------&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;Chain&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;    @&lt;font color="#2040a0"&gt;log&lt;/font&gt;&lt;br /&gt;    @&lt;font color="#2040a0"&gt;prefix&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;I'm chaind but still: &amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;   &lt;font color="ff0000"&gt; def&lt;/font&gt;&lt;font color="ff0000"&gt; do&lt;/font&gt;&lt;font color="2040a0"&gt;(self, *args, **kwargs)&lt;/font&gt;:&lt;br /&gt;&lt;/strong&gt;        &lt;strong&gt;print&lt;/strong&gt; &lt;font color="#008000"&gt;'...done'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7309804679061632582?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7309804679061632582/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7309804679061632582" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7309804679061632582?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7309804679061632582?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2007/11/python-decorators.html" title="python decorators" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D0MBRXk6eip7ImA9WB9XEU4.&quot;"><id>tag:blogger.com,1999:blog-3313530259099615004.post-7787039453202013487</id><published>2007-11-03T18:51:00.000-05:00</published><updated>2007-11-03T19:17:34.712-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-11-03T19:17:34.712-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="lisp" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title>practical common lisp</title><content type="html">Peter Seibel's book &lt;a href="http://www.amazon.com/Practical-Common-Lisp-Peter-Seibel/dp/1590592395/ref=pd_bbs_sr_1/002-9443672-7966448?ie=UTF8&amp;s=books&amp;qid=1194134879&amp;sr=8-1"&gt;Practical Common Lisp&lt;/a&gt; is a jewel.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The book introduces the reader to Lisp in a gentle way, but also covers most of the features that make Lisp so powerful: macros, multimethods, dynamic variables...&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The book is also filled with historical notes that make for a very interesting read.&lt;br /&gt;Towards the end of the book, entire chapters are devoted to building small apps, justifying the title.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The book taught me about Lisp, but also taught me about OO (sic) and about what a modern programming language should provide. Five stars.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3313530259099615004-7787039453202013487?l=clipboarded.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://clipboarded.blogspot.com/feeds/7787039453202013487/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=3313530259099615004&amp;postID=7787039453202013487" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7787039453202013487?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3313530259099615004/posts/default/7787039453202013487?v=2" /><link rel="alternate" type="text/html" href="http://clipboarded.blogspot.com/2007/11/practical-common-lisp.html" title="practical common lisp" /><author><name>mats</name><uri>http://www.blogger.com/profile/09415156435863824246</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12753336799386138858" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
