<?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" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUEHRX06cSp7ImA9WxJUEkQ.&quot;"><id>tag:blogger.com,1999:blog-16002962</id><updated>2009-07-10T23:27:14.319-07:00</updated><title>The Web and all that Jazz</title><subtitle type="html">Picking apart and offering insight to the not-often-talked-about aspects of technology and the web.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://webjazz.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>319</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-sa/2.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><link rel="self" href="http://feeds.feedburner.com/TheWebAndAllThatJazz" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;CUEHRX0zfSp7ImA9WxJUEkQ.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-2353658004992011943</id><published>2009-07-10T23:27:00.001-07:00</published><updated>2009-07-10T23:27:14.385-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-10T23:27:14.385-07:00</app:edited><title>Building a culture of teaching and learning by Dr. Tae!</title><content type="html">
&lt;div class="posterous_bookmarklet_entry"&gt; &lt;object type="application/x-shockwave-flash" height="281" width="500" data="http://vimeo.com/moogaloop.swf?clip_id=5513063&amp;amp;server=vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=1&amp;amp;color=00ADEF"&gt;  	&lt;param name="quality" value="best" /&gt;  	&lt;param name="allowfullscreen" value="true" /&gt;  	&lt;param name="scale" value="showAll" /&gt;  	&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5513063&amp;amp;server=vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=1&amp;amp;color=00ADEF" /&gt;  &lt;/param&gt;&lt;/param&gt;&lt;/param&gt;&lt;/param&gt;&lt;/object&gt;    &lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://vimeo.com/5513063"&gt;vimeo.com&lt;/a&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/building-a-culture-of-teaching-and-learning-b"&gt;The Web and all that Jazz&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/16002962-2353658004992011943?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=X8Bt_-28VZ4:Ziyf_VAYS0k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=X8Bt_-28VZ4:Ziyf_VAYS0k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=X8Bt_-28VZ4:Ziyf_VAYS0k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=X8Bt_-28VZ4:Ziyf_VAYS0k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/X8Bt_-28VZ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/2353658004992011943/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/07/building-culture-of-teaching-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2353658004992011943?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2353658004992011943?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/X8Bt_-28VZ4/building-culture-of-teaching-and.html" title="Building a culture of teaching and learning by Dr. Tae!" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/07/building-culture-of-teaching-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHSXY9cCp7ImA9WxJUEEg.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-7345305289894800941</id><published>2009-07-08T05:27:00.001-07:00</published><updated>2009-07-08T05:30:38.868-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-08T05:30:38.868-07:00</app:edited><title>Regular Expression Matching and Postfix notation</title><content type="html">&lt;div class="posterous_bookmarklet_entry"&gt; &lt;blockquote class="posterous_long_quote"&gt;As the compiler scans the postfix expression, it maintains  a stack of computed NFA fragments.  Literals push new NFA fragments onto the stack, while  operators pop fragments off the stack and then  push a new fragment.  For example,   after compiling the  &lt;code&gt;abb&lt;/code&gt; in &lt;code&gt;abb.+.a.&lt;/code&gt;,  the stack contains NFA fragments for  &lt;code&gt;a&lt;/code&gt;,  &lt;code&gt;b&lt;/code&gt;,  and  &lt;code&gt;b&lt;/code&gt;.  The compilation of the  &lt;code&gt;.&lt;/code&gt;  that follows pops the two  &lt;code&gt;b&lt;/code&gt;  NFA fragment from the stack and pushes an NFA fragment for the  concatenation  &lt;code&gt;bb.&lt;/code&gt;.  Each NFA fragment is defined by its start state and its  outgoing arrows:  &lt;/blockquote&gt;&lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://swtch.com/%7Ersc/regexp/regexp1.html"&gt;swtch.com&lt;/a&gt;&lt;/div&gt;    The snippet doesn't make much sense unless you read the article, but this part, I thought was rather neat.  Usually, when I wrote my crappy, one-off parsers, I just used regexes to pull out the tokens that I needed.  Never thought too much about how it was implemented.  But what's detailed here makes sense.  Regexes are just state machines where you track whether the string you're matching against lets you traverse all the way through the state machine.  And to do that, it pushes each fragment of the regex onto a stack until it reaches an operator, which then pops it off and works on it.  While I've usually left post-fix notation is ass-backwards from a user perspective, I can see the elegance of the implementation.  I suspect Forth and Factor are similar in this regard. &lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/regular-expression-matching-can-be-simple-and"&gt;The Web and all that Jazz&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/16002962-7345305289894800941?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=9RsQY3Kp7KY:KVcqG0Qs7Dc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=9RsQY3Kp7KY:KVcqG0Qs7Dc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=9RsQY3Kp7KY:KVcqG0Qs7Dc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=9RsQY3Kp7KY:KVcqG0Qs7Dc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/9RsQY3Kp7KY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/7345305289894800941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/07/regular-expression-matching-can-be.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/7345305289894800941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/7345305289894800941?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/9RsQY3Kp7KY/regular-expression-matching-can-be.html" title="Regular Expression Matching and Postfix notation" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/07/regular-expression-matching-can-be.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQNQ3Y9fyp7ImA9WxJVEkU.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-833154867578827954</id><published>2009-06-29T08:13:00.001-07:00</published><updated>2009-06-29T08:13:12.867-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-29T08:13:12.867-07:00</app:edited><title>Nerd time issue 16</title><content type="html">
I use to work at a research lab and while it was cutting edge in some ways, it seemed unaware of things going on in software and web.  I&amp;#39;ve since left the research lab, and Nerd Time started as a mailing list to tell my friends still at the lab about things that they might be able to use in their own projects.  &lt;br /&gt;  &lt;div&gt;                  &lt;br /&gt;------------&lt;br /&gt;&lt;br /&gt;Hey all,&lt;br /&gt;&lt;br /&gt;It&amp;#39;s that time again.  I never get feedback about whether you guys read this or not.  But apparently, some of you do, since my last trip back to MD.  This is just a collection of things I found interesting since the last nerd time.  Obviously, there are other trends I&amp;#39;m missing.&lt;br /&gt;    &lt;br /&gt;If you want off, just lemme know.  &lt;br /&gt;&lt;br /&gt;This is rather long since it&amp;#39;s been a good 6 months since the last nerd time.  Work has kept me busy, and I don&amp;#39;t read as much as I use to.  Since there&amp;#39;s no theme, but lots of trends, they&amp;#39;re in no particular order this time.  Skim through it and see if there&amp;#39;s anything that catches your eye.  &lt;br /&gt;    &lt;br /&gt;If you have questions about stuff, feel free to ask me (don&amp;#39;t reply all!)&lt;br /&gt;                &lt;br /&gt;First, some stuff I did on the side:&lt;br /&gt;&lt;b&gt;Senate Majroity vs National Debt&lt;/b&gt;&lt;br /&gt;I was talking with Ian about graphing public data, and this was what he wanted to know.  This sort of thing should be so much easier.  If you find the process of getting this data to graph, lemme know.  I imagine it goes in line with a lot of the net-centric buzzwording that does on in DoD projects.&lt;br /&gt;                    &lt;a href="http://iamwil.posterous.com/senate-majority-vs-national-debt-getting-at-p" target="_blank"&gt;http://iamwil.posterous.com/senate-majority-vs-national-debt-getting-at-p&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Frock, a chicken flocking simulator&lt;/b&gt;&lt;br /&gt;                  I wanted to get to know the Lua programming language, so I chose this as a project.  I&amp;#39;m getting it to support more chickens still.&lt;br /&gt;  &lt;a href="http://webjazz.blogspot.com/2009/02/introducing-frock-flocking-chicken.html" target="_blank"&gt;http://webjazz.blogspot.com/2009/02/introducing-frock-flocking-chicken.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And now, the other stuff.&lt;br /&gt;&lt;br /&gt;                  &lt;b&gt;Twitter&lt;/b&gt;&lt;br /&gt;  So I&amp;#39;m sure most of you by now have heard of twitter.  Considering that Oprah did a show on it, it&amp;#39;s crossed over to mainstream.  A lot of you might not think of it as anything to pay attention to.  However, it&amp;#39;s one of those things where its value depends on whom you follow.  Beyond the hype, it&amp;#39;s mainly a messaging multicast system that has a dead-simple API, so that other people can build things on top of it.  People have made things that twitter, such as plants that tell you when you need to water it, when bridges go up and down, when a meteor almost hits the earth, etc.  &lt;br /&gt;                    &lt;a href="http://www.twitter.com" target="_blank"&gt;http://www.twitter.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twollars.com/" target="_blank"&gt;http://twollars.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.botanicalls.com/kits/" target="_blank"&gt;http://www.botanicalls.com/kits/&lt;/a&gt;&lt;br /&gt;    &lt;a href="http://twitter.com/riverthames" target="_blank"&gt;http://twitter.com/riverthames&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wolfram Alpha and Google Squared and YQL&lt;/b&gt;&lt;br /&gt;  Wolfram Alpha and Google Squared had both been announced in the last  month or so.  Both are looking towards being able to query large  amounts of structured data.  However, wolfram curates this data with  experts, and google squared attempts to make structured data from  indexing tables of data on the web.  In addition, Yahoo released YQL,  which is a query you can use to scrap the web and treat it as just  another database.&lt;br /&gt;&lt;a href="http://www.wolframalpha.com/" target="_blank"&gt;http://www.wolframalpha.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/squared/" target="_blank"&gt;http://www.google.com/squared/&lt;/a&gt;&lt;br /&gt;        &lt;a href="http://tables.googlelabs.com/Home?pli=1" target="_blank"&gt;http://tables.googlelabs.com/Home?pli=1&lt;/a&gt;&lt;br /&gt;    &lt;a href="http://developer.yahoo.com/yql/" target="_blank"&gt;http://developer.yahoo.com/yql/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Real-time search&lt;/b&gt;&lt;br /&gt;  Real-time search seems to be the wrestling ground for the next  generation of search right now.  There are a number of competitors in  this field, including giants and startups.  It&amp;#39;s evident with the death  of Michael Jackson that news doesn&amp;#39;t just travel through the old  channels anymore.&lt;br /&gt;  &lt;a href="http://venturebeat.com/2009/06/20/who-rules-real-time-search-a-look-at-9-contenders/" target="_blank"&gt;http://venturebeat.com/2009/06/20/who-rules-real-time-search-a-look-at-9-contenders/&lt;/a&gt;&lt;br /&gt;        &lt;a href="http://search.twitter.com/" target="_blank"&gt;http://search.twitter.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.scoopler.com/" target="_blank"&gt;http://www.scoopler.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Google Wave&lt;/b&gt;&lt;br /&gt;If you haven&amp;#39;t heard, google released a new communication tool called google wave.  It&amp;#39;s what email would be like if it was reinvented today.  It&amp;#39;s basically combining different aspects of our communication tools and merging them all together.  It&amp;#39;s best if you watch the video and play with the demo.  If you want to play with wave yourself, you don&amp;#39;t have to wait for an invite, but can sign up with a wave server that someone set up themselves.  I recommend watching the video, as it breaks your presumptions of what&amp;#39;s possible with HTML5 and the web.&lt;br /&gt;    &lt;a href="http://wave.google.com/" target="_blank"&gt;http://wave.google.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://wavety.com/pygo-wave-server/" target="_blank"&gt;http://wavety.com/pygo-wave-server/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git and github&lt;/b&gt;&lt;br /&gt;To me, this is really old news, but just in case you&amp;#39;re still using SVN, you should checkout Git instead for your source control.  It&amp;#39;s ass-kicking good, though it has a slight learning curve.  I won&amp;#39;t say too much more about it, but you should really look into it.  It&amp;#39;ll expand your mind.&lt;br /&gt;    &lt;a href="http://git-scm.com/" target="_blank"&gt;http://git-scm.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://github.com/" target="_blank"&gt;http://github.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Key-value stores&lt;/b&gt;&lt;br /&gt;Lately, there&amp;#39;s been a flurry of attention on key-value stores.  I&amp;#39;ve mentioned one of them before, CouchDb.  There are a bunch of others.  Tokyo Cabinet (link #2) is used at &lt;a href="http://Mixx.jp.co" target="_blank"&gt;Mixx.jp.co&lt;/a&gt;, a social network in Japan.  Cassandra (link #3) is used at facebook.  Amazon has SimpleDB and Dynamo.  I&amp;#39;ve only played with tokyo cabinet and couchdb, so I can&amp;#39;t really do a compare and contrast between them all.  But to me, TC, couchdb, and redis seem to be the most interesting.  This marks a shift away from relational dbs as the default data store.  Not that they&amp;#39;ll replace relational db, but we&amp;#39;re finding there are a different class of constraints for the web not necessarily taken care of by relational dbs.  In addition, they have properties not avail to relational dbs, such as being schema-less, an http server built in, replication, distributed, etc.&lt;br /&gt;                    &lt;a href="http://couchdb.apache.org/" target="_blank"&gt;http://couchdb.apache.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tokyocabinet.sourceforge.net/index.html" target="_blank"&gt;http://tokyocabinet.sourceforge.net/index.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://cwiki.apache.org/confluence/display/CSDR/Index" target="_blank"&gt;http://incubator.apache.org/cassandra/&lt;/a&gt;&lt;br /&gt;                    &lt;a href="http://code.google.com/p/redis/" target="_blank"&gt;http://code.google.com/p/redis/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://memcachedb.org/" target="_blank"&gt;http://memcachedb.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://github.com/cliffmoon/dynomite/tree/master" target="_blank"&gt;http://github.com/cliffmoon/dynomite/tree/master&lt;/a&gt;&lt;br /&gt;                    &lt;a href="http://opensource.plurk.com/LightCloud/" target="_blank"&gt;http://opensource.plurk.com/LightCloud/&lt;/a&gt;&lt;br /&gt;    &lt;a href="http://www.oracle.com/technology/products/berkeley-db/index.html" target="_blank"&gt;http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.oracle.com/technology/products/berkeley-db/index.html" target="_blank"&gt;http://www.oracle.com/technology/products/berkeley-db/index.html&lt;/a&gt;&lt;br /&gt;                    &lt;a href="http://code.google.com/p/thrudb/" target="_blank"&gt;http://code.google.com/p/thrudb/&lt;/a&gt;&lt;br /&gt;  &lt;a href="http://code.google.com/p/scalaris/" target="_blank"&gt;http://code.google.com/p/scalaris/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The internet of things&lt;/b&gt;&lt;br /&gt;It&amp;#39;s something further out, but these first two talks from TED got me thinking about where the web was heading.  I don&amp;#39;t think that the semantic web, as we imagine it will come to fruition.  However, having the things we own talk to each other over the internet is not unfathomable.  They&amp;#39;ll be able to negotiate with each other to perform a task, or they&amp;#39;ll be able to keep a history of what they&amp;#39;re doing or how you&amp;#39;re interacting with them.  &lt;br /&gt;                      &lt;a href="http://www.ted.com/index.php/talks/kevin_kelly_on_the_next_5_000_days_of_the_web.html" target="_blank"&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt; &lt;param name="flashvars" value="vu=http://video.ted.com/talks/embed/KevinKelly_2007P-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/KevinKelly-2007P.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=319" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" flashvars="vu=http://video.ted.com/talks/embed/KevinKelly_2007P-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/KevinKelly-2007P.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=319"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ted.com/index.php/talks/tim_berners_lee_on_the_next_web.html" target="_blank"&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt; &lt;param name="flashvars" value="vu=http://video.ted.com/talks/embed/TimBerners-Lee_2009-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TimBerners-Lee-2009.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=484" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" flashvars="vu=http://video.ted.com/talks/embed/TimBerners-Lee_2009-embed_high.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TimBerners-Lee-2009.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=484"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/a&gt;&lt;br /&gt;                        &lt;a href="http://siftables.com/" target="_blank"&gt;http://siftables.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.readwriteweb.com/archives/5_companies_building_the_internet_of_things.php" target="_blank"&gt;http://www.readwriteweb.com/archives/5_companies_building_the_internet_of_things.php&lt;/a&gt;&lt;br /&gt;                    &lt;a href="http://www.makerbot.com" target="_blank"&gt;www.makerbot.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://siftables.com/" target="_blank"&gt;http://siftables.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cheap hardware boards&lt;/b&gt;&lt;br /&gt;Hardware is already cheap, but building hardware yourself has still been somewhat of a pain.  I remember having to use Rabbit boards before.  There are better ones now.  I&amp;#39;ve mentioned arduino before.  Beagle board is a full board that you can run Ubuntu on.  Teensy is a small USB microcontroller.&lt;br /&gt;                    &lt;a href="http://www.arduino.cc/" target="_blank"&gt;http://www.arduino.cc/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://beagleboard.org/" target="_blank"&gt;http://beagleboard.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.pjrc.com/teensy/?not_a_duplicate" target="_blank"&gt;http://www.pjrc.com/teensy/?not_a_duplicate&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;Quake online&lt;/b&gt;&lt;br /&gt;Gaming often is looked on as child&amp;#39;s play, when in fact, it&amp;#39;s some of the hardest programming around, and often drives innovation and progress in graphical techniques, AI, and hardware.  Carmack, the guy that wrote Quake, wants to put Quake on the browser.  For the longest time, people derided the web, saying it&amp;#39;ll never match the performance of desktop apps, and never give the same user experience.  If Carmack can run quake on a native browser, then I believe desktop will lose.  If he&amp;#39;s delivering quake as a video stream, then that&amp;#39;s another matter altogether.&lt;br /&gt;    &lt;a href="http://www.gamasutra.com/view/feature/3946/building_quake_live_carmack_speaks.php?print=1" target="_blank"&gt;http://www.gamasutra.com/view/feature/3946/building_quake_live_carmack_speaks.php?print=1&lt;/a&gt;&lt;br /&gt;                    &lt;br /&gt;&lt;b&gt;Reverse HTTP&lt;/b&gt;&lt;br /&gt;HTTP is by design a pull model, where the client requests resources from a server.  If you wanted to push data to a browser client, you had to rely on a bit of javascript finangling called Comet (cousin to AJAX), where you open an http connection to the client, and leave it open until you want to push stuff to the client.  This certainly puts a load on servers because you have to keep connections open.  Alternatively, you can have the client keep polling the server.  That sucks too.  Reverse HTTP doesn&amp;#39;t need to keep the connection open.  It basically takes advantage of the upgrade field in the HTTP header normally used to find a more appropriate protocol, and instead to turn the connection around from the server to the client.  It&amp;#39;s still experimental, but it makes a lot more things simple instead of messing with javascript on clients to push data to browsers.&lt;br /&gt;    &lt;a href="http://www.reversehttp.net/" target="_blank"&gt;http://www.reversehttp.net/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.secondlife.com/wiki/Reverse_HTTP" target="_blank"&gt;http://wiki.secondlife.com/wiki/Reverse_HTTP&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ietf.org/internet-drafts/draft-lentczner-rhttp-00.txt" target="_blank"&gt;http://www.ietf.org/internet-drafts/draft-lentczner-rhttp-00.txt&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;Whiteboarding in real time&lt;/b&gt;&lt;br /&gt;Many collaboration tools have come out.  We&amp;#39;ve discovered that the web is essentially a communications medium.  Anyway, this set of collaboration tools lets you whiteboard, compose text, and revise docs in real time as other people are editing them.  The last link shows you a re-play of paul graham writing one of his essays.  This allows people to see how they edit their text over time, and shows others how other people think as they write.  It&amp;#39;d be useful as an educational tool.&lt;br /&gt;    &lt;a href="http://www.twiddla.com/" target="_blank"&gt;http://www.twiddla.com/&lt;/a&gt;&lt;br /&gt;                &lt;a href="http://www.etherpad.com/" target="_blank"&gt;http://www.etherpad.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.wikirage.com/" target="_blank"&gt;http://www.wikirage.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.revizr.com/" target="_blank"&gt;http://www.revizr.com/&lt;/a&gt;&lt;br /&gt;            &lt;a href="http://etherpad.com/ep/pad/slider/13sentences" target="_blank"&gt;http://etherpad.com/ep/pad/slider/13sentences&lt;/a&gt;&lt;br /&gt;  &lt;b&gt;&lt;br /&gt;Facebook&amp;#39;s walled garden&lt;/b&gt;&lt;br /&gt;Facebook is the AOL of today.  It&amp;#39;s basically a walled garden of data, where users live.  There&amp;#39;s a bunch of effort to break them open.  Facebook also wants to open itself out as a fast follower to twitter.  I won&amp;#39;t say much more here, but there&amp;#39;s an ongoing battle about where data gets to go on this front.&lt;br /&gt;    &lt;a href="http://www.wired.com/techbiz/it/magazine/17-07/ff_facebookwall?currentPage=all" target="_blank"&gt;http://www.wired.com/techbiz/it/magazine/17-07/ff_facebookwall?currentPage=all&lt;/a&gt;&lt;br /&gt;        &lt;a href="http://googledataapis.blogspot.com/2008/03/3-2-1-contact-api-has-landed.html" target="_blank"&gt;http://googledataapis.blogspot.com/2008/03/3-2-1-contact-api-has-landed.html&lt;/a&gt;&lt;br /&gt;  &lt;a href="http://www.complang.org/dsnp/" target="_blank"&gt;http://www.complang.org/dsnp/&lt;/a&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Data.gov and the sunlight foundation&lt;/b&gt;&lt;br /&gt;Since Obama took office, there&amp;#39;s been a big push and initiative to open up the government to its citizens in the name of transparency.  One of the things they&amp;#39;re doing is &lt;a href="http://data.gov" target="_blank"&gt;data.gov&lt;/a&gt; and opening raw public data up to developers or anyone that wants to use it.  The sunlight foundation is doing the same for legistator and voting data.  I expect that we&amp;#39;ll have more apps that will be able to take advantage of this data in the near future, not just to help the people govern their govenment, but also to lead more informed lives.&lt;br /&gt;    &lt;a href="http://services.sunlightlabs.com/api/" target="_blank"&gt;http://services.sunlightlabs.com/api/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.data.gov/catalog/raw/category/0/agency/0/filter//type//sort//page/1/count/10" target="_blank"&gt;http://www.data.gov/catalog/raw/category/0/agency/0/filter//type//sort//page/1/count/10&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;DNA engineering&lt;/b&gt;&lt;br /&gt;A front that I don&amp;#39;t know too much about, but is probably a bigger revolution than the information age and the internet are things that have to do with genetic and bio engineering.  23andme lets you submit cell samples of yourself, and they&amp;#39;ll do genetic testing to tell you if you have genetic diseases, among other things.  You can now submit gene sequences and get them built for a modest amount of money--not super expensive, but still out of reach for hobbists)  As the cost goes down, you&amp;#39;ll soon see designer pets and bacteria.  The last post is about a guy that theoretically hacks a more potent variant of swine flu.&lt;br /&gt;    &lt;a href="http://23andme.com" target="_blank"&gt;http://23andme.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mrgene.com/desktopdefault.aspx/tabid-2/" target="_blank"&gt;http://mrgene.com/desktopdefault.aspx/tabid-2/&lt;/a&gt;&lt;br /&gt;          &lt;a href="http://www.bunniestudios.com/blog/?p=353" target="_blank"&gt;http://www.bunniestudios.com/blog/?p=353&lt;/a&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;GWT, sproutcore, and Cappucino&lt;/b&gt;&lt;br /&gt;Javascript is the most widely used language in the world.  And while it has its merits as a functional language, people are trying to develop frameworks that compile to javascript.  Javascript is not bad when you&amp;#39;re using jQuery.  Scriptaculous 2 just got released also.  &lt;br /&gt;    &lt;a href="http://code.google.com/webtoolkit/" target="_blank"&gt;http://code.google.com/webtoolkit/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.sproutcore.com/" target="_blank"&gt;http://www.sproutcore.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://cappuccino.org/" target="_blank"&gt;http://cappuccino.org/&lt;/a&gt;&lt;br /&gt;    &lt;a href="http://jquery.com" target="_blank"&gt;http://jquery.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://scripty2.com/" target="_blank"&gt;http://scripty2.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Chat on couchdb, standalone web apps, and taking your data with you&lt;/b&gt;&lt;br /&gt;  This was curious.  Couchdb is a key-value document orientated database with an http server as its frontend.  They were able to demonstrate that you can fit an entire web app just in the database.  Data is code, and code is data.  Not only that, you can use the database&amp;#39;s replication to port your data and sync it where-ever you go.  It&amp;#39;s an interesting head turn, even if it&amp;#39;s just a demo.&lt;br /&gt;    &lt;a href="http://damienkatz.net/2009/05/realtime_chat_on_couchdb.html" target="_blank"&gt;http://damienkatz.net/2009/05/realtime_chat_on_couchdb.html&lt;/a&gt;&lt;br /&gt;        &lt;a href="http://www.jasondavies.com/blog/2009/05/08/couchdb-on-wheels/" target="_blank"&gt;http://www.jasondavies.com/blog/2009/05/08/couchdb-on-wheels/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://devlindaley.com/2009/2/14/couchdb-bloom-filters" target="_blank"&gt;http://devlindaley.com/2009/2/14/couchdb-bloom-filters&lt;/a&gt;&lt;br /&gt;              &lt;br /&gt;&lt;b&gt;Mozilla Ubiquity again, but this time hooks into webapps&lt;/b&gt;&lt;br /&gt;I&amp;#39;ve mentioned ubiquity before, which is like a commandline interface for your browser.  I use it myself, but only in limited amounts.  What&amp;#39;s interesting about the direction is that they leverage web services to complete tasks it can&amp;#39;t complete for itself.  I think that high level languages will eventually adopt the idea of being able to easily hook into web services as a natural part of the language, without extra libraries.&lt;br /&gt;    &lt;a href="http://www.readwriteweb.com/archives/firefoxs_ubiqity_starts_thinking_for_itself.php" target="_blank"&gt;http://www.readwriteweb.com/archives/firefoxs_ubiqity_starts_thinking_for_itself.php&lt;/a&gt;&lt;br /&gt;  &lt;br /&gt;&lt;b&gt;Mozilla Jetpack lets you write Firefox addons with the web&lt;/b&gt;&lt;br /&gt;Traditionally, web developers have stayed out of the realm of desktop developers.  This is one of the many indications I have that a lot of programming--especially those with user interfaces or a social aspect--will move towards web programming constructs.  &lt;a href="https://jetpack.mozillalabs.com/" target="_blank"&gt;https://jetpack.mozillalabs.com/&lt;/a&gt;&lt;br /&gt;    &lt;b&gt;&lt;br /&gt;Clojure, Scala, Haskell, Erlang&lt;/b&gt;&lt;br /&gt;    I&amp;#39;m not going to say too much about these programming languages, since I&amp;#39;ve mentioned them before, but just as a reminder, there&amp;#39;s more than Java out there.  These four to me, represent the edge of programming languages that have potential in the future.  With the advent of multicores, it&amp;#39;s likely that functional programming will lead the way in giving us adequate programming constructs to deal with multicores.  If you&amp;#39;re a programmer, it&amp;#39;d probably serve you well to learn at least one of these in the coming 4 years.&lt;br /&gt;    &lt;a href="http://clojure.org/" target="_blank"&gt;http://clojure.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.scala-lang.org/" target="_blank"&gt;http://www.scala-lang.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.haskell.org/" target="_blank"&gt;http://www.haskell.org/&lt;/a&gt;&lt;br /&gt;  &lt;a href="http://erlang.org/" target="_blank"&gt;http://erlang.org/&lt;/a&gt;&lt;br /&gt;  &lt;br /&gt;&lt;b&gt;ParrotVM and mod_parrot&lt;/b&gt;&lt;br /&gt;Admittedly, I don&amp;#39;t know much about Parrot.  But the claims it makes is big.  With the rise and popularity of dynamic programming languages like Python and Ruby, we&amp;#39;re struggling for a fast virtual machine.  And to have to build a new virtual machine every time we have a new language is a pain.  ParrotVM is suppose to take care of easing that pain.  If that&amp;#39;s the case, it might be easier to make languages catered to our problem domain.&lt;br /&gt;      &lt;a href="http://www.linux-mag.com/cache/7373/1.html" target="_blank"&gt;http://www.linux-mag.com/cache/7373/1.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.smashing.org/talks/mod_parrot.ppt" target="_blank"&gt;http://www.smashing.org/talks/mod_parrot.ppt&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;Augmented reality and zombies&lt;/b&gt;&lt;br /&gt;We&amp;#39;ve moved closer to having augmented reality.  This is a far cry from the geeky headcam helmets and laptop backpacks that dorky MIT profs wore a decade ago.  It still relies on a 2D barcode, and has limited uses, but now with the iPhone3GS out (it has a compass), we might see more augmented reality apps (as well as on android phones)&lt;br /&gt;      &lt;a href="http://singularityhub.com/2009/06/19/augmented-reality-is-full-of-zombies/" target="_blank"&gt;http://singularityhub.com/2009/06/19/augmented-reality-is-full-of-zombies/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.thinkartificial.org/machine-interfaces/augmented-reality-iphone/" target="_blank"&gt;http://www.thinkartificial.org/machine-interfaces/augmented-reality-iphone/&lt;/a&gt;&lt;br /&gt;              &lt;a href="http://news.cnet.com/8301-17938_105-10266380-1.html" target="_blank"&gt;http://news.cnet.com/8301-17938_105-10266380-1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sysadmin tips&lt;/b&gt;&lt;br /&gt;Here are some good sysadmin tips.  I&amp;#39;d like to think I know my way around linux, when in fact, I&amp;#39;ve just started.&lt;br /&gt;    &lt;a href="http://www.ibm.com/developerworks/linux/library/l-10sysadtips/" target="_blank"&gt;http://www.ibm.com/developerworks/linux/library/l-10sysadtips/&lt;/a&gt;&lt;br /&gt;          &lt;a href="http://blog.transmit.net/2008/10/my-best-unix-tricks.html" target="_blank"&gt;http://blog.transmit.net/2008/10/my-best-unix-tricks.html&lt;/a&gt;&lt;br /&gt;                    &lt;br /&gt;&lt;b&gt;Probabilistic chips&lt;/b&gt;&lt;br /&gt;I don&amp;#39;t know anymore than what&amp;#39;s written in the article.  So read about it.&lt;br /&gt;  &lt;a href="http://www.chron.com/disp/story.mpl/metropolitan/6252697.html" target="_blank"&gt;http://www.chron.com/disp/story.mpl/metropolitan/6252697.html&lt;/a&gt;&lt;br /&gt;  &lt;br /&gt;&lt;b&gt;Google Moderator&lt;/b&gt;&lt;br /&gt;  Voting on websites is old hat since about 2005 with the advent of  Digg.com and &lt;a href="http://reddit.com" target="_blank"&gt;reddit.com&lt;/a&gt;.  I found it curious that google has a  moderator app, to help facilitate the asking of questions.  If you want  your own, you can create a white label voting site at slinkset.&lt;br /&gt;&lt;a href="http://moderator.appspot.com/" target="_blank"&gt;http://moderator.appspot.com/&lt;/a&gt;&lt;br /&gt;  &lt;a href="http://www.slinkset.com" target="_blank"&gt;http://www.slinkset.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The rest of these are related to software, but not about code.  If you can only watch/read one, I&amp;#39;d recommend the poisonous people one.  That applies to more than open source projects.  In it, SVN core devs talk about how someone came in and told them they were all wrong.  I have a feeling that was Linus Torvalds, as he rails on the SVN guys in his talk.&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;The Business and Politics of Software&lt;/b&gt;&lt;br /&gt;&lt;a href="http://blog.cusec.net/2009/01/05/zed-shaw-the-acl-is-dead-cusec-2008/" target="_blank"&gt;http://blog.cusec.net/2009/01/05/zed-shaw-the-acl-is-dead-cusec-2008/&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;          &lt;b&gt;Pivoting, or knowing when to stop.&lt;/b&gt;&lt;br /&gt;&lt;a href="http://startuplessonslearned.blogspot.com/2009/06/pivot-dont-jump-to-new-vision.html" target="_blank"&gt;http://startuplessonslearned.blogspot.com/2009/06/pivot-dont-jump-to-new-vision.html&lt;/a&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;How open source projects survive poisonous people.&lt;/b&gt;&lt;br /&gt;              &lt;object height="417" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ZSFDm3UYkeE&amp;rel=1&amp;ap=%2526fmt%3D18" /&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent" /&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ZSFDm3UYkeE&amp;rel=1&amp;ap=%2526fmt%3D18" type="application/x-shockwave-flash" height="417" wmode="transparent" width="500"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Linus Torvalds on Git&lt;/b&gt;&lt;br /&gt;&lt;object height="417" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/4XpnKHJAok8&amp;rel=1&amp;ap=%2526fmt%3D18" /&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent" /&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/4XpnKHJAok8&amp;rel=1&amp;ap=%2526fmt%3D18" type="application/x-shockwave-flash" height="417" wmode="transparent" width="500"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;Build or buy?&lt;/b&gt;&lt;br /&gt;&lt;a href="http://sitecanary.com/blog/5" target="_blank"&gt;http://sitecanary.com/blog/5&lt;/a&gt;&lt;br /&gt;      &lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/nerd-time-issue-16"&gt;The Web and all that Jazz&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/16002962-833154867578827954?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ySJuNkj8QG4:nWPMU2fRFsI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ySJuNkj8QG4:nWPMU2fRFsI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ySJuNkj8QG4:nWPMU2fRFsI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=ySJuNkj8QG4:nWPMU2fRFsI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/ySJuNkj8QG4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/833154867578827954/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/06/nerd-time-issue-16.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/833154867578827954?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/833154867578827954?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/ySJuNkj8QG4/nerd-time-issue-16.html" title="Nerd time issue 16" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/06/nerd-time-issue-16.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MBQng4fip7ImA9WxJVEEs.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-5239626308017830244</id><published>2009-06-26T17:10:00.001-07:00</published><updated>2009-06-26T17:10:53.636-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-26T17:10:53.636-07:00</app:edited><title>Netflix Prize barrier of 10% has been broken</title><content type="html">
&lt;div&gt; &lt;a href="http://www.netflixprize.com/leaderboard?att"&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iamwil/zuklCuyrCDDhImmICkDFFeinvcAjtgpxhFIqFameasIlugucwbEcbDijfhfk/media_httpwwwnetflixprizecomassetsheaderprizejpg_swbCtqmbGJDmDwy.jpg.scaled1000.jpg'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iamwil/zuklCuyrCDDhImmICkDFFeinvcAjtgpxhFIqFameasIlugucwbEcbDijfhfk/media_httpwwwnetflixprizecomassetsheaderprizejpg_swbCtqmbGJDmDwy.jpg.scaled500.jpg" width="500" height="52"/&gt;&lt;/a&gt; &lt;/a&gt;&lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://www.netflixprize.com/leaderboard?att"&gt;netflixprize.com&lt;/a&gt;&lt;/div&gt;  &lt;p&gt;  Well, looks like they did it.  A bunch of teams came together and put their solutions together to do 10%.  Congrats. &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/netflix-prize-barrier-of-10-has-been-broken"&gt;The Web and all that Jazz&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/16002962-5239626308017830244?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=v3Z6fNVZtrk:ooC9H7az0KA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=v3Z6fNVZtrk:ooC9H7az0KA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=v3Z6fNVZtrk:ooC9H7az0KA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=v3Z6fNVZtrk:ooC9H7az0KA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/v3Z6fNVZtrk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/5239626308017830244/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/06/netflix-prize-barrier-of-10-has-been.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/5239626308017830244?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/5239626308017830244?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/v3Z6fNVZtrk/netflix-prize-barrier-of-10-has-been.html" title="Netflix Prize barrier of 10% has been broken" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/06/netflix-prize-barrier-of-10-has-been.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UBQ3kzfSp7ImA9WxJWGEk.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-3178475611064379183</id><published>2009-06-24T06:14:00.001-07:00</published><updated>2009-06-24T06:14:12.785-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-24T06:14:12.785-07:00</app:edited><title>Army Exoskeleton Suit Gives Man Superhuman Strength | Singularity Hub</title><content type="html">
&lt;div&gt; &lt;object type="application/x-shockwave-flash" height="344" width="425" data="http://www.youtube.com/v/sJ4J69EEpu4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.youtube.com/v/sJ4J69EEpu4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;/param&gt;&lt;/param&gt;&lt;/param&gt;&lt;/param&gt;&lt;/object&gt;    &lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://singularityhub.com/2009/06/11/army-exoskeleton-suit-gives-man-superhuman-strength/"&gt;singularityhub.com&lt;/a&gt;&lt;/div&gt; &lt;p&gt;"it is impressive enough to hear somebody say that they gave up on lifting a 200-pound weight after 500 repetitions not because they were tired but because they were bored." &lt;/p&gt;&lt;p&gt;I've always wanted one of these.  I wonder if having mechs is too far off.  Perhaps there's no tactical advantage to having a large humanoid robot.   &lt;/p&gt;&lt;p&gt;In any case, this makes me wonder what other things DARPA funds.&lt;/p&gt;&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/army-exoskeleton-suit-gives-man-superhuman-st"&gt;The Web and all that Jazz&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/16002962-3178475611064379183?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=nLfuBAF2T3A:IH_xvAcg2zw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=nLfuBAF2T3A:IH_xvAcg2zw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=nLfuBAF2T3A:IH_xvAcg2zw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=nLfuBAF2T3A:IH_xvAcg2zw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/nLfuBAF2T3A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/3178475611064379183/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/06/army-exoskeleton-suit-gives-man.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3178475611064379183?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3178475611064379183?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/nLfuBAF2T3A/army-exoskeleton-suit-gives-man.html" title="Army Exoskeleton Suit Gives Man Superhuman Strength | Singularity Hub" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/06/army-exoskeleton-suit-gives-man.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAGRX8yfSp7ImA9WxJQF0w.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-8287678198384030275</id><published>2009-05-30T10:43:00.000-07:00</published><updated>2009-05-30T13:18:44.195-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-30T13:18:44.195-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="couchdb" /><title>Returning the keys of all documents in CouchDb</title><content type="html">There's a bit of a learning curve when trying to use CouchDb's mapreduce.  One of the harder parts is to write the reduce function, which can have two separate cases:  called from the map functions, and called again from reduce functions.&lt;br /&gt;&lt;br /&gt;When you emit data from map, the examples show you emitting the document, but you can emit any data structure you care to dream up in the key and value portion of the emit.  I needed a mapreduce view that returned all the keys that were present in the all the documents.  So if I had documents in the db in the form:&lt;br /&gt;&lt;pre class="javascript"&gt;{"year": 2008, "birth_rate": 20.0 }&lt;br /&gt;{"year": 2009, "birth_rate": 21.0 }&lt;br /&gt;{"year": 2008, "death_rate": 20.0 }&lt;br /&gt;{"year": 2009, "death_rate": 20.0 }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I wanted something that returned: ["year", "birth_rate", "death_rate"]&lt;br /&gt;&lt;br /&gt;Here's one way to do it:&lt;br /&gt;&lt;script src="http://gist.github.com/120523.js"&gt;&lt;/script&gt;&lt;br /&gt;Tip!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-8287678198384030275?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=bK963VnGBI0:k1u8PqZo_vQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=bK963VnGBI0:k1u8PqZo_vQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=bK963VnGBI0:k1u8PqZo_vQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=bK963VnGBI0:k1u8PqZo_vQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/bK963VnGBI0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/8287678198384030275/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/05/returning-keys-of-all-documents-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/8287678198384030275?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/8287678198384030275?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/bK963VnGBI0/returning-keys-of-all-documents-in.html" title="Returning the keys of all documents in CouchDb" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/05/returning-keys-of-all-documents-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UARXk7eSp7ImA9WxJQFE4.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-3156527664310854235</id><published>2009-05-27T08:43:00.001-07:00</published><updated>2009-05-27T08:47:24.701-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-27T08:47:24.701-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><title>How to add helpers, controllers, models, and views of your plugin into the Rails loadpath</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;p&gt;Sometimes, when you're writing a plugin, you end up writing models,&lt;br /&gt; helpers, and controllers that the main app can use. &amp;nbsp;However, you&lt;br /&gt; don't want to copy it into the main app all the time. &amp;nbsp;You'd like to&lt;br /&gt; keep things separate between the plugin, but you'd like to be able to&lt;br /&gt; include it in the path of the main app.&lt;br /&gt; &lt;br /&gt; To do this, put the following in your &lt;b&gt;init.rb&lt;/b&gt; file in the root&lt;br /&gt; of your plugin. &amp;nbsp;To add a new view path in your plugin that's at&lt;br /&gt; PLUGIN_ROOT/lib/views (where PLUGIN_ROOT is the root directory of your&lt;br /&gt; plugin):&lt;br /&gt; &lt;br /&gt; &lt;pre name="code" class="ruby"&gt;&lt;br /&gt;   ActionController::Base.append_view_path(File.join(PLUGIN_ROOT, "lib", "views"))&lt;br /&gt; &lt;/pre&gt;&lt;br /&gt; &lt;br /&gt; Any template files (like html.erb) that you put in that path will be&lt;br /&gt; seen in your app.&lt;br /&gt; &lt;br /&gt; To add new helper, model, or controller directories in the rails load path:&lt;br /&gt; &lt;br /&gt; &lt;pre name="code" class="ruby"&gt;&lt;br /&gt; %w{ helpers model controller }.each do |dir|&lt;br /&gt;   path = File.join(PLUGIN_ROOT, 'lib', dir)&lt;br /&gt;   $LOAD_PATH &lt;&lt; path&lt;br /&gt;   Dependencies.load_paths &lt;&lt; path&lt;br /&gt;   Dependencies.load_once_paths.delete(path)&lt;br /&gt; end&lt;br /&gt; &lt;/pre&gt;&lt;br /&gt; &lt;br /&gt; And now, any models you put in lib/model, lib/controller, and&lt;br /&gt; lib/helpers will be in the rails load path.&lt;br /&gt; &lt;br /&gt; Of course, this might all be moot with the reintroduction of Rails&lt;br /&gt; engines in 2.3. &amp;nbsp;I haven't gotten around to using them or figuring it&lt;br /&gt; out yet, but for now, this is how you do it with plugins. &amp;nbsp;tip!&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/how-to-add-helpers-controllers-models-and-vie"&gt;The Web and all that Jazz&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/16002962-3156527664310854235?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=_h8iF51XOIA:Lwl0I_YdZCA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=_h8iF51XOIA:Lwl0I_YdZCA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=_h8iF51XOIA:Lwl0I_YdZCA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=_h8iF51XOIA:Lwl0I_YdZCA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/_h8iF51XOIA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/3156527664310854235/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/05/how-to-add-helpers-controllers-models.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3156527664310854235?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3156527664310854235?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/_h8iF51XOIA/how-to-add-helpers-controllers-models.html" title="How to add helpers, controllers, models, and views of your plugin into the Rails loadpath" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/05/how-to-add-helpers-controllers-models.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ADQ3o9cSp7ImA9WxJQEE8.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1879939191797114764</id><published>2009-05-22T12:49:00.001-07:00</published><updated>2009-05-22T12:49:32.469-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-22T12:49:32.469-07:00</app:edited><title>Never mix package managers</title><content type="html">
Today, I decided to dive into Python and explore some web frameworks. &lt;br /&gt;Instead, I've spent the better part of the day messing around with &lt;br /&gt;package problems on Mac OsX. &lt;br /&gt;&amp;nbsp;&lt;br /&gt;The problem? Mixing package managers. I had installed py-setuptools &lt;br /&gt;from Mac Ports. Turns out it's still far behind, so it barfs when &lt;br /&gt;easy_install uses it to install something like mysql-python.egg. &lt;br /&gt;&amp;nbsp;&lt;br /&gt;I should know better. On Ubuntu, I only use apt to get the language, &lt;br /&gt;and the rest is managed in rubygems.&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/never-mix-package-managers"&gt;The Web and all that Jazz&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/16002962-1879939191797114764?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=NP5Pv1rxbd8:kNMXn3hAZlU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=NP5Pv1rxbd8:kNMXn3hAZlU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=NP5Pv1rxbd8:kNMXn3hAZlU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=NP5Pv1rxbd8:kNMXn3hAZlU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/NP5Pv1rxbd8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1879939191797114764/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/05/never-mix-package-managers.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1879939191797114764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1879939191797114764?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/NP5Pv1rxbd8/never-mix-package-managers.html" title="Never mix package managers" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/05/never-mix-package-managers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8HSHc8cSp7ImA9WxVbFk4.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1467584230524411914</id><published>2009-04-01T18:53:00.001-07:00</published><updated>2009-04-01T19:03:59.979-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-01T19:03:59.979-07:00</app:edited><title>Senate majority vs. national debt - Getting at public data is a pain</title><content type="html">&lt;div&gt;&lt;div style="padding-bottom: 10px;"&gt;                                  &lt;div&gt;          Last weekend, my friend Ian and I were talking, and we got to the topic of trying to find data online to fact check newspapers.  As newspapers get squeezed due to readership moving online, they have less money to do in-depth research.  We hear more stories about Britney Spears and her ilk not just because of her hot pants, but because she's cheaper to cover.  Sometimes, when newspapers put out something, we find out later that their facts weren't exactly right.&lt;br /&gt;  &lt;br /&gt; One of things he wanted to fact-check was the national debt, and how it related to our politicians.  I imagine he was incensed at the state of financial affairs and wanted to know who were the fools that did it.  He wanted to know what the senate majority was plotted against the national debt.&lt;br /&gt;  &lt;br /&gt; After that, I took some time in the last couple of days to find the data, and then write a ruby script to scrape it and plot it on a javascript webpage.  Here's the resulting graph:&lt;br /&gt;&lt;br /&gt; &lt;div style="text-align: center;"&gt;  &lt;a href="http://docs.google.com/File?id=ajcft2fj8nmp_57dgndwbfx_b" target="_blank"&gt;&lt;img src="http://docs.google.com/File?id=ajcft2fj8nmp_57dgndwbfx_b" style="width: 541px; height: 271px;" /&gt;&lt;/a&gt;  &lt;/div&gt; &lt;br /&gt; The first surprising thing was how fast the national debt has grown in the last 30 years.  It's been an exponential growth.  I think that while increased spending have happened, the interest on the debt has a significant effect on that growth.&lt;br /&gt;  &lt;br /&gt; The second surprising thing was how much democrats dominated the era between 1930 and 1980, with a sliver of Republican majority in the 50's.  And before that, it was dominated by the Republicans.  Apparently, political ideology shifts back and forth.&lt;br /&gt;  &lt;br /&gt; One of the things I have to note about the graph is that the first set of Red in the early 1800's is not the modern Republican party we know today.  It was another party of the same name, I think also called Jeffersonian-Republicans.  The gaps before and after were times when there were no Democrats or Republicans.  There were Pro-administration or Anti-administration, or Pro-Jackson, Anti-Jackson, or Whigs and others.  In addition, there weren't 100 seats in the Senate at the very beginning, so we see some instances where Senate Majority wasn't more than 50 seats.&lt;br /&gt;  &lt;br /&gt; Oh, and because I'm lazy, I didn't label the axis.  The left y-axis is the # of senate seats held by the majority party.  The right y-axis is the national debt in dollars.&lt;br /&gt;&lt;br /&gt; We can see from the graph that the explosive rise in national debt occurred in the last two or three decades.  In addition, both parties had Senate majority at the time.  Not only that, but the Senate Majority party only had a slight majority, which meant that it could tip in favor of the other party from congress to congress.&lt;br /&gt;  &lt;br /&gt; Seeing how it was exponential, I plotted it as a &lt;a href="http://www.physics.uoguelph.ca/tutorials/GLP/" title="log-plots" target="_blank"&gt;log-plot&lt;/a&gt;.  Ian quipped that "it's terrifying that it makes sense to plot the national debt in log scale."&lt;br /&gt;  &lt;br /&gt; &lt;div style="text-align: center;"&gt;  &lt;a href="http://docs.google.com/File?id=ajcft2fj8nmp_58fpfrq2cf_b" target="_blank"&gt;&lt;img src="http://docs.google.com/File?id=ajcft2fj8nmp_58fpfrq2cf_b" style="width: 547px; height: 281px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; &lt;div style="text-align: left;"&gt;  &lt;/div&gt;  &lt;/div&gt;  You can see more details here.  Remember, a line in a log plot means exponential growth.  We can see that there are times in history that the US debt dropped or rose at a significantly rapid rate.  I was surprised to see that in the mid 1830's, it looked like the US cleared itself of its debt.  I don't know enough about history to know whether the US just defaulted or it paid the debt back.  The significant rises in debt seem to correlate with the major wars.  1860's for the US Civil War, the 1915's for WWI and 1940's for WWII.&lt;br /&gt;  &lt;br /&gt; Now the last graph is not for the faint of heart.  It's a graph of the rate of change of the national debt on a log scale.&lt;br /&gt;&lt;br /&gt; &lt;div style="text-align: center;"&gt;  &lt;a href="http://docs.google.com/File?id=ajcft2fj8nmp_59wnjm9pc2_b" target="_blank"&gt;&lt;img src="http://docs.google.com/File?id=ajcft2fj8nmp_59wnjm9pc2_b" height="277" width="551" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; &lt;div style="text-align: left;"&gt;  Because the changes have been so dramatic in the last couple of decades, it dwarfs any changes in earlier periods on a linear scale.  Here, we can see that for most of the history of the US, the debt change fluctuated up and down.  There were periods of lots of spending, but then also periods of cutting back.  Sometimes, one party was responsible for doing that, and sometimes, it was another.  But in the recent years, we've just been accruing debt.  See that little dip in the late 90's/early 2000?  That was the big savings from the Clinton era.  Note that it's a log scale, so that a little dip up high on the scale means that it's huge when it's lower down.  If we had the level of debt back in the 1920's, we've almost have cleared it.&lt;br /&gt;  &lt;br /&gt; So all this has been interesting, but is this what falls under the "all that jazz" category?  What does it have to do with the web and programming?  I've been thinking about all the public the data that's out there, and how to get to it.  The conclusion was that it was pretty damn hard.  There were four steps to tell this story to you.  I had to find the data, scrape it, clean it, and then graph it.  Of the four steps, the hardest part was scraping and cleaning.  It took a good 4+ hours to do it, and I'm a programmer.  Most other people that were curious enough could use excel, but last I checked, excel didn't do data scraping on web pages.  Hello cut and paste.&lt;br /&gt;  &lt;br /&gt; I think it should be much much easier for citizens in a country where we elect government officials to be informed and see this data for themselves.  Before, we had relied on journalists to give me the straight dope on these facts.  But, as I mentioned before, the newspapers have been in decline.  As a result there's less budget to pay for good reporting watching the government and what it's doing.  Beyond watching the government, I expect that people generally have questions that can be best answered by graphs of public data--and those answers aren't just yes or no.&lt;br /&gt;  &lt;br /&gt; As an example, another friend of mine, Matt, is single and looking for the ladies.  However, living in Columbia, MD, it's a tough dating environment--everyone's under 18 or over 40.  So if he could move, which counties in Maryland has the highest number of single females?&lt;br /&gt;  &lt;br /&gt; Do any of you find that you have similar questions that can be answered by public data in graphs?&lt;br /&gt;&lt;br /&gt;Data Sources:&lt;br /&gt;&lt;a href="http://www.treasurydirect.gov/govt/reports/pd/histdebt/histdebt.htm" target="_blank"&gt;http://www.treasurydirect.gov/&lt;wbr&gt;govt/reports/pd/histdebt/&lt;wbr&gt;histdebt.htm&lt;/a&gt;&lt;br /&gt; &lt;a href="http://www.senate.gov/pagelayout/history/one_item_and_teasers/partydiv.htm" target="_blank"&gt;http://www.senate.gov/&lt;wbr&gt;pagelayout/history/one_item_&lt;wbr&gt;and_teasers/partydiv.htm&lt;/a&gt;&lt;br /&gt; &lt;/div&gt;  &lt;/div&gt;  &lt;/div&gt;  &lt;/div&gt;&lt;/div&gt;&lt;p style="font-size: 10px;"&gt;  &lt;a href="http://posterous.com/"&gt;Posted via email&lt;/a&gt;   from &lt;a href="http://iamwil.posterous.com/senate-majority-vs-national-debt-getting-at-p"&gt;Wil's posterous&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/16002962-1467584230524411914?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ohBczIz36Zs:jFgjDRUCjsw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ohBczIz36Zs:jFgjDRUCjsw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=ohBczIz36Zs:jFgjDRUCjsw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=ohBczIz36Zs:jFgjDRUCjsw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/ohBczIz36Zs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1467584230524411914/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/04/senate-majority-vs-national-debt.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1467584230524411914?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1467584230524411914?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/ohBczIz36Zs/senate-majority-vs-national-debt.html" title="Senate majority vs. national debt - Getting at public data is a pain" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/04/senate-majority-vs-national-debt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YESHkzeip7ImA9WxVUFUs.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-4536259318220330357</id><published>2009-03-19T11:07:00.000-07:00</published><updated>2009-03-20T09:05:09.782-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-20T09:05:09.782-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><title>Bastardized recursion</title><content type="html">I seem to be posting less.  I've been thinking about why that is.  Perhaps, less things are surprising to me now (i.e. I'm not learning as much as before).  When doing this Rails stuff, the bulk is standard fare, and only occasionally do you run into something mildly interesting.  I have been queuing up posts, however.  Between work, small side projects, reading, and hanging, there's less time than before.  &lt;br /&gt;&lt;br /&gt;I stumbled on something, which I saw in the Rails source once.  Thought I'd share.  &lt;br /&gt;&lt;br /&gt;Say I have a :blog that has_many :posts.  But Posts are subclassed to have many different types.  But I wanted that post_type information from Blog in different formats.  Originally, it looked something like this&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;class Blog&lt;br /&gt;  has_many :posts&lt;br /&gt;&lt;br /&gt;  def post_types&lt;br /&gt;    Post.subclasses&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def post_names&lt;br /&gt;    post_types.map { |pt| pt.name.gsub('Post::','') }&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def post_string&lt;br /&gt;    post_names.map { |n| "'" + n + "'" }.join(",")&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since they progressively built off of each other, I figured I can use a bastardized recursion, like I saw in find() in ActiveRecord::Base.&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;class Blog&lt;br /&gt;  has_many :posts&lt;br /&gt;&lt;br /&gt;  def post_types(format = :classes)&lt;br /&gt;    case format&lt;br /&gt;    when :classes&lt;br /&gt;      Post.subclasses&lt;br /&gt;    when :names&lt;br /&gt;      post_types(:classes).map { |pt| pt.name.gsub('Post::','') }&lt;br /&gt;    when :string&lt;br /&gt;      post_types(:names).map { |n| "'" + n + "'" }.join(",")&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Seems alright.  Reduces the clutter of functions that are related to each other, so I'm on the lookout for being able to reduce related functions together like that.  tip~!&lt;br /&gt;&lt;br /&gt;Updated:&lt;br /&gt;Found this &lt;a href="http://research.microsoft.com/en-us/um/people/tball/papers/XmasGift/"&gt;reverse engineering brief on obfuscated code that recites the 12 days of Christmas&lt;/a&gt;.  It uses the same technique that I described above.  I suppose as always, case statements can be abused.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-4536259318220330357?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=PBrVTIPtP6o:FelhFJBWFCw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=PBrVTIPtP6o:FelhFJBWFCw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?a=PBrVTIPtP6o:FelhFJBWFCw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheWebAndAllThatJazz?i=PBrVTIPtP6o:FelhFJBWFCw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/PBrVTIPtP6o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/4536259318220330357/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/03/bastardized-recursion.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/4536259318220330357?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/4536259318220330357?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/PBrVTIPtP6o/bastardized-recursion.html" title="Bastardized recursion" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/03/bastardized-recursion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUESHo7fip7ImA9WxVXFUg.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1705899240134472539</id><published>2009-02-13T10:35:00.000-08:00</published><updated>2009-02-13T10:36:49.406-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-13T10:36:49.406-08:00</app:edited><title>Reply comments to Frock</title><content type="html">Since I can't comment on my own blog, here we go.  And people on &lt;a href="http://groups.google.com/group/blogger-help-howdoi/browse_thread/thread/1ea89c7275eec8e5/deba3f0abdeb9114?lnk=gst&amp;amp;q=can%27t+comment#deba3f0abdeb9114"&gt;blogger groups don't know either&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I was reading that some of the tree methods were mainly used for static collision culling, due to their expensive insertion and deletion properties.  I don't know yet if Quadtrees have the desirable properties.&lt;br /&gt;&lt;br /&gt;Thanks for the link on the Voronoi paper.  I'll take a look at it. &lt;br /&gt;&lt;br /&gt;@Wally thanks.  I'll see what I can do.&lt;br /&gt;&lt;br /&gt;@Hal Oddly enough I saw your simulation on youtube when I was browsing around the other day.  Do you have source I can look at for that?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-1705899240134472539?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=uCw9OB1G"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=BuL5XV0V"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=LWphfFwv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=LWphfFwv" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/AhDpS4ooCG4" height="1" width="1"/&gt;</content><link rel="related" href="http://webjazz.blogspot.com/2009/02/introducing-frock-flocking-chicken.html" title="Reply comments to Frock" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1705899240134472539/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/02/reply-comments-to-frock.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1705899240134472539?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1705899240134472539?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/AhDpS4ooCG4/reply-comments-to-frock.html" title="Reply comments to Frock" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/02/reply-comments-to-frock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8ESXkycCp7ImA9WxVXFEk.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-7685990474949676347</id><published>2009-02-12T04:35:00.000-08:00</published><updated>2009-02-12T05:53:28.798-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-12T05:53:28.798-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="product" /><category scheme="http://www.blogger.com/atom/ns#" term="graphics" /><category scheme="http://www.blogger.com/atom/ns#" term="algorithm" /><category scheme="http://www.blogger.com/atom/ns#" term="love" /><category scheme="http://www.blogger.com/atom/ns#" term="emergent systems" /><category scheme="http://www.blogger.com/atom/ns#" term="lua" /><title>Introducing Frock, a flocking chicken simulation written in Lua with Löve</title><content type="html">I recently learned about &lt;a href="http://love2d.org/"&gt;LÖVE&lt;/a&gt;, a 2D game framework for &lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt; off HN.  It looked simple enough, and when I ran the particle system demo and it was pretty fast.  It seemed faster than what Ruby &lt;a href="http://help.shoooes.net/"&gt;Shoes &lt;/a&gt;would be able to do.  I got rather excited because&lt;br /&gt;&lt;ol&gt;&lt;li&gt;I've always wanted to make my own game.  A lawnmowing game comes to mind.&lt;/li&gt;&lt;li&gt;I wanted to see if I could create a large flocking simulation&lt;/li&gt;&lt;/ol&gt;Also, I've decided a while back to start writing more great projects and do less reading of tech news garbage.  While #1 would be on the backburner for the time being, #2 was fairly easy to do in a couple of hours.  (I think about a weekend's worth of hours total tweaking things).&lt;br /&gt;&lt;br /&gt;I've been fascinated with decentralized systems since right after college--one of them being flocks.  But how do they work?  For a long time, ornithologist (bird scientists) had no clue how birds flocked.  Birds seem to be able to move in unison, as a super-organism, swooping, expanding/contracting, splitting.  When you see massive waves of these things (these are starlings), it's something to behold.  Who is the leader?  How do they coordinate these flocks?&lt;br /&gt;&lt;br /&gt;&lt;object height="295" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/XH-groCeKbE&amp;amp;hl=en&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/XH-groCeKbE&amp;amp;hl=en&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="295" width="480"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;We still don't exactly know, since we don't yet have the capabilities to tap into a bird's decision making mechanism in real time.  However, in the 1990's, Craig Reynolds demonstrated that you can get &lt;a href="http://www.red3d.com/cwr/boids/"&gt;very convincing flock-like behavior generated procedurally&lt;/a&gt;, using three simple rules.  And it ends up that you don't need a leader to get flocking behavior.  All interactions can be local, and each flock member (or boid, as he called it), just needed to follow three simple rules:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Attraction: Move towards the perceived center of the flock according to your neighbors&lt;/li&gt;&lt;li&gt;Repulsion: Avoid colliding with your neighbors&lt;/li&gt;&lt;li&gt;Alignment: Move in the same direction and speed (velocity) as your neighbors.&lt;/li&gt;&lt;/ol&gt;Add up all these vectors together and you get a resultant velocity vector.  Different amounts of the three influences leads to different looking types of flocks.  As an aside, &lt;a href="http://en.wikipedia.org/wiki/Particle_swarm_optimization"&gt;particle swarm optimization&lt;/a&gt; works on the same sort of principles.&lt;br /&gt;&lt;br /&gt;So here it is.  Introducing Frock, a flocking simulator in Lua Love.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_gHN52xJ15r0/SZLQ36aUBDI/AAAAAAAAAgI/q_fPPVHXOuI/s1600-h/Frock.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 239px;" src="http://4.bp.blogspot.com/_gHN52xJ15r0/SZLQ36aUBDI/AAAAAAAAAgI/q_fPPVHXOuI/s320/Frock.png" alt="" id="BLOGGER_PHOTO_ID_5301529370359497778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I release it now, because while it's primitive, it works (release early, release often!).  The screenshot doesn't really show it well, they fly about in a flock, hunting for plants to eat.  It's rather mesmerizing, and I find I just stare at it, the same way I stare at fish tanks.&lt;br /&gt;&lt;br /&gt;It was originally a port of the Ruby Shoe's &lt;a href="http://the-shoebox.org/apps/45"&gt;hungry boids&lt;/a&gt;, but I used flying chickens lifted from &lt;a href="http://tsgk.captainn.net/index.php?p=showgame&amp;amp;t=sy&amp;amp;sy=8&amp;amp;ga=291&amp;amp;sec=7"&gt;Harvest Moon&lt;/a&gt; instead.  I originally had cows flying about, but without flapping, it just wasn't the same.  I also made the repulsion vector increase as a function of decreasing distance.  Otherwise, the chickens didn't mind being right on top of each other if they were on the inside of the flock.&lt;br /&gt;&lt;br /&gt;My immediate goal is to make it support more chickens, so I can get a whole swarm of them.  Right now, I'm using an inefficient algorithm to calculate which chickens are neighbors (basically n^2 comparisons).  So if any of you have good culling techniques applicable here, I'd love to hear it.  I'm currently looking at &lt;a href="http://en.wikipedia.org/wiki/R-tree"&gt;R-trees&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are different possibilities as to where it could go.  I think while lots of people have written boid simulations, they haven't taken it much further than that.  While I've seen ones with predators, I haven't seen anything where people try to evolve the flock parameters, or try to scale it up to a large number of chickens.  One can also do experiments on whether different flock parameters have different coverage of the field, or which set of parameters minimizes the time a plant is alive.&lt;br /&gt;&lt;br /&gt;If at the basic, it becomes a framework for me to write 'me and my neighbors' decentralized algorithms, that'd be useful too.  And since Lua is suppose to be embeddable into other languages, that makes it an even more exciting possibility.  Later on, I'll write a little something about Lua.&lt;br /&gt;&lt;br /&gt;Well, if you decide to try it out yourself, get to the &lt;a href="http://github.com/iamwilhelm/frock/tree/master"&gt;Frock github repo&lt;/a&gt;, and follow the readme.   Patches are welcome, but note I haven't decided on a license yet--but it will be open source.  If you have questions, feel free to contact me or comment.  Have fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-7685990474949676347?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=FwIZYo7B"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=N4ULvvbE"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=HHctNEqR"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=HHctNEqR" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/e0_wU-nHQds" height="1" width="1"/&gt;</content><link rel="related" href="http://github.com/iamwilhelm/frock/tree/master" title="Introducing Frock, a flocking chicken simulation written in Lua with Löve" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/7685990474949676347/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/02/introducing-frock-flocking-chicken.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/7685990474949676347?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/7685990474949676347?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/e0_wU-nHQds/introducing-frock-flocking-chicken.html" title="Introducing Frock, a flocking chicken simulation written in Lua with Löve" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_gHN52xJ15r0/SZLQ36aUBDI/AAAAAAAAAgI/q_fPPVHXOuI/s72-c/Frock.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/02/introducing-frock-flocking-chicken.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIHQXoycSp7ImA9WxVQFkQ.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-8889716853280626811</id><published>2009-02-03T14:00:00.000-08:00</published><updated>2009-02-03T14:02:10.499-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-03T14:02:10.499-08:00</app:edited><title>Can't comment</title><content type="html">Somehow, blogger doesn't let me comment.  I'm not sure why, and I'll fix it some time later, or export to Posterous. &lt;br /&gt;&lt;br /&gt;Thanks trevor.  I've subscribed to your weekly digest.  I've been reading Hacker News all this time.  However, it wasn't so much that I didn't have time to read, as I didn't have time to synthesize them.&lt;br /&gt;&lt;br /&gt;And oh, thanks for the Perforce slides.  They've been really helpful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-8889716853280626811?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=607fNWls"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=W2SgWBnl"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=yXo0mDVn"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=yXo0mDVn" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/W0rojHXZi5k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/8889716853280626811/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/02/cant-comment.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/8889716853280626811?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/8889716853280626811?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/W0rojHXZi5k/cant-comment.html" title="Can't comment" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/02/cant-comment.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMEQno_eip7ImA9WxVQFkQ.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1221190679898008628</id><published>2009-02-03T12:47:00.000-08:00</published><updated>2009-02-03T12:53:23.442-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-03T12:53:23.442-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nerd time" /><title>Nerd time, issue 15</title><content type="html">Nerd time is back, due to some complaints in person about how they missed it.  In brief, nerd time is an occasional mailing list I send out to people I know that work at research labs.  They're usually slow in getting the tech world news, so I thought it would be fun to pass along some tech news bits.  This is issue 15.&lt;br /&gt;-----&lt;br /&gt;Hi all. &lt;br /&gt;&lt;br /&gt;Well, after starting work at Frogmetrics last May, I got really busy writing code, learning about business and startup related things, and absorbing sales and marketing stuff, that I simply read a lot less.  There was also less tech news going on that I felt was significant.  When there's no significant news, the echoes become pretty loud in the echo chamber.  Since I didn't hear anyone say anything about it, I figured no one read nerd time.  And since I was reading less, I became more intellectually lazy.  Hence the 10 month silence on nerd time.&lt;br /&gt;&lt;br /&gt;But about a month and a half ago, I got in-person complaints that nerd time was no longer being sent out, so here it is reinstated.  Some of these might be old news, but it's what I collected and found was significant over the last couple of months.  And what the hell, old news in the tech world takes a while to get to the research lab world, so hey, this might be new to you.  This time is mostly about source control and languages.  I have other things I'm playing with that might be of interest, but will reveal them as I mature them.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git the decentralized version control&lt;br /&gt;&lt;/b&gt;Decentralized version control isn't anything new, but its adoption is.  Git is pretty powerful.  I don't go into all the reasons why.  You can read about it in my post &lt;a href="http://webjazz.blogspot.com/2009/01/git-allows-my-workflow-to-be-stateless.html" target="_blank"&gt;here&lt;/a&gt;.  But on a deeper level, git is essentially a versioned filesystem.  In fact, what's most interesting about it is how general it is and how you can use it for things other than version control.  You can use it to synchronize address books, remote deploy code, or even as a basic wiki or blog. &lt;br /&gt;&lt;a href="http://git-scm.com/" target="_blank"&gt;http://git-scm.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://whygitisbetterthanx.com/" target="_blank"&gt;http://whygitisbetterthanx.&lt;wbr&gt;com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://eagain.net/articles/git-for-computer-scientists/" target="_blank"&gt;http://eagain.net/articles/&lt;wbr&gt;git-for-computer-scientists/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Github a social network for developers&lt;/b&gt;&lt;br /&gt;Github is like sourceforge, but much better designed, and has a social component to it.  I can follow the coders and projects that I admire or find useful, and I can also see what projects they are committing to or watching.  Thus, it gives me a sort of leading indicator of what the alpha nerds and geeks find interesting.  And what they find interesting is what you and I will be using in our jobs 5 to 8 years down the line.  The generality of git, as mentioned in the previous entry is given as an example in the last link.  It's of Raganwald, a well known Ruby coder and blogger who blogs on Github.  Having a central place to commit and share code sorta defeats a mainstay of decentralized source control, but let's ignore that point for now, and drink the github kool-aid&lt;br /&gt;&lt;a href="http://www.github.com/" target="_blank"&gt;http://www.github.com/&lt;/a&gt;&lt;br /&gt;   &lt;a href="http://github.com/raganwald/homoiconic/tree/master/2008-10-30/thrush.markdown" target="_blank"&gt;http://github.com/raganwald/&lt;wbr&gt;homoiconic/tree/master/2008-&lt;wbr&gt;10-30/thrush.markdown&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;GitTorrent&lt;/b&gt;&lt;br /&gt;Along the same lines, someone combined git with bittorrents.  Whoot.&lt;br /&gt;&lt;a href="http://www.advogato.org/article/994.html" target="_blank"&gt;http://www.advogato.org/&lt;wbr&gt;article/994.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SUP friendfeed&lt;/b&gt;&lt;br /&gt; I'm personally not as excited about SUP as I don't mess around with feeds that much.  But it claims to cut down on bandwidth for servicing feeds&lt;br /&gt;&lt;a href="http://blog.friendfeed.com/2008/08/simple-update-protocol-fetch-updates.html" target="_blank"&gt;http://blog.friendfeed.com/&lt;wbr&gt;2008/08/simple-update-&lt;wbr&gt;protocol-fetch-updates.html&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Sinatra&lt;/b&gt;&lt;br /&gt;If you thought Rails was lightweight, Sinatra blows it out of the water.  While there have been other micro-frameworks for web apps, sinatra takes the cake in my opinion.  It doesn't take very much at all to get something up and running with sinatra.  So given the amount of prototyping work that the lab does, it helps to just get something demoable up.  If you wanted to continue with it, sinatra runs on pretty solid web server, and you can optionally switch it out also.  I'd recommend taking a good look at it, and brush up on your Ruby skills as well.&lt;br /&gt;&lt;a href="http://sinatra.rubyforge.org/" target="_blank"&gt;http://sinatra.rubyforge.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Clojure&lt;/b&gt;&lt;br /&gt;Clojure is a lisp dialect in a JVM.  I've heard some good things about it, but I haven't really tried it out myself, so I can't speak on the merits of Clojure.  However, as the second link below wonders, could Clojure be to concurrency orientated programming as Java was to OOP?  I've talked about Erlang in the past, and it defn has some amazing traits as a programming language, barring the syntax. &lt;br /&gt;&lt;a href="http://clojure.org/" target="_blank"&gt;http://clojure.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://bc.tech.coop/blog/081201.html" target="_blank"&gt;http://bc.tech.coop/blog/&lt;wbr&gt;081201.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As for actual programming languages I've been messing with, there are three.  Erlang, Javascript, and Lua.  I'll only talk about the last one--and I only started messing with it because of LÖVE.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;LÖVE is an &lt;i&gt;"unquestionably&lt;/i&gt; awesome 2D game engine"&lt;/b&gt;&lt;br /&gt;More akin to Pygame in Python than to Shoes in Ruby, Love lets you quickly build a game, but still stay within the realms of programming.  The reason why I find it worth mentioning are the merits of Lua.  It's a basic interpreted language, but it's embeddable into other languages, and its total size is pretty small ~200k or so.  This make it ideal to be used in embedded systems.  In addition, it's one of the faster interpreted languages out there, and with LuaJIT (on the JVM), it's even faster. &lt;br /&gt;&lt;a href="http://love2d.org/?teej" target="_blank"&gt;http://love2d.org/?teej&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mozilla Weave and Prism&lt;br /&gt;Google Chrome&lt;/b&gt;&lt;br /&gt;While I'm sure the lot of you have heard about Google Chrome, what's interesting to me is in relation to the direction that Mozilla, and also Adobe Air have been trying to move towards: treating web applications like desktop applications.  Not only will they be easy to install, and easy to maintain, but they afford easy collaboration with others.  And with the maturity of Google Gears, being offline is not a problem now either.  While there are still a couple bastions where pure desktop applications reign, such as gaming, I think we'll find that the web app style development to be more pervasive for desktop apps.&lt;br /&gt; &lt;a href="http://labs.mozilla.com/2007/10/prism/" target="_blank"&gt;http://labs.mozilla.com/2007/&lt;wbr&gt;10/prism/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://labs.mozilla.com/2007/12/introducing-weave/" target="_blank"&gt;http://labs.mozilla.com/2007/&lt;wbr&gt;12/introducing-weave/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/chrome" target="_blank"&gt;http://www.google.com/chrome&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SVG and application development&lt;/b&gt;&lt;br /&gt;I don't know that SVG will be the future of application development or not, but I know that the current html and css constructs were meant for documents.  Web developers are actually rebending those tools for application needs.  While it's useful to think of the web as a collection of resources and document--it makes for a scaleable app--the actual page elements are still stuck in document-page speak.  It would make it easier for app development to have their own app-specific constructs.  SVG may or may not help in that regard&lt;br /&gt;&lt;a href="http://www.sitepoint.com/blogs/2008/12/22/svg-is-the-future-of-application-development/" target="_blank"&gt;http://www.sitepoint.com/&lt;wbr&gt;blogs/2008/12/22/svg-is-the-&lt;wbr&gt;future-of-application-&lt;wbr&gt;development/&lt;/a&gt;&lt;br /&gt;     &lt;br /&gt;&lt;b&gt;Stackless Python, PyCUDA&lt;/b&gt;&lt;br /&gt;There's lot of people trying to find suitable languages for our multicore future.  I'm not so sure that Erlang will be it.  However, functional programming concepts are going to make a comeback, if not already.  Python is poised to be ready as being able to handle concurrency through stackless.  Some people are experimenting with using Python to access the new Nvidia CUDA hardware architecture.&lt;br /&gt;&lt;a href="http://www.stackless.com/" target="_blank"&gt;http://www.stackless.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mathema.tician.de/software/pycuda" target="_blank"&gt;http://mathema.tician.de/&lt;wbr&gt;software/pycuda&lt;/a&gt;&lt;br /&gt;   &lt;br /&gt;&lt;b&gt;Gnip Central&lt;/b&gt;&lt;br /&gt;Gnip central acts as a data middle man.  Often times, getting through the API sucks for various reasons, and having a middle man that either converts that data for you, makes it available, or converts it into a push model instead makes it convenient.  It's an interesting niche, and I see this is as a perennial tar pit of data portability. &lt;br /&gt; &lt;a href="http://www.gnipcentral.com/" target="_blank"&gt;http://www.gnipcentral.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;New York Times API&lt;/b&gt;&lt;br /&gt;New York times is probably the more forward thinking out of all the newspapers when it comes to the web.  Who else do you know that has released an API?&lt;br /&gt; &lt;a href="http://developer.nytimes.com/docs/movie_reviews_api?authChecked=1" target="_blank"&gt;http://developer.nytimes.com/&lt;wbr&gt;docs/movie_reviews_api?&lt;wbr&gt;authChecked=1&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-1221190679898008628?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=guuNBnUG"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=pByZs7MP"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=22Whycyh"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=22Whycyh" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/qWKwFjDZ86s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1221190679898008628/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/02/nerd-time-issue-15.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1221190679898008628?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1221190679898008628?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/qWKwFjDZ86s/nerd-time-issue-15.html" title="Nerd time, issue 15" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/02/nerd-time-issue-15.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cHQno6cSp7ImA9WxVQE0g.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-2525659016849002110</id><published>2009-01-29T06:25:00.000-08:00</published><updated>2009-01-30T13:30:33.419-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-30T13:30:33.419-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="deployment" /><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><title>Figuring out a branching strategy</title><content type="html">To be honest, before I started working at &lt;a href="http://www.frogmetrics.com"&gt;Frogmetrics&lt;/a&gt;, I didn't know how project branches were managed.  I was working at a research lab, and most of what we did was prototyping.  After we demonstrated that it worked, we threw it over a wall, and then it was someone else's problem (poor them).  A lot of the time, I was doing work on my own, so there was no (perceived) need for source control.  The only time we used source control was when I was working on the New Horizon spacecraft.  And even then, someone else managed the branches.  Because it was SVN, we all mainly worked off trunk. &lt;br /&gt;&lt;br /&gt;Until recently, I never contributed to an open source project either.  Therefore, I really had no idea when to branch.  So when we started working on the analytics, we really had no idea what a good branching strategy would be.&lt;br /&gt;&lt;br /&gt;Googling didn't help, because either everyone else doesn't call it "branching strategy", or everyone already knew how to do it.  I eventually figured something out though.  &lt;br /&gt;&lt;br /&gt;Last week, after talking to AJ of &lt;a href="http://www.scoopler.com"&gt;Scoopler&lt;/a&gt; about git, he ended up asking about branching strategy.  It became apparent that branching strategy wasn't an obvious thing, so I decided to write something here.  This is obviously not the only way to do it, so if you have other suggestions, by all means, comment.&lt;br /&gt;&lt;br /&gt;At first, we didn't know what we were doing.  We knew that we wanted to have a branch that had the same code on the production server, and another branch where we're working on the 'next' version.  So we had a branching strategy that looked like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gHN52xJ15r0/SYG8vJr6wtI/AAAAAAAAAfg/QR5fclTSp0Y/s1600-h/bad+branching.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_gHN52xJ15r0/SYG8vJr6wtI/AAAAAAAAAfg/QR5fclTSp0Y/s320/bad+branching.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296722155004412626" /&gt;&lt;/a&gt;&lt;br /&gt;As you can see, we branched every time we deployed weekly.  This gave us the option of doing bug fixes on the every deploy version, while keeping a working branch.  However, this was a terrible way to do things.  This branching strategy required you to keep merging back bug fixes that you had made earlier.  In addition, we were using bug tracking software to track all the issues from week to week, which results in much ticket shuffling and overhead. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_gHN52xJ15r0/SYG9FpRJCLI/AAAAAAAAAfo/X0ES8zhjaRU/s1600-h/good+branching.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_gHN52xJ15r0/SYG9FpRJCLI/AAAAAAAAAfo/X0ES8zhjaRU/s320/good+branching.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5296722541439158450" /&gt;&lt;/a&gt;&lt;br /&gt;Now, we're doing this.  Locally, we still branch for every feature that we're working on.  And when there's a major set of features that need to be implemented by more than one developer, we create a remote branch for it that we push and pull to/from.&lt;br /&gt;&lt;br /&gt;Thus, we're treating master as the golden copy of the code base.  It is always deploy-able, passes all tests, and is perfect code as we know it.  This allows us still the advantage of doing bug fixes and deploying independent of what features are currently on deck or in the hole, and yet we don't have to do merges every time are about to do a new version.  We simply (and somewhat arbitrarily) tag versions as we go along, and only merge feature branches back.  When we can, we rebase the branches to keep the history clean.  In addition, we try to make our commits atomic and about one thing, rather than one feature set.  That way, it makes it very helpful to remove a piece of code, cherry-pick a changeset to another branch, or find an offending commit that broke something.&lt;br /&gt;&lt;br /&gt;So far, it's worked pretty well, but it might evolve as we go on.&lt;br /&gt;&lt;br /&gt;Well, hope that helps.  This post wasn't as fun to write, but it was something I hadn't see too much of out on the web, so I figured I'd contribute.  Fun times.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-2525659016849002110?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=1t8dCUXI"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=Q5qUtgKu"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=DHhy5oMm"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=DHhy5oMm" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/1mz2bhtXICo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/2525659016849002110/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/01/figuring-out-branching-strategy.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2525659016849002110?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2525659016849002110?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/1mz2bhtXICo/figuring-out-branching-strategy.html" title="Figuring out a branching strategy" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_gHN52xJ15r0/SYG8vJr6wtI/AAAAAAAAAfg/QR5fclTSp0Y/s72-c/bad+branching.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/01/figuring-out-branching-strategy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQEQXw7cCp7ImA9WxVRF04.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-429989580926548664</id><published>2009-01-23T09:55:00.000-08:00</published><updated>2009-01-23T09:55:00.208-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-23T09:55:00.208-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="git tip" /><title>Git allows my workflow to be "stateless" (or more advanced features of git)</title><content type="html">I've been using &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; since May, and I feel like I use it pretty comfortably now.  Oddly enough, with SVN, I just learned the basic check in and out, and left it at that.  With git, I find that I want to do something--after poking around docs and tutorials, I find some of the advanced features of git something that I'd want to use.&lt;br /&gt;&lt;br /&gt;Git has a bit of a learning curve, since their commands aren't exactly intuitive (&lt;a href="http://webjazz.blogspot.com/2008/07/git-remote-branch-notes.html"&gt;deleting a remote repository anyone?&lt;/a&gt;, how about reverting is different from resetting?) you have to discard your notions of Svn, and learn how Git models a repository.  But once you grasp that, it's pretty easy, not to mention pretty powerful. For me, Git had certain features that gave me a "wow", as I learned about and got use to using them.  Here's in order as I discovered them.&lt;br /&gt;&lt;h3&gt;Local branching&lt;/h3&gt;&lt;br /&gt;Branching is fast, and merging is relatively painless. When branching is fast, you end up treating branches are like tabs on your browser, but for source control.  This lets you experiment with different code without affecting the main branch.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git checkout -b new_branch&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Builtin Grep&lt;/h3&gt;&lt;br /&gt;I hated that grep would also search through the .svn files.  Sure, I wrote an alias and script so that it wouldn't, but it would leak sometimes.  Having git have a built-in grep was very nice.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git grep "some_regex"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Interactive staging of commits&lt;/h3&gt;&lt;br /&gt;Git has this idea of staging files, meaning marking them for a commit.  Because you can commit different files, you can fix little things that might not have to do with your current ticket, but add them as separate commits.  &lt;br /&gt;&lt;br /&gt;But what if you edited one file but the edits had to do with two different tickets?  With git, you can selectively stage parts of a file for committing.  &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git add -p&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Rebasing branches&lt;/h3&gt;&lt;br /&gt;Rebase was a little confusing to me at first.  The name didn't tell me anything.  Rebase isa tool with multiple functions, with the same underlying principle, which is why it has just one name.  &lt;br /&gt;&lt;br /&gt;At the very basic, you can use rebase to move the root of the local branch if you want the changes made on the parent branch since then.  This is important because it puts the burden of merging on the patch writer, and not on the merger.  In addition, it makes for a cleaner commit history. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git checkout child_branch&lt;br /&gt;git rebase parent_branch&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Even better, you can reorder the commits as long as you haven't pushed it to a remote repository yet. The same task allows you to squash your commits together for a cleaner history. &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git rebase -i HEAD~&lt;span style="font-style:italic;"&gt;n&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Stashing changes&lt;/h3&gt;&lt;br /&gt;Because you can stage files for commits and you can readily switch between branches, sometimes, you might be working on something, but they're not ready to be committed.  The production code has a bug that needs to be fixed immediately.  Git won't let you switch branches, but you don't want to commit unfinished code.  What do you do?&lt;br /&gt;&lt;br /&gt;Git lets you stash your changes to save your uncommitted changes, but not commit them anywhere.  This is useful to switch to another branch to fix an emergency bug or perform other operations that require no uncommitted changes in the working directory (like rebase). &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git stash&lt;br /&gt;...fix bug on other branch...&lt;br /&gt;git stash list&lt;br /&gt;git stash apply&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Bisection of commits&lt;/h3&gt;&lt;br /&gt;Sometimes, you're humming along with your commits, and you find that there was a part of the application that is broken, but your tests didn't catch it.  You need to revert back to that version and make a branch.  You can use git bisect to look for a particular commit.  You give it a commit, and git will checkout that version, and ask you whether it works or not.  Then it bisects the commits and half and then checks out the other half and asks you if it's correct.  If not, it'll keep narrowing down the space of commits until you find the right one.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git bisect &lt;span style="font-style:italic;"&gt;commit_hash&lt;/span&gt; &lt;span style="font-style:italic;"&gt;other_commit_hash&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Basically, a lot of what Git enables me to do is switch between tasks easily.  I don't know if it's the right word, but it lets me work statelessly.  At no time does git not let me do something because of a particular part of my workflow that I'm in.  Outside of a few commands like &lt;span style="font-style:italic;"&gt;rebase&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;merge&lt;/span&gt; (which can be fixed with &lt;span style="font-style:italic;"&gt;stash&lt;/span&gt;), the commands I can run in git doesn't depend on the previous commands I've run.  Really, git is a tabbed browser for me.&lt;br /&gt;&lt;br /&gt;My biggest complaint is probably that the names of the commands aren't intuitive because it goes against the usual mental model of what a repo does.  The names are actually make a lot more sense only after you understand how git models a repository.  So take a look at the &lt;a href="http://book.git-scm.com/"&gt;git book&lt;/a&gt;, and learn what you can.&lt;br /&gt;&lt;br /&gt;tip!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-429989580926548664?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=N69gAqXk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=96BCTHv1"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=GhCjKJhk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=GhCjKJhk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/I4-oN_pusfs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/429989580926548664/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/01/git-allows-my-workflow-to-be-stateless.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/429989580926548664?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/429989580926548664?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/I4-oN_pusfs/git-allows-my-workflow-to-be-stateless.html" title="Git allows my workflow to be &quot;stateless&quot; (or more advanced features of git)" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/01/git-allows-my-workflow-to-be-stateless.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUGRHkzfyp7ImA9WxVXEUU.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1028678761784714644</id><published>2009-01-12T11:13:00.000-08:00</published><updated>2009-02-09T05:47:05.787-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-09T05:47:05.787-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sexual selection" /><category scheme="http://www.blogger.com/atom/ns#" term="iphone" /><title>iPhone jailbreaking resources because search has failed me.</title><content type="html">A couple weeks back, I jailbroke my iPhone, so I could finally join the rest of the techno literati while on a carrier besides AT&amp;amp;T.  However, this is one of those popular topics that are fraught with websites that just have a ridiculous number of ads on them.  Not only that, it's mostly blogs repeating each other, and you get 2nd, 3rd, or maybe 50th hand information.  And a lot of them are un-informational--only trying to sell you iPhone jailbreaking services.  Didn't know the difference between jailbreaking and unlocking, and could barely find the page.&lt;br /&gt;&lt;br /&gt;Because google search fails in this regard, I will recount that Jailbreaking is when you break the iPhone free of the app store, and you can install software from other sources and app installers, like Cydia.  Unlocking is making your phone work with any phone carrier.&lt;br /&gt;&lt;br /&gt;Surprisingly, these links were hard to fine--of the actual &lt;a href="http://wikee.iphwn.org/main"&gt;iPhone Dev Team Portal&lt;/a&gt; and of &lt;a href="http://www.hackint0sh.org/forum/f123/"&gt;their forum&lt;/a&gt;.  Those are what I found to be most helpful, though they don't even have a download page, which makes me kinda mad as I hunted around for it.  Checkout &lt;a href="http://blog.iphone-dev.org/post/67797811/dont-eat-yellowsn0w"&gt;yellowsn0w&lt;/a&gt;, as well as their &lt;a href="http://wikee.iphwn.org/news:pwnage20announcement"&gt;QuickPwn&lt;/a&gt;, also &lt;a href="http://blog.iphone-dev.org/post/74278878/close-the-stable-door"&gt;here&lt;/a&gt; (much better than Z-phone).  If you're still confused, which rightfully, you are.  Over at&lt;a href="http://www.iclarified.com/entries/index.php?caid=2&amp;amp;scid=11&amp;amp;seid=1"&gt; iClarified&lt;/a&gt;, there are very good and clear tutorials on how to use the applications.&lt;br /&gt;&lt;br /&gt;IPhone unlocking is one of those searches that I think Google just fails at.  I hadn't noticed because most of what I search for is usually academic, mathematic, or open source developer related.  Those two have been rather blissfully free of intrusive ads of non-informational webpages.  With such a system, people know they're being watched and indexed, and if it's an advantage to get a 'high score', they're going to try to game (or optimize) on it.  It seems uncannily related to sexual selection.  I'll talk about that in another post in the future.  For now, enjoy the iPhone resources&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-1028678761784714644?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=1VSJLdQt"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=nhnYFNBw"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=JLqaPkUN"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=JLqaPkUN" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/R8iOdN597yo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1028678761784714644/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2009/01/iphone-jailbreaking-resources-because.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1028678761784714644?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1028678761784714644?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/R8iOdN597yo/iphone-jailbreaking-resources-because.html" title="iPhone jailbreaking resources because search has failed me." /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2009/01/iphone-jailbreaking-resources-because.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cHRH49fCp7ImA9WxRaEE4.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-2290410809136709167</id><published>2008-12-11T14:37:00.000-08:00</published><updated>2008-12-11T14:37:15.064-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-11T14:37:15.064-08:00</app:edited><title>The Web and all that Jazz: Git remote branch notes</title><content type="html">A while back, I was wondering how to make a remote branch from a local branch because all the solutions I knew of &lt;a href="http://webjazz.blogspot.com/2008/07/git-remote-branch-notes.html"&gt;created a remote branch from master, using origin&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After trying out a couple things, I realized I could just create the remote branch from master, and just rebase the damn thing:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;git push origin {new_remote_branch}&lt;br /&gt;git branch --track {new_remote_branch} origin/{new_remote_branch}&lt;br /&gt;git checkout {new_remote_branch}&lt;br /&gt;git rebase {local_branch}&lt;br /&gt;git push&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Not super interesting, but enough and short enough to blog about.  tip!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-2290410809136709167?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=GFGrphcv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=sGt3nN3U"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=vcchYNDu"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=vcchYNDu" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/ZOn7UO588Nk" height="1" width="1"/&gt;</content><link rel="related" href="http://webjazz.blogspot.com/2008/07/git-remote-branch-notes.html" title="The Web and all that Jazz: Git remote branch notes" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/2290410809136709167/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/12/web-and-all-that-jazz-git-remote-branch.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2290410809136709167?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2290410809136709167?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/ZOn7UO588Nk/web-and-all-that-jazz-git-remote-branch.html" title="The Web and all that Jazz: Git remote branch notes" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/12/web-and-all-that-jazz-git-remote-branch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMNQn49cCp7ImA9WxRUEkU.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-3685887479932854614</id><published>2008-11-21T09:11:00.000-08:00</published><updated>2008-11-21T09:11:33.068-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-21T09:11:33.068-08:00</app:edited><title>Augmenting Google's search results</title><content type="html">Here, techcrunch was complaining about Google's newly released feature of being able to change the ordering of the search results.  The point that seemed to have escaped people is that, the search results that you change are only local to you. Other people don't see them.&lt;br /&gt;&lt;br /&gt;Because of that, I think Google can encourage the behavior where people are sending links relevant to themselves up to the their front page in an honest way. If they click things up that have no relevance to themselves, they only screw up their own searches.&lt;br /&gt;&lt;br /&gt;So if you have millions of people sending things relevant to themselves up the list, Google is basically gathering data about what the human 'gold standard' for a particular search query is (augmented by machine sorting first).&lt;br /&gt;&lt;br /&gt;In information retrieval, one of the hard things is to know whether you've done a better job of returning search results or not, since a gold standard dataset is hard to come by and time consuming to produce.&lt;br /&gt;&lt;br /&gt;Here, I think Google is simply using a mechanism where they're aligning people's self-interest to create accurate data they can use to compare their search algorithm tweaks.&lt;br /&gt;&lt;br /&gt;All in all, a good thing. Even better if you can 'merge' search results from others that you trust..say your friends. I wouldn't mind merging my search results with _why's. More complexity that way, though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-3685887479932854614?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=nePJFFbc"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=aTo0Yv7q"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=NiOwRgXS"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=NiOwRgXS" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/4eOSj_8dRVs" height="1" width="1"/&gt;</content><link rel="related" href="http://www.techcrunch.com/2008/11/21/google-it-wasnt-broke/" title="Augmenting Google's search results" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/3685887479932854614/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/11/augmenting-googles-search-results.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3685887479932854614?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/3685887479932854614?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/4eOSj_8dRVs/augmenting-googles-search-results.html" title="Augmenting Google's search results" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/11/augmenting-googles-search-results.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQNQ3s9cSp7ImA9WxRWEkk.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-2838456014090749590</id><published>2008-10-24T06:29:00.000-07:00</published><updated>2008-10-28T19:46:32.569-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-28T19:46:32.569-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="frogmetrics" /><title>Frogmetrics on techcrunch</title><content type="html">As some of you know, I joined a YCombinator company called &lt;a href="http://www.frogmetrics.com"&gt;Frogmetrics&lt;/a&gt;.  We've launched, and was covered by &lt;a href="http://www.techcrunch.com/2008/10/23/frogmetrics-handheld-surveys-you-might-actually-want-to-fill-out/"&gt;Techcrunch&lt;/a&gt; last night.  &lt;br /&gt;&lt;br /&gt;I work on the server side of things, which means &lt;a href="http://frogmetrics.com/analytics"&gt;the analytics package&lt;/a&gt; which we call Mastermind.  Working on the architecture over the summer was a little bit different than the typical rails app.  &lt;br /&gt;&lt;br /&gt;Mastermind allows users to view graphs of survey data for a particular region, location, or employee at a specific time period.   &lt;br /&gt;&lt;br /&gt;One of the comments that I saw on techcrunch was why didn't we use iPhones?  That's a common question, and the answer is a mix of technical and business reasons.  If we had iPhones to give to people, they would readily know that it was an iPhone and be more likely to run off with one.  Sorry Nokia, but your tablets just aren't as sexy to run off with.  Alternatively, telling people to go to a webpage on their iPhones would be another barrier to taking the survey.  It wouldn't get the high response rates that we're seeing right now.  The idea is to make it as easy and as painless as possible to take a survey.  In our pilots, we found that older folks had a much tougher time reading the text.  Nokias have bigger screens, and we could hence put bigger text on there, not to mention big beautiful buttons that affords pushing.  &lt;br /&gt;&lt;br /&gt;Well, if you or your company has interest in our product, feel free to let us know on &lt;a href="http://frogmetrics.com/contact"&gt;the contact page&lt;/a&gt;.  I dislike that we don't have our prices on the web page as of yet, but that'll be worked out soon. &lt;br /&gt;&lt;br /&gt;Wish us luck (and hard work)!&lt;br /&gt;&lt;br /&gt;As a side note, interesting things that I post on here don't always have to do with Frogmetrics.  Like any good engineer, I play or think about interesting things whether they're related to work or not.  So don't take it that whatever I'm playing with here is what's going into Frogmetrics.  :)&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;br /&gt;Edited&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-2838456014090749590?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=mFn5ld8A"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=Fr2kD6QD"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=ihtv1rR8"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=ihtv1rR8" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/itCm6Ukhbeo" height="1" width="1"/&gt;</content><link rel="related" href="http://www.techcrunch.com/2008/10/23/frogmetrics-handheld-surveys-you-might-actually-want-to-fill-out/" title="Frogmetrics on techcrunch" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/2838456014090749590/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/10/frogmetrics-on-techcrunch.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2838456014090749590?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/2838456014090749590?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/itCm6Ukhbeo/frogmetrics-on-techcrunch.html" title="Frogmetrics on techcrunch" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/10/frogmetrics-on-techcrunch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIDRngyeSp7ImA9WxRQEEk.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1743270020220645859</id><published>2008-10-02T20:07:00.000-07:00</published><updated>2008-10-03T07:02:57.691-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-03T07:02:57.691-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="snippet" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="benchmarking" /><category scheme="http://www.blogger.com/atom/ns#" term="linear algebra" /><title>Benchmarking row multiply in Ruby's Linalg</title><content type="html">While using LinAlg to write and understand/review &lt;a href="http://www.autonlab.org/tutorials/infogain.html"&gt;information gain&lt;/a&gt;, I found that I wanted the equivalent of a row multiply, notated as &lt;span style="font-style: italic;"&gt;[*]&lt;/span&gt; (it's non-standard.  I made up the notation), where:&lt;br /&gt;&lt;pre&gt;A [*] x = B&lt;br /&gt;&lt;br /&gt;[[a&lt;sub&gt;00&lt;/sub&gt;, ..., a&lt;sub&gt;0M&lt;/sub&gt;]      [[x&lt;sub&gt;0&lt;/sub&gt;]    [[a&lt;sub&gt;00&lt;/sub&gt; * x&lt;sub&gt;0&lt;/sub&gt;, ..., a&lt;sub&gt;0M&lt;/sub&gt; * &lt;sub&gt;x0&lt;/sub&gt;]&lt;br /&gt; [...       ...]  [*]  [x&lt;sub&gt;1&lt;/sub&gt;]  =  [... * x&lt;sub&gt;1&lt;/sub&gt;, ....      ...]&lt;br /&gt; [a&lt;sub&gt;N0&lt;/sub&gt;, ..., a&lt;sub&gt;NM&lt;/sub&gt;]]      [x&lt;sub&gt;2&lt;/sub&gt;]]    [a&lt;sub&gt;N0&lt;/sub&gt; * x&lt;sub&gt;2&lt;/sub&gt;, ..., a&lt;sub&gt;NM&lt;/sub&gt; * &lt;sub&gt;x2&lt;/sub&gt;]]&lt;/pre&gt;&lt;br /&gt;I want to map each row with each corresponding value of x.  This operation is not standard matrix multiplication, though I feel like it should be!&lt;br /&gt;&lt;br /&gt;I admit I slept in Linear Algebra class.  Thus I was a bit dumbfounded about how to express it using normal matrix multiplication.  While I could do it using LinAlg's mapping functions, I knew that it could be done because it was all linear transformations.  &lt;br /&gt;&lt;br /&gt;Luckily James Lawrence, who maintains &lt;a href="http://linalg.rubyforge.org/"&gt;LinAlg&lt;/a&gt; was emailing me, and asked me about it (thanks!).  He gave me some code that did it both ways.  After I read it, I slapped myself.&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;# using straight up matrix multiplication&lt;br /&gt;def calculate1(con)&lt;br /&gt;  DMatrix.diagonal(con*DMatrix.new(con.hsize,1,1)).inverse*con&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# using map&lt;br /&gt;def calculate2(con)&lt;br /&gt;  DMatrix.diagonal((con*DMatrix.new(con.hsize,1,1)).map { |e| 1.0/e })*con&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I wasn't sure which one was faster.  Maybe they'd be about the same.  Maybe doing matrix multiply would be slower because you'd have to go through all the multiplications.  Per James's suggestion, I benchmarked them, in the fine form of yak shaving.&lt;br /&gt;&lt;br /&gt;Run on a laptop 1.1GHz Pentium M, 758MBs, I did two experiments.  For one experiment, I kept the matrix at 800 rows, then I grew the columns.  Let's see what it looks like: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gHN52xJ15r0/SOVoPcLd2SI/AAAAAAAAAdY/1Mk7sLmmmfA/s1600-h/growing_cols.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_gHN52xJ15r0/SOVoPcLd2SI/AAAAAAAAAdY/1Mk7sLmmmfA/s320/growing_cols.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5252719154869164322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="text-align:center"&gt;time (secs) vs column size&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I should have labeled the axis in GnuPlot, but you'll live.  The y axis is the number of seconds, and the x axis is the column size.  Uninteresting, but nice to know it's linear.  The two functions aren't significantly different from each other in the amount of time that it takes.  I expected the map (calculate2) to be much faster since it didn't have to do all the multiplies.  oh well. &lt;br /&gt;&lt;br /&gt;I almost didn't run the second test, but it proved to be a bit more interesting.  This time I kept 800 columns and grew the number of rows.  Same axis.  Different graph:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_gHN52xJ15r0/SOVpSGTreLI/AAAAAAAAAdo/PIffmbWPAAY/s1600-h/growing_rows.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_gHN52xJ15r0/SOVpSGTreLI/AAAAAAAAAdo/PIffmbWPAAY/s320/growing_rows.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5252720300049266866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="text-align:center"&gt;time (secs) vs row size&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Whoa!  It's exponential.  Or quadratic.  I can't tell.  Anyway, anything curving up is bad news.  &lt;strike&gt;I suspect this might have something to do with &lt;a href="http://www.uoks.uj.edu.pl/docs/LAPACK/node19.html"&gt;row major/column major ordering&lt;/a&gt;.  C stores matrices row by row, whereas Fortran stores it column by column.&lt;/strike&gt;.  &lt;span style="font-style:italic;"&gt;Update&lt;/span&gt;: As corrected by James L., in the first experiment, growing columns will create more multiplies inside the diag() call, but the size of the diagonal will stay the same.  Growing the rows, however, will create less multiplies inside the diag() call, but each increase in row size will increase both dimensions of the resulting diagonal matrix, giving us n^2.  So it's quadratic.&lt;br /&gt;&lt;br /&gt;So what I went looking for wasn't what I meant to find.  But given that &lt;strike&gt;I've read about it before, it wasn't super interesting&lt;/strike&gt;it would have made sense had I thought about it, I guess it's not super surprising.  Let's see if we can use transpose to cut down on the time.  For one part, we'll grow the rows as before, and compare it to growing rows, but transposing the input then transposing the output, to get the same deal.  What's it look like:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gHN52xJ15r0/SOVqYttE8YI/AAAAAAAAAdw/NIpMYPhb-aw/s1600-h/growing_rows_with_transpose.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_gHN52xJ15r0/SOVqYttE8YI/AAAAAAAAAdw/NIpMYPhb-aw/s320/growing_rows_with_transpose.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5252721513215619458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="text-align:center"&gt;time(secs) vs row size&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is good news.  Even if transpose is an extra couple of manipulations, it saves us computation for bigger matrix sizes.  The most interesting part of the graph is the crossing of the two graphs.  If somehow, LinAlg (or any other package for that matter) can detect where that inflection point is going to be, it can switch off between the two.  The only thing I can think of is another package lying underneath doing sampling of each implementation randomly whenever a user calls the function to do interpolation of its growth curve, and then calculate the crossing analytically.  I don't currently know of any package that does this (or if it does, I don't know about it, cuz it already performs so well by doing the switch!)&lt;br /&gt;&lt;br /&gt;This was a nice little diversion from my side projects...a side project of side projects.  Back to learning about information gain and its ilk.  At least something came out of it.  I have a nice little experiment module that I can use to do other experiments.  And I spent way too much time on it not to post something...&lt;br /&gt;&lt;br /&gt;I share my code below, and you can run it if you want.  snippet!&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;# These are the experiments that I ran&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'experiment'&lt;br /&gt;&lt;br /&gt;require 'linalg'&lt;br /&gt;include Linalg&lt;br /&gt;&lt;br /&gt;def calculate1(con)&lt;br /&gt;  DMatrix.diagonal(con*DMatrix.new(con.hsize,1,1)).inverse*con&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def calculate2(con)&lt;br /&gt;  DMatrix.diagonal((con*DMatrix.new(con.hsize,1,1)).map { |e| 1.0/e })*con&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;DATA_PTS = 10&lt;br /&gt;MAX = 800&lt;br /&gt;MID = MAX / 2&lt;br /&gt;STEP = MAX / DATA_PTS&lt;br /&gt;&lt;br /&gt;# Growing columns&lt;br /&gt;Experiment::compare(1..MAX, STEP, &lt;br /&gt;                    proc { |col_size| DMatrix.rand(MID, col_size) },&lt;br /&gt;                    proc { |matrix, col_size|&lt;br /&gt;                      calculate1(matrix)&lt;br /&gt;                    },&lt;br /&gt;                    proc { |matrix, col_size|&lt;br /&gt;                      calculate2(matrix)&lt;br /&gt;                    })&lt;br /&gt;&lt;br /&gt;# Growing rows&lt;br /&gt;Experiment::compare(1..MAX, STEP, &lt;br /&gt;                    proc { |row_size| DMatrix.rand(row_size, MID) },&lt;br /&gt;                    proc { |matrix, row_size|&lt;br /&gt;                      calculate1(matrix)&lt;br /&gt;                    },&lt;br /&gt;                    proc { |matrix, row_size|&lt;br /&gt;                      calculate2(matrix)&lt;br /&gt;                    })&lt;br /&gt;&lt;br /&gt;# Growing rows, transposing&lt;br /&gt;Experiment::compare(1..MAX, STEP, &lt;br /&gt;                    proc { |row_size| DMatrix.rand(row_size, MID) },&lt;br /&gt;                    proc { |matrix, col_size|&lt;br /&gt;                      calculate1(matrix)&lt;br /&gt;                    },&lt;br /&gt;                    proc { |matrix, col_size|&lt;br /&gt;                      calculate1(matrix.transpose).transpose&lt;br /&gt;                    })&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;# Experiment.rb - perform timed experiments across on one dimension&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'gnuplot'&lt;br /&gt;&lt;br /&gt;# Experiment is a module where you can use to plot and benchmark pieces of code&lt;br /&gt;# and plot it on a gnuplot&lt;br /&gt;#&lt;br /&gt;# &lt;br /&gt;module Experiment&lt;br /&gt;  class &lt;&lt; self&lt;br /&gt;&lt;br /&gt;    def timer&lt;br /&gt;      start_time = Time.now&lt;br /&gt;      yield&lt;br /&gt;      diff_time = Time.now - start_time&lt;br /&gt;      puts "That run took #{diff_time} seconds"&lt;br /&gt;      return diff_time&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    # takes range to try and the step resolution of the range and runs &lt;br /&gt;    # the benchmark_block with each of the different ranges. &lt;br /&gt;    # the init_proc only gets run once during setup.&lt;br /&gt;    #&lt;br /&gt;    # Experiment::benchmark((1..50), 10, &lt;br /&gt;    #            proc { |col_size| DMatrix.rand(500, col_size)},&lt;br /&gt;    #            proc { |matrix, col_size| ProbSpace.new(matrix).entropy })&lt;br /&gt;    def benchmark(range, resolution, init_proc, benchmark_block)&lt;br /&gt;      xs, ts = [], []&lt;br /&gt;      range.step(resolution) do |x_size|&lt;br /&gt;        object = init_proc.call(x_size)&lt;br /&gt;        xs &lt;&lt; x_size&lt;br /&gt;        ts &lt;&lt; timer { benchmark_block.call(object, x_size) }&lt;br /&gt;      end&lt;br /&gt;      plot(xs, ts)&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    # same idea as benchmark, but does two at the same time.  So &lt;br /&gt;    # it takes an init_proc to initialize the experiment, &lt;br /&gt;    # and two different procs, standard and comparison, to run &lt;br /&gt;    # for each step in the range at the given resolution.&lt;br /&gt;    #&lt;br /&gt;    # Experiment::benchmark((1..50), 10, &lt;br /&gt;    #            proc { |col_size| DMatrix.rand(500, col_size)},&lt;br /&gt;    #            proc { |matrix, col_size| ProbSpace.new(matrix).entropy1 },&lt;br /&gt;    #            proc { |matrix, col_size| ProbSpace.new(matrix).entropy2 })&lt;br /&gt;    def compare(range, resolution, init_proc, &lt;br /&gt;                standard_block, comparison_block)&lt;br /&gt;      xs, s_ts, c_ts = [], [], []&lt;br /&gt;      range.step(resolution) do |x_size|&lt;br /&gt;        object = init_proc.call(x_size)&lt;br /&gt;        xs &lt;&lt; x_size&lt;br /&gt;        s_ts &lt;&lt; timer { standard_block.call(object, x_size) }&lt;br /&gt;        c_ts &lt;&lt; timer { comparison_block.call(object, x_size) }&lt;br /&gt;        puts "#{x_size} = standard : comparison :: #{s_ts.last} : #{c_ts.last} secs"&lt;br /&gt;      end&lt;br /&gt;      plot(xs, s_ts, c_ts)&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def plot(x, *ys)&lt;br /&gt;      Gnuplot.open do |gp|&lt;br /&gt;        Gnuplot::Plot.new(gp) do |plot|&lt;br /&gt;          ys.each do |y|&lt;br /&gt;            plot.data &lt;&lt; Gnuplot::DataSet.new([x, y]) do |ds|&lt;br /&gt;              ds.with = "linespoints"&lt;br /&gt;              ds.notitle&lt;br /&gt;            end&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-1743270020220645859?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=IeBO9nnC"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=k4fMRtiU"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=4m4isjMt"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=4m4isjMt" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/j8SGcIlmOV4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1743270020220645859/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/09/benchmarking-row-multiply.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1743270020220645859?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1743270020220645859?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/j8SGcIlmOV4/benchmarking-row-multiply.html" title="Benchmarking row multiply in Ruby's Linalg" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_gHN52xJ15r0/SOVoPcLd2SI/AAAAAAAAAdY/1Mk7sLmmmfA/s72-c/growing_cols.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/09/benchmarking-row-multiply.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMGQX06cCp7ImA9WxRRFkg.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-1083113603338583811</id><published>2008-09-29T20:36:00.000-07:00</published><updated>2008-09-28T18:40:20.318-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-28T18:40:20.318-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="library" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>Somebody knows Shoes</title><content type="html">I'm a fairly late adopter compared to some of you.  When &lt;a href="http://shoooes.net/"&gt;Shoes&lt;/a&gt; came out, I had followed it, but never tried it.  It's been at least 8 months now, and I finally got around to it.  I guess I don't really try something out unless I have a use for it in my mind.  Still waiting for that Haskell project...&lt;br /&gt;&lt;br /&gt;Anyway, trying out Shoes was...easy.  Outside of compiling it, actually.  I take that back.  Once I read the README and figured out what packages I needed, it was easy.  Even easier when I found the executables.  Running the sample code was...easy.  And trying out your own app...you guessed it...even easier.  It helps that there's a ton of examples and documentation.  Makes me think that when programming, you should keep the API of your code in mind, so that it's easy to use after you've implemented it. &lt;br /&gt;&lt;br /&gt;Two things strike me immediately.  _why took his ability to make DSL in Ruby to heart.  I don't have to think about the buffering, cursor positions, etc.  Even better, the functions are orthogonal and consistent.  &lt;br /&gt;&lt;br /&gt;You can not only move shapes around to follow your mouse, but also widgets, like buttons.&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;Shoes.app(:width =&gt; 300, :height =&gt; 300 do&lt;br /&gt;  background snow&lt;br /&gt;  @o = stack do&lt;br /&gt;    button("Message") { alert("Sent!") }&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  motion do |x,y|&lt;br /&gt;    @o.move width - x, height - y&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;Motion gets executed whenever your mouse moves around on the Shoes screen.  So you can have a button dancing opposite to your mouse.  Another surprising thing is that an app is structured like a webpage, and different pages have urls.  And routing is declared in the app block itself!  And not only that, it takes regexs&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;class Dictionary &lt; Shoes&lt;br /&gt;  url '/', :index&lt;br /&gt;  url '/(\w+)', :word&lt;br /&gt;&lt;br /&gt;  def index&lt;br /&gt;    stack do&lt;br /&gt;      title "Enter a Word"&lt;br /&gt;      @word = edit_line&lt;br /&gt;      button "OK" do &lt;br /&gt;        visit "/#{@word.text}"&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def word(string)&lt;br /&gt;    stack do&lt;br /&gt;      para "No definition found for #{string}. ",&lt;br /&gt;        "Sorry this doesn't actually work."&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Shoes.app&lt;/pre&gt;&lt;br /&gt;I'm not sure how far this sort of thing can go when building more complex GUIs, but so far, it seems pretty promising.  There were a couple things that were broken on Ubuntu, however.  I couldn't get margins to work, as well as rounded corners:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;Shoes.app(:margin =&gt; 20) do&lt;br /&gt;  background red, :radius =&gt; 12&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;Boo.  Rounded corners would have been exciting.&lt;br /&gt;&lt;br /&gt;Well, try it out and see if you like it.  There's &lt;a href="http://the-shoebox.org/"&gt;lots of neat things people have built&lt;/a&gt; with Shoes already.  &lt;br /&gt;&lt;br /&gt;I, on the other hand, just built a prototype.  Nothin to see here folks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-1083113603338583811?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=QMfehwsv"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=Q77EMcBK"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=4cslaLtP"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=4cslaLtP" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/-QDCBH1CjCc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/1083113603338583811/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/09/somebody-knows-shoes.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1083113603338583811?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/1083113603338583811?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/-QDCBH1CjCc/somebody-knows-shoes.html" title="Somebody knows Shoes" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/09/somebody-knows-shoes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4HQHo-cCp7ImA9WxRREko.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-4105828799659580176</id><published>2008-09-24T10:38:00.000-07:00</published><updated>2008-09-24T10:38:51.458-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-24T10:38:51.458-07:00</app:edited><title>EmacsWiki: Moving The Ctrl Key</title><content type="html">&lt;a href="http://www.emacswiki.org/cgi-bin/wiki/MovingTheCtrlKey"&gt;EmacsWiki: Moving The Ctrl Key&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I put off doing this for too long now.  I have to admit, if there are settings that I can do in a GUI without mucking around in a config file, I'd do it.  Ubuntu has made it easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-4105828799659580176?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=pzSWkcbW"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=A2nPtzNK"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=3aVKb6Gr"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=3aVKb6Gr" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/dOnWuu5C7Yk" height="1" width="1"/&gt;</content><link rel="related" href="http://www.emacswiki.org/cgi-bin/wiki/MovingTheCtrlKey" title="EmacsWiki: Moving The Ctrl Key" /><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/4105828799659580176/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/09/emacswiki-moving-ctrl-key.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/4105828799659580176?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/4105828799659580176?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/dOnWuu5C7Yk/emacswiki-moving-ctrl-key.html" title="EmacsWiki: Moving The Ctrl Key" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/09/emacswiki-moving-ctrl-key.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUBRHc_fip7ImA9WxRREUk.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-9212276859769173140</id><published>2008-09-22T21:28:00.000-07:00</published><updated>2008-09-22T22:04:15.946-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-22T22:04:15.946-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><title>Installing Ruby's linalg in Ubuntu</title><content type="html">Ruby has a project for &lt;a href="http://rubyforge.org/frs/?group_id=273"&gt;download&lt;/a&gt; called &lt;a href="http://linalg.rubyforge.org/"&gt;linalg&lt;/a&gt; that exposes the LAPACK functions in Ruby.  &lt;a href="http://www.netlib.org/lapack/"&gt;LAPACK&lt;/a&gt; is a set of routines written in Fortran to do Linear Algebra operations.  Now, before you cry foul about Fortran, LAPACK is used in a lot of places, and it's pretty damn old and has held up over the years.  &lt;br /&gt;&lt;br /&gt;The linalg package just updated about two weeks ago, first since 2004, so it has some updates.  Unfortunately, there's no easy gem to install.  You'll have to download the tar, and then run &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo ruby install.rb&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Of course, you'll run into some problems, unless you have other packages installed:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo apt-get install lapack3 lapack3-dev libg2c0-dev &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Don't worry, if you don't like it, you can run uninstall.  Read INSTALL file for more directions.&lt;br /&gt;I use to wonder how people knew which packages to look for.  Apparently, you look at the output and see what files the configure is crapping out on.  Then use apt-file to search for which package the file is in.  It's one of those basic things that seems not mentioning in hindsight.  Like calling "source ~/.bashrc" after you've edited your bash files.  No one ever mentions that.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sudo apt-get install apt-file&lt;br /&gt;sudo apt-file update&lt;br /&gt;apt-file list g2c.h&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Knowing that, you'll know how to fish, and I'll not post how to install stuff in the future.&lt;br /&gt;&lt;br /&gt;tip!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-9212276859769173140?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=VGyFCzmC"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=8Cn5oQaN"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=XAJ17RGW"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=XAJ17RGW" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/U1ySaRAYc64" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/9212276859769173140/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/09/installing-rubys-linalg-in-ubuntu.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/9212276859769173140?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/9212276859769173140?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/U1ySaRAYc64/installing-rubys-linalg-in-ubuntu.html" title="Installing Ruby's linalg in Ubuntu" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/09/installing-rubys-linalg-in-ubuntu.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08NRXk8cCp7ImA9WxRREU8.&quot;"><id>tag:blogger.com,1999:blog-16002962.post-6191992446581734529</id><published>2008-09-12T10:00:00.000-07:00</published><updated>2008-09-22T15:18:14.778-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-22T15:18:14.778-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="snippet" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="algorithm" /><category scheme="http://www.blogger.com/atom/ns#" term="cilk" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>Algorithm always matters, even when parallel</title><content type="html">I've finally had some time to start looking at things that looked interesting to me.  One of the things that I started looking at was parallel algorithms.  &lt;br /&gt;&lt;br /&gt;I was reading Hacker News, and I saw some link that lead me to discover &lt;a href="http://supertech.csail.mit.edu/cilk/"&gt;Cilk&lt;/a&gt;, a C extension to easily make parallel programs.  &lt;br /&gt;&lt;pre name="code" class="c"&gt;thread int fib(int n) {&lt;br /&gt;  if (n &lt; 2)&lt;br /&gt;    return n;&lt;br /&gt;  else {&lt;br /&gt;    cont int x, y;&lt;br /&gt;    x = spawn fib (n-2);&lt;br /&gt;    y = spawn fib (n-1);&lt;br /&gt;    sync;&lt;br /&gt;    return x+y;&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This was the example given for calculating the Fibonacci sequence in parallel.  This is the standard mathematical way to define it, and it looks clean enough.  So instead of trying it out in Cilk, I fired up Erlang to try my hand at doing a port.  I found it a little bit difficult because while you can easily spawn processes in Erlang, there was no quick way for the parent process to wait/sync/join child processes and get their results.  Since that was besides the point of the exercise, I fired up Ruby, even though they had a slow Threading library (which is suppose to be fixed in 1.9, plus Fibers!)  I'll do with it Erlang some other time.&lt;br /&gt;&lt;br /&gt;First I wrote the threaded version to mimic the Cilk code:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;def fib_threaded(n)&lt;br /&gt;  if n &lt; 2&lt;br /&gt;    return 1&lt;br /&gt;  else&lt;br /&gt;    threads = []&lt;br /&gt;    x = 0&lt;br /&gt;    y = 0&lt;br /&gt;    threads &lt;&lt; Thread.new(n - 2) { |i| x = fib_threaded(i) }&lt;br /&gt;    threads &lt;&lt; Thread.new(n - 1) { |i| y = fib_threaded(i) }&lt;br /&gt;    threads.each { |thread| thread.join }&lt;br /&gt;    return x + y&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;I don't have a multi-core processor.  I'm on a 3 year old 1GHz laptop.  At a mere fib(18), it was taking about 21 seconds to run.  To see if there was a difference, I wrote a serial version.&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;def fib_serial(n)&lt;br /&gt;  n &lt; 2 ? 1 : fib_serial(n - 1) + fib_serial(n - 2)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This one ran much much faster.  It took about 0.02594 seconds.  At this point, it's probably the overhead of thread creation that's making it take so long to run.  Maybe with green threads or lightweight threads, the threaded version would run much faster.  That makes me want to try it in Erlang just to compare.  But wtf, adding shouldn't take that long, even if it is 0.025 seconds&lt;br /&gt;&lt;br /&gt;When I thought about it, it was an efficient algorithm:  there's a lot of wasted cycles.  In order to compute f(n), you have to calculate f(n - 1) and f(n - 2) in separate threads.  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;The f(n - 1) thread requires it to spawn two more threads to compute f(n - 2) and f(n - 3).&lt;/li&gt;&lt;li&gt;The f(n - 2) thread requires it to spawn two more threads to compute f(n - 3) and f(n - 4).&lt;/li&gt;&lt;/ul&gt;  Notice that both the threads for f(n - 1) and f(n - 2) have to &lt;span style="font-weight:bold;"&gt;spawn two different threads to calculate f(n - 3)&lt;/span&gt;.  And since this algorithm has no way for threads to share their results, they have to recompute values all over again.  The higher the n, the worse the problem is, exponentially. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gHN52xJ15r0/SMH56X5NN4I/AAAAAAAAAZk/F4D-8gGKR7w/s1600-h/fib.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_gHN52xJ15r0/SMH56X5NN4I/AAAAAAAAAZk/F4D-8gGKR7w/s320/fib.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242746222477653890" /&gt;&lt;/a&gt;&lt;br /&gt;To calculate the speedup given to an algorithm by adding more processors, you calculate the amount of total work required and divide it by the span of the parallel graph.  If that didn't make sense, read &lt;a href="http://supertech.csail.mit.edu/cilk/lecture-1.ppt"&gt;lecture one for Cilk&lt;/a&gt;, which is where the diagram comes from.  So for fib(n)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Twork = O(n^2)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The total amount of work is the total number of processes spawned.  Since every f(n) recursively spawns two other processes, it's about n^2 processes.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Tspan = O(ln n)&lt;/pre&gt;&lt;br /&gt;The total span is how many nodes a particular calculation traverses.  A la the diagram, it's about the height of the tree, so that's about ln n nodes.&lt;br /&gt;&lt;br /&gt;Therefore, for fib(n), the processor speed up is at most:&lt;br /&gt;&lt;br /&gt;Tw / Ts = O(n^2) / O(ln n)&lt;br /&gt;&lt;br /&gt;I don't know of any reductions for that off the top of my head, but you can see that the processor speedup gain grows somewhere in between n and n^2.  On one hand, it means this algorithm can benefit from speedups by adding up to somewhere between n and n^2 processors.  However, that also means that to make this algorithm go as fast as it can to process fib(1000), you need more than 1000 processors to make it worthwhile.  Not so good for a parallel program that's just doing addition.&lt;br /&gt;&lt;br /&gt;As a last version, I wrote one that computed the Fibonacci from 0 up to n, and keeping the total as I go along, instead of the recursive version that has to work its way n back down to zero.&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;def fib_loop(n) &lt;br /&gt;  sequence = [1, 1]&lt;br /&gt;  if n &lt; 2&lt;br /&gt;    sequence[n]&lt;br /&gt;  else&lt;br /&gt;    sequence = (1..n-1).inject(sequence) do |t, e|&lt;br /&gt;      t &lt;&lt; (t[-2] + t[-1])&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  sequence[-1]&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's not space effective since I wrote it quickly, but this beat the pants off the other two running at 0.00014 seconds.  As you can see, you're not recalculating any f(n) more times than you need to.  &lt;br /&gt;&lt;br /&gt;I wish Cilk had a better first example to parallel programs.  Given that the guy making Cilk is the same guy that co-wrote &lt;a href="http://www.catonmat.net/blog/mit-introduction-to-algorithms-part-one/"&gt;the famous mobile book for algorithms&lt;/a&gt;, I guess I was surprised.  However, it was a fun exercise, and made me think about algorithms again.  &lt;br /&gt;&lt;br /&gt;I'll find some other little project that requires me to write in Erlang, rather than falling back on the comfortable Ruby.  snippet!  Below if you want to run it yourself.  &lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;#!/usr/bin/ruby&lt;br /&gt;# rubinacci.rb by Wilhelm&lt;br /&gt;&lt;br /&gt;def fib_threaded(n)&lt;br /&gt;  if n &lt; 2&lt;br /&gt;    return 1&lt;br /&gt;  else&lt;br /&gt;    threads = []&lt;br /&gt;    x = 0&lt;br /&gt;    y = 0&lt;br /&gt;    threads &lt;&lt; Thread.new(n - 2) { |i| x = fib_threaded(i) }&lt;br /&gt;    threads &lt;&lt; Thread.new(n - 1) { |i| y = fib_threaded(i) }&lt;br /&gt;    threads.each { |thread| thread.join }&lt;br /&gt;    return x + y&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def fib_serial(n)&lt;br /&gt;  n &lt; 2 ? 1 : fib_serial(n - 1) + fib_serial(n - 2)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def fib_loop(n) &lt;br /&gt;  sequence = [1, 1]&lt;br /&gt;  if n &lt; 2&lt;br /&gt;    sequence[n]&lt;br /&gt;  else&lt;br /&gt;    sequence = (1..n-1).inject(sequence) do |t, e|&lt;br /&gt;      t &lt;&lt; (t[-2] + t[-1])&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  sequence[-1]&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def run(&amp;algorithm)&lt;br /&gt;  start_time = Time.now&lt;br /&gt;  integer = 18&lt;br /&gt;  answer = algorithm.call(integer)&lt;br /&gt;  elapsed = Time.now - start_time&lt;br /&gt;  &lt;br /&gt;  puts "Fib(#{integer}) = #{answer}"&lt;br /&gt;  puts "Total elapsed time: #{elapsed} seconds"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;puts "threaded:"&lt;br /&gt;run do |integer|&lt;br /&gt;  fib_threaded(integer)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;puts "serial:"&lt;br /&gt;run do |integer|&lt;br /&gt;  fib_serial(integer)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;puts "loop:"&lt;br /&gt;run do |integer|&lt;br /&gt;  fib_loop(integer)&lt;br /&gt;end&lt;/textarea&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16002962-6191992446581734529?l=webjazz.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=THOnLL04"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=V4CfWQs0"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?d=52" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?a=udZ013uk"&gt;&lt;img src="http://feeds.feedburner.com/~f/TheWebAndAllThatJazz?i=udZ013uk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheWebAndAllThatJazz/~4/ib4qHI7Oh1k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://webjazz.blogspot.com/feeds/6191992446581734529/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://webjazz.blogspot.com/2008/09/algorithm-always-matters-even-when.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/6191992446581734529?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/16002962/posts/default/6191992446581734529?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheWebAndAllThatJazz/~3/ib4qHI7Oh1k/algorithm-always-matters-even-when.html" title="Algorithm always matters, even when parallel" /><author><name>Wilhelm</name><uri>http://www.blogger.com/profile/03696320260631888445</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="03115708320816698972" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_gHN52xJ15r0/SMH56X5NN4I/AAAAAAAAAZk/F4D-8gGKR7w/s72-c/fib.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webjazz.blogspot.com/2008/09/algorithm-always-matters-even-when.html</feedburner:origLink></entry></feed>
