<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1358941065293307736</id><updated>2012-02-16T09:34:57.943-08:00</updated><category term='ruby'/><category term='amqp'/><category term='technology'/><category term='twisted'/><category term='development'/><category term='maven'/><category term='predictions'/><category term='github'/><category term='creative commons'/><category term='microblogging'/><category term='ipython'/><category term='browsers'/><category term='messaging middleware'/><category term='NaNoWriMo'/><category term='aaku'/><category term='novel'/><category term='frameworks'/><category term='git'/><category term='opengl'/><category term='python'/><category term='hot chip'/><category term='rabbitmq'/><category term='science fiction'/><category term='code'/><category term='launchpad'/><category term='humor'/><category term='facebook'/><category term='java'/><category term='programming'/><category term='graphics'/><category term='rants'/><category term='python magazine'/><category term='music'/><category term='rcs'/><category term='hate'/><category term='communication'/><category term='concurrency'/><category term='seo'/><category term='bitbucket'/><category term='internet marketing'/><category term='onion news'/><category term='software'/><category term='ie6'/><category term='twitter'/><category term='mac'/><category term='puzzles'/><category term='marketing'/><category term='microsoft'/><category term='social media'/><category term='pyglet'/><category term='fiction'/><category term='mercurial'/><category term='competitive website  analysis'/><category term='google'/><title type='text'>multum im parvo</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-2930257729768839032</id><published>2011-09-10T13:10:00.000-07:00</published><updated>2011-10-21T10:13:48.936-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='rcs'/><category scheme='http://www.blogger.com/atom/ns#' term='launchpad'/><category scheme='http://www.blogger.com/atom/ns#' term='bitbucket'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='rants'/><title type='text'>The Code Hosting Site Holy War (I didn't know about)</title><content type='html'>&lt;p&gt;Apparently there's been a mighty battle going on between code hosting sites on the Internetz and now from the clouds of dust a mighty and worthy victor has emerged wielding a sword and proclaiming victory ... Or it least this is the new meme I've observed. News to me. So now I need to understand what this holy war is even about ...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;small&gt;(Let me first say that I'm pretty much a git/github fanboy at this point. (Although git can be damn stink to learn.) But I don't buy into this notion that github is supreme and all other sites are crap ... or more importantly that development communities should be monolithic in what they use to revision teh codez.)&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;quote&gt;Oh I do want to know what mysterious code hosting war has just been fought and apparently concluded with a victor ...&lt;/quote&gt;&lt;br /&gt;&lt;p&gt;Who was even on the battlefield fighting for their dominance of the Internetz--I'm guessing mostly github, launchpad and bitbucket. So.... Github Wins what? If we mean popularity contest, I agree. If by supreme awesomeness and superiority in implementation, I'm undecided right now.  Github is very nice and generally I advocate it because &lt;strong&gt;it is&lt;/strong&gt; the most popular (out of similar sites) no doubt, so it's a good way to attract developers, and I'm much more keen on git's branching model (vs. hg and bzr). In general, though, I'm a polyglot when it comes to revisioning tools and use bzr, hg, git and svn through the week depending on what project I'm hacking on.  I like being able to use and learn concepts behind all of git, hg, and bzr, but I'm not so much a fan of legacy options like svn which just make experimentation with code &lt;strong&gt;and&lt;/strong&gt; preserving (and possibly merging) revision history from those experiments a complete pain in the ass ... sorry Subversion stalwarts, you're advocating a &lt;a href="http://www.youtube.com/watch?v=4XpnKHJAok8"&gt;"misguided rewrite of CVS"&lt;/a&gt; to paraphrase.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Concerning the code hosting sites, let me say some ill words about them all. Because they each have a few grams of suck in them and even to some extent deserve the sophomoric insults and rewordings like shithub, shitbucket or launchcrap. So let me unload some hate towards each in fairness.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Github (aka Shithub)&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;I think GitHub needs some improvements towards receiving the Awesome Supremacy award from the Drew Smathers Buckshot Society of Fringe Opinions on Software Awesomeness:&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;Urls like &lt;em&gt;http://foo/theuser/theproject&lt;/em&gt; are an insult to what open source means. Be project-centric like Launchpad: "theuser" doesn't belong in the url. (The ship has already sailed ... alas)&lt;br /&gt;  &lt;li&gt;Work on git core to integrate easily with github itself (again: where's my "git clone github:someproject" a la "bzr branch lp:someproject" - again being "project-centric" makes this easier)&lt;br /&gt;  &lt;li&gt;Build tools more auxiliary tasks integrated with the main UI (again like launchpad does) to attract contribution from non-developers: translations, project roadmaps, etc. (Right now all the CTAs are basically: "code, code, code, code, more code"). &lt;a href="http://sheddingbikes.com/posts/1299555462.html"&gt;Some people on the internet&lt;/a&gt; think this is all a code hosting site should be. &lt;a href="http://b.lvh.cc/why-do-people-hate-launchpad-so-much"&gt;Others extoll the benefits of a rock solid issue tracker&lt;/a&gt; which is a useful technology that really stems beyond just software development.&lt;/p&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h4&gt;Bitbucket (aka Shitbucket)&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Bitbucket too needs a little slap around before getting a Supreme Awesomeness award:&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;Your ticket tracker is total dirt. Launchpad open sourced their's so maybe there's some low-hanging fruit to integrate and reskin.&lt;br /&gt;  &lt;li&gt;Just keep copying github like you did from the start: bitbucket pages, edit commits and contribute in. the. brower., something like gist.github, also. Don't worry, you and Github are both run by a bunch of hipsters, so a patent war is impossible ... right?  (I'm watching you hipsters, keep it classy) &lt;br /&gt;  &lt;li&gt;Ditto on Github critique (1) - your urls should have been project-centric.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h4&gt;Launchpad (aka Launchcrap)&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;The most common complaint against launchpad has perhaps been against its somewhat confusing UI.&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt; UX, UX, UX, UX. Seriously. I've got this dude who can make a big a big ass button that says CODE and people will know that's how to get to the codez. On the cheap too.  For a little extra he can reskin loggerhead to make it look like the same site ... and maybe even pull it inline that with the core navigation.&lt;br /&gt;  &lt;li&gt;Also, just copy a lot of what github does except the obviously inferior parts (ticket tracker, etc.). So some good things to emulate: "launchpad pages", comments on commits, etc.  Canonical is part enlightened capitalist, part hipster, so again I think we can dodge any patent bullets.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h4&gt;After the war ...&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Alas, finally, if there really was a war going on, I'm hoping for some lingering skirmishes that will ensure one thing: If there is an end-all, let it be to code hosting sites and not revisioning tools. My DVCS Polyglot Party is amassing weapons and fortifying our bunkers on the fringe of this vast battlefield to fight towards this end. Let there be a &amp;lt;any old dvcs&amp;gt;.com to succeed github.com where people will share code, hack on code, merge code using any reasonable tool they prefer (darcs, bzr, hg, git, ...) all seamlessly, and with not a thought needed as to what's happening behind the scenes on this RCS-agnostic server. Such a sucessor would indeed be a far worthier victor in this war.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-2930257729768839032?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/2930257729768839032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2011/09/code-hosting-site-holy-war-i-didnt-know.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2930257729768839032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2930257729768839032'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2011/09/code-hosting-site-holy-war-i-didnt-know.html' title='The Code Hosting Site Holy War (I didn&apos;t know about)'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-1688549579068348361</id><published>2011-02-17T07:58:00.001-08:00</published><updated>2011-02-17T08:14:19.406-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python List Comprehensions are not For-loops</title><content type='html'>I've too frequently seen Python code that looks like this:&lt;div&gt;&lt;pre&gt;&lt;br /&gt;[ dosomething(v) for v in items ]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Normally one would write a plain old for-loop:&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;for v in items:&lt;br /&gt;    dosomething(v)&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You should always use the latter - not a list comprehension. Why?&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;A simple for-loop is easier to read&lt;/li&gt;&lt;li&gt;The for-loop does not need to allocate memory for a list that's not even used&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;The second point is the most important. To repeat the title of this post: A list comprehension is not a for-loop. In worser cases, items may be tied to a database cursor, for example, and could return an arbitrary number of items, so we could potentially allocate excess memory for a very large result set - and all to support a less readable idiom for looping over the result set.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, don't be tempted by the dark side and confuse list comprehensions with for-loops and your code will be awesome.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-1688549579068348361?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/1688549579068348361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2011/02/python-list-comprehensions-are-not-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1688549579068348361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1688549579068348361'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2011/02/python-list-comprehensions-are-not-for.html' title='Python List Comprehensions are not For-loops'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-5575120350196080932</id><published>2010-07-23T18:57:00.001-07:00</published><updated>2010-07-23T18:57:36.312-07:00</updated><title type='text'>2012: Personal review</title><content type='html'>Dude, that movie sucked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-5575120350196080932?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/5575120350196080932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2010/07/2012-personal-review.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/5575120350196080932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/5575120350196080932'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2010/07/2012-personal-review.html' title='2012: Personal review'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-69938923200442752</id><published>2010-06-21T08:17:00.000-07:00</published><updated>2010-06-21T08:24:38.586-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ipython'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>IPython and libreadline Don't Work On Mac OSX ... Unless</title><content type='html'>This annoyed for quite some time: a default installation of IPython (even sometimes with python libreadline bindings installed) doesn't work to smoothly: IPython apparently loads libedit (the BSD variant) which garbles your text when you type past so many characters and doesn't support contextual history completion, etc.  I was able to solve this problem with the following:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;$ sudo pip uninstall readline ipython&lt;/div&gt;&lt;div&gt;$ sudo easy_install readline ipython&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that the second step should be "easy_install" - not "pip".&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-69938923200442752?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/69938923200442752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2010/06/ipython-and-libreadline-dont-work-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/69938923200442752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/69938923200442752'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2010/06/ipython-and-libreadline-dont-work-on.html' title='IPython and libreadline Don&apos;t Work On Mac OSX ... Unless'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6526597383531226310</id><published>2010-02-02T09:17:00.001-08:00</published><updated>2010-02-02T09:17:01.778-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='ie6'/><category scheme='http://www.blogger.com/atom/ns#' term='browsers'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>Ding Dong, The (IE6) Witch is (almost) dead</title><content type='html'>&lt;div class='posterous_autopost'&gt;I felt my office vibrating this morning but I soon realized it must be reverberations of the collective sigh of web developers all across the globe following &lt;a href="http://finance.yahoo.com/q?s=GOOG" title="NASDAQ: GOOG" class="zem_slink" rel="stockexchange"&gt;Google&lt;/a&gt;&amp;#39;s announcement of dropping support for &lt;a href="http://en.wikipedia.org/wiki/Internet_Explorer_6" title="Internet Explorer 6" class="zem_slink" rel="wikipedia"&gt;IE6&lt;/a&gt;.  Apparently the French and German governments are &amp;quot;[advising] &lt;span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: 16px;"&gt;citizens to switch to a different browser until the IE6 issue had been resolved&amp;quot; according to at least &lt;a href="http://www.techradar.com/news/internet/google-phases-out-ie6-support-667414"&gt;one source&lt;/a&gt;.  I find that quite absurd considering the implication that someone might install a different browser and then switch back to &amp;quot;good old&amp;quot; IE6 ;)&lt;/span&gt;&lt;p /&gt;&lt;div&gt;&lt;span style="font-size: 12px; line-height: 16px;"&gt;It&amp;#39;s depressing to note that IE6 still comprises about 9% of the browser market; so a web developer still has to fret over writing workarounds to account for about 1 out of 10 of their users.  Out of all the theories I&amp;#39;ve heard over why people still use this browser (dating back to 2001), the &lt;a href="http://www.quirksmode.org/blog/archives/2009/06/state_of_the_br_1.html"&gt;legacy corporate Intranet one&lt;/a&gt; is the most convincing.  I always new in my heart of hearts that &lt;a href="http://en.wikipedia.org/wiki/ActiveX" title="ActiveX" class="zem_slink" rel="wikipedia"&gt;ActiveX&lt;/a&gt; for the most part was a bad idea.  &lt;br /&gt; &lt;/span&gt;&lt;p /&gt;&lt;p /&gt;&lt;/div&gt;Related articles by Zemanta&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://news.bbc.co.uk/go/rss/-/2/hi/technology/8488751.stm"&gt;Google phases out support for IE6&lt;/a&gt; (&lt;a href="http://news.bbc.co.uk"&gt;news.bbc.co.uk&lt;/a&gt;)&lt;/li&gt; &lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://online.wsj.com/article/SB10001424052748704541004575011331741244868.html"&gt;Microsoft&amp;#39;s Browser Under Fire In Europe&lt;/a&gt; (&lt;a href="http://online.wsj.com"&gt;online.wsj.com&lt;/a&gt;)&lt;/li&gt; &lt;/ul&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://quaternion.posterous.com/ding-dong-the-ie6-witch-is-almost-dead"&gt;Quaternion's Mind Dump&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-6526597383531226310?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6526597383531226310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2010/02/ding-dong-ie6-witch-is-almost-dead.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6526597383531226310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6526597383531226310'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2010/02/ding-dong-ie6-witch-is-almost-dead.html' title='Ding Dong, The (IE6) Witch is (almost) dead'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-8364637425597092867</id><published>2010-01-18T18:26:00.001-08:00</published><updated>2010-01-18T18:26:46.140-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='creative commons'/><category scheme='http://www.blogger.com/atom/ns#' term='fiction'/><category scheme='http://www.blogger.com/atom/ns#' term='science fiction'/><title type='text'>The Cell</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;div class="zemanta-img" style="margin-top: 1em; margin-right: 1em; margin-bottom: 1em; margin-left: 1em; float: right; display: block;"&gt;&lt;a href="http://commons.wikipedia.org/wiki/Image:1e15m_comparison_light_year_month_comet_1910a1.png"&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/1e15m_comparison_light_year_month_comet_1910a1.png/300px-1e15m_comparison_light_year_month_comet_1910a1.png" height="225" alt="Comparison of sizes of lengths with order of m..." width="300" style="border: none; display: block;" /&gt;&lt;/a&gt;&lt;p class="zemanta-img-attribution" style="font-size: 0.8em;"&gt; Image via &lt;a href="http://commons.wikipedia.org/wiki/Image:1e15m_comparison_light_year_month_comet_1910a1.png"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;div style="font-family: Times; font-size: medium;"&gt;&lt;div style=""&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;4215 Fre 41 (Memoirs and Reflections | by Aubsoluone Jikro 89th)&lt;/div&gt;&lt;p /&gt;A sister.  The cold flesh. Birthed and on the table glowing in an effusive, self-contained bulbous cobweb of light, pulsating white, then blue, white, then blue ...&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;     This is the first memory of life.  The decanter spilling her across the table, she breathes and tries to understand life, immediately she is a cold wet slimy puppet; in days a beautiful baby; in months a crawling sentient being; and in years a fellow worker in the hull, a friend.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    She grows and learns to know and understand like I the laws of our very finite world: the size of only 10,500 cabinets interconnected like tunnels or stitched together with walls beat open to form small quarters - sleeping rooms, mess rooms, equipment access closets ...&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    We are here floating to our lineage&amp;#39;s death.  Marooned in a seemingly infinite vacuum of space.&lt;br /&gt;&lt;/div&gt;&lt;p /&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;2945 Jyr 33 (Recollections of the meteor field incident | Eschenon Rik 1st)&lt;/div&gt;&lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;My age is 23 years and 17 months, I believe.  There should be others here to talk with and help with my duties in the hull, but I am alone.  I am literate but could not gauge the degree of my intellectual achievements good or bad having no living, non-artificial intellectual peer to compare myself to.  I can read at a rate of 3,000 words a minute and can record approximately 1,000 words every five minutes, or 200 words a minute on average.  None of the literature I&amp;#39;ve read in the library affirms my reading and writing capabilities as either success or failure in an intellectual endeavor.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    I only have one endeavor in life.  To activate the embryo cells and begin decanting members of my genetic family and race and preserve what little I remember of the spoken language and culture from my brief three years of contact with living members of my genetic family and race.&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    The ship was traveling through what I now believe to be a meteor field.  Comm system was the first to be disabled by impact and if there were any transmissions they were not recorded in the library.  I have already consumed the entirety of the library.  I have memorized nearly on quarter of it as well.  There are no traces of any trasmission.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    (The written literature in the library&amp;#39;s hull was of one differing from my family&amp;#39;s spoken tongue.  The remaining two drones on board were programmed to speak my native tongue, so I spoke that bastardized perhaps with the vocabulary I absorbed most through reading rather than dim, shallow interactive with the emotionless, persona-less machines.)&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    It was one of 10,000 cells, each the size of 1/40 of our home planet&amp;#39;s moon, in network of self-sustained micro-orbitals.  10,000 feet from my head, is the curved wall of the main reactor, a the concetric hollow of a large sphere dumping oxygen and nitrogen through the system, its center, our  spinning hull, with it tunnels and rooms wrapped around the inside of the ring to produce gravity.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    Based on the number of years that have passed, I can only assume that our cell was not only damaged but detached from the main ship and launched off into open space.  I am at least tens of light years away from any solar system that would have any planets, and those planets would not be life-sustaining from my projections.  The cell is traveling close to 60,000 kilometers per hour through natural momentum.  Based on the design requirements of the cell, I believe that it may last from 500 to a maximum of 2,000 years.  Of course that could be made drastically short by collision with a dense cloud of space dust or a meteor collision.&lt;br /&gt; &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    &lt;br /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    They say there is a time of trauma in everyone&amp;#39;s life.  Trauma always produces potent memories, and a young age can provide a level of persistent lucidity in recollection otherwise impossible in such a young age.  For me that age was 3, and 1 month, I believe.  I was considered slower than the others, my genetic siblings, sister and brothers and had not yet been trained in writing or reading.  I was expected to be a laborer on the hull.  The methren (our genetic aunts) followed us toddlers, three aged three there were.  (We talked in a soft, rolling tongue in Illenish, a language that have developed in 2367 - a strangely accented derivative of Chinese with vocabulary heavily borrowed from Icelandic.  The language developed over the years after China&amp;#39;s RMT corporation bought and inhabited the island nation.  Or so the articles from history I have access to so document.  There is not a tremendous body of literature devoted to this cultural subject.)&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    I remember the methren Lucinia who adopted me spiritually.  I remember her name from my deep love for her and my memories of watching her die.  The walls of the escape vestibule crushing her body and eyes showing an expression of horror as the life was squeezed out of here.  There was a millisecond expression of her mind shouting &amp;quot;I love you&amp;quot; before the frozen pupils evoked only the hollowed sign of death.  And then she was entirely consumed, crushed and hidden behind folding metal walls.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    The others had been hurled out of the damaged escape vestibule, thrown violently into the thick nitrogen gases of the reactor and splattered against the opposing wall, the kernel of the micro-orbital.&lt;br /&gt; &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    Everyone had died.  I was the last human survivor on cell AF1416.&lt;br /&gt;&lt;/div&gt;&lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;     Were it not for AD4, I would have died there; drowning any logic or clear reasoning in tears and screaming fits as I stared out a small intact polymer window peering out into the reactor.  I only remember clouds of blood and imagined my sisters and brothers alive in the spinning mist of dark red blood.  I was deluded in my horror by hallucinations of other methren nearby holding my fragile body there in the bubble formed in the collapse.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    I didn&amp;#39;t realize a small crawl space with light trickling in immediately behind me until I heard a nursery song and a voice effecting a methren whose name I have forgotten:&lt;br /&gt; &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    &amp;quot;Rik, rik, trick a trick&amp;quot;  It sang in a soft voice perfectly emulating the methren.  I lay there and fell asleep for what seemed like a long time - for how long I cannot be sure.  I cannot remember the dream exactly but I know I had vivid and fantastic dreams trying to comfort my traumatized mind.  I do remember waking with the false illusion that I was crawling up a bunker ladder, a feat I had never really managed but tried and failed many times.&lt;br /&gt; &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    AD4 was singing again.  Some nursery song about climbing and falling.  &amp;quot;Be brave and climb.&amp;quot;  And then I crawled toward what I though was a methren singing to me; my eyes were still swollen from crying.  The last memory I have was after coming into the full light of hallway into which I had been summoned; the horrific moment of realizing it was AD4 emulating the methren.  I had convinced myself, wrongly, that the drone was going to kill me and throw me into the reactor with the rest; or at least crush me somehow.  I erupted into fitful sobbing again and stared back at the faceless drone which floated back from me playing a soft nursery song to calm my troubled self.&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    From there I have no recollections until the age of 3 years and 10 months, I think, when AD4  had taught me basic writing, the alphabet, the concept of colors.  It spoke in its affected robotic voice after failing to convince me of its humanness.  I often wonder if I spoke to an outsider, they would confuse me for an android?  There is no way of telling.&lt;/div&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;    I am the third generation of the cell, we were commissioned as miners to be used in later parts of the main ship&amp;#39;s voyage.  Now I am only racing time to make others to live in the little amount of time left.  0 generations? 1 generation? 2 generations? 100 generations? 1,000 generations?&lt;br /&gt; &lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&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://quaternion.posterous.com/the-cell-16"&gt;Quaternion's Mind Dump&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-8364637425597092867?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/8364637425597092867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2010/01/cell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/8364637425597092867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/8364637425597092867'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2010/01/cell.html' title='The Cell'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-8775768611064163604</id><published>2010-01-15T09:26:00.001-08:00</published><updated>2010-01-15T09:26:47.408-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='competitive website  analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='seo'/><category scheme='http://www.blogger.com/atom/ns#' term='marketing'/><category scheme='http://www.blogger.com/atom/ns#' term='internet marketing'/><title type='text'>Competitor Research in Global Markets</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;div class="zemanta-img" style="margin-top: 1em; margin-right: 1em; margin-bottom: 1em; margin-left: 1em; float: right; display: block;"&gt;&lt;a href="http://www.flickr.com/photos/13685933@N00/4276220611"&gt;&lt;img src="http://farm3.static.flickr.com/2687/4276220611_50282aeb93_m.jpg" height="187" alt="quantcast-baidu" width="240" style="border: none; display: block;" /&gt;&lt;/a&gt;&lt;p class="zemanta-img-attribution" style="font-size: 0.8em;"&gt; Image by &lt;a href="http://www.flickr.com/photos/13685933@N00/4276220611"&gt;mastaschmue&lt;/a&gt; via Flickr&lt;/p&gt;&lt;/div&gt;Competitive website analysis can be tricky for global markets.  Take the stats for &lt;a href="http://www.crunchbase.com/company/baidu" title="Baidu" class="zem_slink" rel="crunchbase"&gt;Baidu.com&lt;/a&gt;, the leading search engine in China, from &lt;a href="http://www.crunchbase.com/company/quantcast" title="Quantcast" class="zem_slink" rel="crunchbase"&gt;Quantcast&lt;/a&gt; which is logically not representative of global traffic (including China) to the site; only an estimated 848K per month (compare that to US &lt;a href="http://finance.yahoo.com/q?s=GOOG" title="NASDAQ: GOOG" class="zem_slink" rel="stockexchange"&gt;Google&lt;/a&gt; traffic of 146M).  Of course those are hits mostly Chinese expatriots and non-resident visitors.&lt;p /&gt;&lt;div&gt;&lt;div style="font-size: 13px;"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; direction: inherit;"&gt;The magic of &lt;a href="http://quantcast.com" target="_blank"&gt;quantcast.com&lt;/a&gt;, &lt;a href="http://compete.com" target="_blank"&gt;compete.com&lt;/a&gt; estimates [1] is simply getting scrubbed datasets from some ISPs.  Therefore they can be drastically inaccurate due to natural anomalies such as a large majority of traffic falling outside of available data samples.&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; direction: inherit;"&gt;Quantcast only provides statistics for US markets; I wish I had a market research consultant sitting next to me now to suggest similar competitor research tools.&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; direction: inherit;"&gt;There are a host of these sites (basically great marketing planning software with many features free from the bat) which are incredibly great for domestic companies researching other sites with a strong presence in the US markets.&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; direction: inherit;"&gt;I don&amp;#39;t see many with sites which offer estimation of non-US markets.  I&amp;#39;ll try completing a survey for my own purposes to hone in on options for researching some Asian, European and South American regions.  Anybody know of other companies such as Quantcast offering statistics on non-US traffic?&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; direction: inherit;"&gt;[1] Quantcast and other similar companies do provide direct measurement to webmasters via javascript tracking codes.&lt;/div&gt; &lt;/div&gt;&lt;/div&gt;&lt;br /&gt; Related articles&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://www.benzinga.com/markets/company-news/88970/baidu-inc-shares-rise-after-google-decided-to-pull-out-of-china-markets-b"&gt;Baidu Inc Shares Rise After Google Decided To Pull Out of China Markets (BIDU, GOOG)&lt;/a&gt; (&lt;a href="http://benzinga.com"&gt;benzinga.com&lt;/a&gt;)&lt;/li&gt; &lt;/ul&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://quaternion.posterous.com/competitor-research-in-global-markets"&gt;Quaternion's Mind Dump&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-8775768611064163604?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/8775768611064163604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2010/01/competitor-research-in-global-markets_15.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/8775768611064163604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/8775768611064163604'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2010/01/competitor-research-in-global-markets_15.html' title='Competitor Research in Global Markets'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2687/4276220611_50282aeb93_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-9139767615004938477</id><published>2009-12-17T11:51:00.001-08:00</published><updated>2009-12-17T11:51:24.871-08:00</updated><title type='text'>2010 Is the Year Bullshit Takes Off</title><content type='html'>&lt;a href='http://posterous.com/getfile/files.posterous.com/quaternion/4KsWOYl3tzxGSJ8bhlSO2RlEY6EPBhPXxlnjBFAet2I4kxCqKRU6HZg5tcEF/seo-search-volume.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/quaternion/HOjJWYS2hT7fZEZXwYkPAJxpqRHDisCUyPNzPxWWBlVOjgabuvzXI4tPRZlL/seo-search-volume.png.scaled.500.jpg" width="500" height="224"/&gt;&lt;/a&gt; &lt;p&gt;&lt;/p&gt;&lt;div class="zemanta-img" style="margin-top: 1em; margin-right: 1em; margin-bottom: 1em; margin-left: 1em; float: right; display: block;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Image:Scoble_by_feldstein.jpg"&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/en/thumb/1/1e/Scoble_by_feldstein.jpg/300px-Scoble_by_feldstein.jpg" height="295" alt="Scoble, Longhorn Evangelist" width="300" style="text-align: left; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-color: initial; display: block;" /&gt;&lt;/a&gt;&lt;p class="zemanta-img-attribution" style="font-size: 0.8em;"&gt; Image via &lt;a href="http://en.wikipedia.org/wiki/Image:Scoble_by_feldstein.jpg"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;a href="http://scobleizer.com" title="Robert Scoble" class="zem_slink" rel="homepage"&gt;Robert Scoble&lt;/a&gt; just joined the SEO hate club with a &lt;a href="http://scobleizer.com/2009/12/16/2010-the-year-seo-isnt-important-anymore/"&gt;little piece&lt;/a&gt; proclaiming SEO is dead.  His initial premise is that the &amp;quot;game&amp;quot; is too hard: &lt;p /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt;&lt;blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"&gt; Small business marketing is moving away from focusing on SEO. Why do I say that? Because, well, Google and Bing are changing the rules so often and are getting so good at figuring out the real businesses that deserve to be on pages.&lt;/blockquote&gt; &lt;/blockquote&gt;&lt;span style="line-height: 22px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="line-height: 22px;"&gt;A pretty weak argument, considering that the same can be applied to nearly any domain. Web Development is dead.  Why? Well all the frameworks are changing so fast and big companies are figuring out how to use out-of-the-box frameworks without using web developers.  Television advertising is dead.  Why?  Well consumers are using technologies to circumvent ads, like DVRs, and consumers are getting smart about what they really want to buy.&lt;/span&gt;&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;span style="line-height: 22px;"&gt;Concerning market demand for SEO, let&amp;#39;s just look in Google Trends where its clear SEO has risen year after year with no sign of decline. (See attached figure).  But apparently Scoble doesn&amp;#39;t need data to back his argument, just take his word for it.&lt;/span&gt;&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;span style="line-height: 22px;"&gt;Secondly, its beyond absurd to claim that Google looks for &amp;quot;real businesses that deserve to be on pages.&amp;quot;  I guess Scoble really didn&amp;#39;t do his homework on SEO, since anyone worth their muster knows this isn&amp;#39;t Google&amp;#39;s problem in search is to look not for businesses but rather &amp;quot;pages&amp;quot; alone to include in their SERPs.  Page is the unit of trust and relevancy, fueled by contextual links. Concerning businesses and their relevancy to Google, only the inverse is true; that is, Google does look for sites or businesses that distribute malware, conduct phishing, try to hijack the browser&amp;#39;s back button to keep a user on the site, or any other nasty tricks.  Just see their &lt;a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;amp;answer=35769"&gt;guidelines for webmasters&lt;/a&gt;.  Sad will be the day that you can&amp;#39;t rank in Google because you don&amp;#39;t work for some major media outlet.&lt;/span&gt;&lt;/div&gt; &lt;p /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt; &lt;blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"&gt; &lt;span style="color: rgb(17, 17, 17); line-height: 22px;"&gt;With other searches, like one for Tiger Woods, you’ll get a page filled with stuff that SEO just doesn’t affect much anymore. In the middle of that page is a real time box that brings items from Twitter and Google News. It no longer is good enough to be just an SEO expert to get items onto pages like these. You’ve gotta be great at creating content that gets Google’s algorithms to trust it enough to shove it onto these new hybrid pages.&lt;/span&gt;&lt;/blockquote&gt; &lt;/blockquote&gt;&lt;p /&gt;For the records, &amp;quot;the stuff&amp;quot; is called verticals.  Very informative.  Good &lt;a href="http://en.wikipedia.org/wiki/Search_engine_optimization" title="Search engine optimization" class="zem_slink" rel="wikipedia"&gt;SEOs&lt;/a&gt; of course recommend a holistic approach to online marketing that includes verticals and other aspects that are starting to appear more and more on the SERPs.  Many are already talking a &lt;a href="http://searchengineland.com/searching-for-small-businesses-coming-up-frustrated-15112"&gt;lot&lt;/a&gt; &lt;a href="http://www.seomoz.org/blog/10-steps-to-advanced-keyword-research"&gt;about&lt;/a&gt; &lt;a href="http://www.seobook.com/10-blue-links-and-bunch-other-stuff"&gt;verticals&lt;/a&gt;.  The idea that creating great content to get into a vertical is a stretch.  Let&amp;#39;s take maps, for example.  I can have a site with very with little or no good content, but if there&amp;#39;s a page for my local Pizza Burger restaurant in Atlanta with an address and listing, and there&amp;#39;s little no competition, you damn well bet that a search for &amp;quot;Pizza Burger Restaurant Atlanta&amp;quot; will pop up in the map vertical.  With competition, though, the unfortunate reality is that good content (good to humans, that is) doesn&amp;#39;t preempt well-linked content.  Better content can&amp;#39;t fall below others in the SERPs if it isn&amp;#39;t well promoted and referenced throughout the web (from trusted and relevant sites).  This is all part of any good SEO strategy: developing quality content AND implementing a non-spammy link-building strategy through available PR channels on the web, including (ahem) things like Twitter and Facebook.&lt;p /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt;&lt;div&gt;&lt;blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"&gt; &lt;span style="color: rgb(17, 17, 17); line-height: 22px;"&gt;But there’s something deeper going on. Google has built systems that aren’t Page Rank controlled anymore and are giving far better analytics to small businesses than they did a year ago. They know a LOT more about your behavior now other than you clicked on a link, even to the extent that they know whether you called that business or bought something and THAT is changing the skills SEO/SEM types need to have&lt;/span&gt;&lt;/blockquote&gt; &lt;/div&gt;&lt;/blockquote&gt;&lt;p /&gt;Can someone explain this paragraph to me?  Google Analytics isn&amp;#39;t controlled by Page Rank?  Ummm yeah, okay, I&amp;#39;ll agree with you there.  Seriously, I&amp;#39;m trying to figure out if Scoble is trying to imply that SEO is all about page rank, or something.  Maybe I can&amp;#39;t read well, or something, but this guy just comes across as really, really dumb.&lt;p /&gt;&lt;div&gt;Scoble tries to swoon us at the end of the article with revelations of the next big thing:&lt;/div&gt; &lt;p /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt;&lt;div&gt;&lt;blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"&gt; &lt;span style="color: rgb(17, 17, 17); line-height: 22px;"&gt;... the new breed is going beyond just search engines to provide holistic systems that find and track customers not only on search engines like Google and Bing, but on social networks like Facebook and Twitter.&lt;/span&gt;&lt;/blockquote&gt; &lt;p /&gt;&lt;/div&gt;&lt;/blockquote&gt;Dude, you are really out of touch.  There&amp;#39;s already even a word (and acronym) for this &amp;quot;new breed&amp;quot; of marketing you&amp;#39;ve just pretended to invent: Social Media Optimization (SMO).&lt;p /&gt;&lt;div&gt;While I don&amp;#39;t have predictions for 2010 (the popular thing to blog about these days), I can only hope that sometime in 2010 Google figures out how to analyze blog entries and figure out which ones are total bullshit, and then maybe display a nice icon next to its text link on the SERP - like a steaming cow patty of something.  In closing, I won&amp;#39;t be reading anymore Scoble in 2010 - that&amp;#39;s a fact, not a prediction. &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://quaternion.posterous.com/2010-is-the-year-bullshit-takes-off"&gt;Quaternion's Mind Dump&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/1358941065293307736-9139767615004938477?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/9139767615004938477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/2010-is-year-bullshit-takes-off.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/9139767615004938477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/9139767615004938477'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/2010-is-year-bullshit-takes-off.html' title='2010 Is the Year Bullshit Takes Off'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6590348428457074973</id><published>2009-12-15T12:36:00.001-08:00</published><updated>2009-12-15T12:36:11.490-08:00</updated><title type='text'>Google's AdWords Policies - Great Ideas, If they Only Implemented  Them</title><content type='html'>&lt;span style="font-family: arial, sans-serif; font-size: 13px;"&gt;Google recently did a review of it&amp;#39;s &lt;a href="http://googleblog.blogspot.com/2009/12/ad-policies-year-in-review.html" style="color: rgb(0, 0, 204);" target="_blank"&gt;Ad Policy, progress in the current year&lt;/a&gt;, and purported improvements they&amp;#39;re making to algorithms and policies to protect users from &amp;quot;spammy ads&amp;quot; and even worse, sites that trick users&lt;span style="background-color: rgb(255, 255, 255);"&gt; into&lt;/span&gt; installing malware, revealing personal information for &amp;quot;free&amp;quot; goods or getting locked into recurring charges outlined in small text .  The article is really laughable.  This is one area where Google shouldn&amp;#39;t be patting itself on the back, but writing a letter of apology to its users for either doing such a horrible job at improving the quality of approved ads and their &lt;a href="http://en.wikipedia.org/wiki/Landing_page" title="Landing page" rel="wikipedia" style="color: rgb(0, 0, 204);" target="_blank"&gt;landing pages&lt;/a&gt;, or just flat out lying about their efforts; I&amp;#39;m not sure which is the truth.  Take this line from their latest installment of braggadocio:&lt;p /&gt;&lt;blockquote style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(221, 221, 221); border-right-color: rgb(221, 221, 221); border-bottom-color: rgb(221, 221, 221); border-left-color: rgb(221, 221, 221); border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; margin-right: 0px; margin-left: 40px;"&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;&lt;i&gt;To make sure that the ads are safe, we&amp;#39;ve also increased our efforts to detect scam ads and remove them from our system. For example, we’ve recently implemented a new process for permanently disabling &lt;a href="http://en.wikipedia.org/wiki/AdWords" title="AdWords" rel="wikipedia" style="color: rgb(0, 0, 204);" target="_blank"&gt;AdWords&lt;/a&gt; accounts that attempt to harm users by doing things like installing malware on your computer, or offering free services that bait you into accepting hidden fees.&lt;/i&gt;&lt;/div&gt; &lt;/blockquote&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;&lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;Hrmm, let&amp;#39;s see, &amp;quot;permanently disabling AdWords accounts&amp;quot; for companies &amp;quot;offering free services that bait you into accepting hidden fees.&amp;quot;  Let&amp;#39;s take a high profile case such as &lt;a href="http://freecreditreports.com" style="color: rgb(0, 0, 204);" target="_blank"&gt;freecreditreports.com&lt;/a&gt; which has been under &lt;a href="http://www.ftc.gov/" title="Federal Trade Commission" rel="homepage" style="color: rgb(0, 0, 204);" target="_blank"&gt;FTC&lt;/a&gt; &lt;a href="http://www.boston.com/business/personalfinance/managingyourmoney/archives/2009/12/free_isnt_alway.html" style="color: rgb(0, 0, 204);" target="_blank"&gt;investigation&lt;/a&gt; for tricking customers into monthly recurring charges for their &amp;quot;free&amp;quot; credit report.  Google, maybe you&amp;#39;ve been following the news on this?  Let&amp;#39;s do a search for &amp;quot;free credit report.&amp;quot;  Wow! Looky there. The top ad is none other than &lt;a href="http://freecreditreports.com" style="color: rgb(0, 0, 204);" target="_blank"&gt;freecreditreports.com&lt;/a&gt;.  Maybe they&amp;#39;re too high-paying of customers to permanently ban from AdWords?&lt;/div&gt; &lt;p /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;&lt;div style="font-size: 13px;"&gt;&lt;div style="font-family: arial, sans-serif;"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;Google also makes reference to it&amp;#39;s help topic on disabled AdWords accounts which lists the following amongst others as a violation of their landing page policy:&lt;/div&gt; &lt;p /&gt;&lt;/div&gt;&lt;blockquote style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(221, 221, 221); border-right-color: rgb(221, 221, 221); border-bottom-color: rgb(221, 221, 221); border-left-color: rgb(221, 221, 221); border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; margin-right: 0px; margin-left: 40px;"&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;&lt;div style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;i&gt;Arbitrage sites without relevant and original content that are designed for the purpose of showing ads&lt;/i&gt;&lt;/div&gt;&lt;/div&gt; &lt;p /&gt;&lt;/div&gt;&lt;/blockquote&gt;Let&amp;#39; see. I did a search for &amp;quot;free government loans&amp;quot; (another popular scam Google has supported through its AdWords network) and found an ad linking to a site called &lt;a href="http://us.peeplo.com" style="color: rgb(0, 0, 204);" target="_blank"&gt;us.peeplo.com&lt;/a&gt; which alas was yet another meta search engine returning results for the said search terms and some &lt;a href="http://www.google.com/adsense" title="AdSense" rel="homepage" style="color: rgb(0, 0, 204);" target="_blank"&gt;AdSense&lt;/a&gt; placements to boot.  These kind of crap results without original content are still fairly common in both organic and &lt;a href="http://en.wikipedia.org/wiki/Pay_per_click" title="Pay per click" rel="wikipedia" style="color: rgb(0, 0, 204);" target="_blank"&gt;paid listings&lt;/a&gt;.&lt;/div&gt;&lt;p /&gt; &lt;div style="margin-top: 0px; margin-bottom: 0px;"&gt;One wealthy man I truly respect is &lt;a href="http://en.wikipedia.org/wiki/Warren_Buffett" style="color: rgb(0, 0, 204);" target="_blank"&gt;Warren Buffet&lt;/a&gt; who often speaks in frank and undecorated language even when &lt;a href="http://www.cbsnews.com/stories/2009/02/28/business/main4835570.shtml" style="color: rgb(0, 0, 204);" target="_blank"&gt;his company fails to deliver results to its shareholders&lt;/a&gt;.  As &lt;span style="background-color: rgb(255, 255, 255);"&gt;a&lt;/span&gt;&lt;/div&gt; user of Google&amp;#39;s services, I only wish they could speak with the same level of humility and admit fault in profiting off of scams and underachieving in its &amp;quot;efforts&amp;quot; to protect its users on the Internet.&lt;/div&gt; &lt;/div&gt;&lt;/div&gt;&lt;/span&gt; &lt;p&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/quaternion/NVRSHU0OFemAQg1dp9bxo0XrdJhqM21qB015EnnVo0sSSJWuIKxyVDD0z975/google-profitingOffScams.png" width="337" height="282"/&gt; &lt;a href='http://posterous.com/getfile/files.posterous.com/quaternion/r84ApbvTVHoRYHeWCViqNQlXdpGJ58NqPa9balrgx51QGtDO3Okde1SpICNr/free-credit-report-search.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/quaternion/nNPowc34CGKYLwl5ohvpUo9qneM1se1zzuYBGYFq6s19Rgk3XM4NnZH9zXRi/free-credit-report-search.png.scaled.500.jpg" width="500" height="280"/&gt;&lt;/a&gt; &lt;div&gt;&lt;a href='http://quaternion.posterous.com/googles-adwords-policies-great-ideas-if-they'&gt;See and download the full gallery on posterous&lt;/a&gt;&lt;/div&gt;&lt;/p&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://quaternion.posterous.com/googles-adwords-policies-great-ideas-if-they"&gt;Quaternion's mind dump&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/1358941065293307736-6590348428457074973?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6590348428457074973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/google-adwords-policies-great-ideas-if.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6590348428457074973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6590348428457074973'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/google-adwords-policies-great-ideas-if.html' title='Google&amp;#39;s AdWords Policies - Great Ideas, If they Only Implemented  Them'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-2788473638438393178</id><published>2009-12-08T09:52:00.001-08:00</published><updated>2009-12-08T09:52:03.430-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NaNoWriMo'/><category scheme='http://www.blogger.com/atom/ns#' term='creative commons'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='hot chip'/><category scheme='http://www.blogger.com/atom/ns#' term='novel'/><category scheme='http://www.blogger.com/atom/ns#' term='aaku'/><category scheme='http://www.blogger.com/atom/ns#' term='science fiction'/><title type='text'>The Plains</title><content type='html'>&lt;div&gt;&lt;object type="application/x-shockwave-flash" height="281" data="http://vimeo.com/moogaloop.swf?clip_id=8034448&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" width="500"&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=8034448&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;/object&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Kwatsura stood back as Ysmelro drove the long hammer down, busting the calcified hinges clear off the ladder box; the metal plate of the busted door fell off and drifted down for several seconds, disappearing from sight before landing in the soft dirt of the plain below them.&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://quaternion.posterous.com/the-plains"&gt;Quaternion's mind dump&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/1358941065293307736-2788473638438393178?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/2788473638438393178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/plains.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2788473638438393178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2788473638438393178'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/plains.html' title='The Plains'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-2841772282664288490</id><published>2009-12-03T11:47:00.001-08:00</published><updated>2009-12-03T11:47:25.757-08:00</updated><title type='text'>Nonjatta: Malt Maniac Awards: "The quality of the average Japanese whisky has now surpassed the quality of the average Scotch whisky."</title><content type='html'>&lt;div class="posterous_bookmarklet_entry"&gt; &lt;a href="http://nonjatta.blogspot.com/2009/12/malt-maniac-awards-quality-of-average.html"&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/quaternion/ocJJrAGpoyotdgmplAiDeBDvsssnkroJoueHGxgfmleGioyFuxdlAkcjCvpb/media_httplh4ggphtcom7Nheqvl9IVcSxXgS6jDwoIAAAAAAAAG2kEWPTBX6uwYos800awardcloseupJPG_jHIdfdIktAxvCEo.JPG.scaled500.jpg" width="428" height="473"/&gt; &lt;/a&gt;&lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://nonjatta.blogspot.com/2009/12/malt-maniac-awards-quality-of-average.html"&gt;nonjatta.blogspot.com&lt;/a&gt;&lt;/div&gt; &lt;p&gt;Damned if we don't start importing more of these drams to the states.&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://quaternion.posterous.com/nonjatta-malt-maniac-awards-the-quality-of-th"&gt;Quaternion's mind dump&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/1358941065293307736-2841772282664288490?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/2841772282664288490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/nonjatta-malt-maniac-awards-quality-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2841772282664288490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2841772282664288490'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/nonjatta-malt-maniac-awards-quality-of.html' title='Nonjatta: Malt Maniac Awards: &amp;quot;The quality of the average Japanese whisky has now surpassed the quality of the average Scotch whisky.&amp;quot;'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-3030769154231974171</id><published>2009-12-03T10:42:00.001-08:00</published><updated>2009-12-03T10:42:19.028-08:00</updated><title type='text'>Flickr Color Search for "Aaku" Images</title><content type='html'>&lt;div class="posterous_bookmarklet_entry"&gt; &lt;img src="http://farm1.static.flickr.com/136/319924391_b3a12672fd.jpg" height="356" alt="The ceiling of the lodging tapered to a small curved bowl which reflect small pink slivers of light curling at their ends, nebulous tendrils of light slowly shifting forms across the wall." width="500" /&gt;    &lt;div class="posterous_quote_citation"&gt;via &lt;a href="http://aaku.tumblr.com/post/267749962/11-eidon-29065-rsola-east-irdon-high-tower-a"&gt;aaku.tumblr.com&lt;/a&gt;&lt;/div&gt; &lt;p&gt;I've been using &lt;a href="http://labs.ideeinc.com/multicolr/"&gt;http://labs.ideeinc.com/multicolr/&lt;/a&gt; to try and match images from the creative commons with segments of aaku.  Sometimes with good results, other times not so great.  Hopefully they'll form a whole that provides a good visual summary of the chapters.&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://quaternion.posterous.com/flickr-color-search-for-aaku-images"&gt;Quaternion's mind dump&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/1358941065293307736-3030769154231974171?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/3030769154231974171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/flickr-color-search-for-images.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/3030769154231974171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/3030769154231974171'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/flickr-color-search-for-images.html' title='Flickr Color Search for &amp;quot;Aaku&amp;quot; Images'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/136/319924391_b3a12672fd_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-7304865903057959722</id><published>2009-12-01T10:56:00.001-08:00</published><updated>2009-12-01T10:56:13.786-08:00</updated><title type='text'>Waaaarggggghhh</title><content type='html'>&lt;div class="posterous_bookmarklet_entry"&gt; &lt;object height="430" width="480"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://www.theonion.com/content/themes/common/assets/onn_embed/embedded_player.swf?image=http%3A%2F%2Fwww.theonion.com%2Fcontent%2Ffiles%2Fimages%2FZOMBIE_REAGAN_ARTICLE_11_23_09.jpg&amp;amp;videoid=99422&amp;title=Zombie+Reagan+Raised+From+Grave+To+Lead+GOP" /&gt;&lt;param name="wmode" value="transparent" /&gt;&lt;embed allowfullscreen="true" type="application/x-shockwave-flash" src="http://www.theonion.com/content/themes/common/assets/onn_embed/embedded_player.swf" flashvars="image=http%3A%2F%2Fwww.theonion.com%2Fcontent%2Ffiles%2Fimages%2FZOMBIE_REAGAN_ARTICLE_11_23_09.jpg&amp;amp;videoid=99422&amp;amp;title=Zombie+Reagan+Raised+From+Grave+To+Lead+GOP" allowscriptaccess="always" height="430" wmode="transparent" width="480"&gt;&lt;/embed&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://www.theonion.com/content/video/zombie_reagan_raised_from_grave?utm_source=onion_rss_daily"&gt;theonion.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://quaternion.posterous.com/waaaarggggghhh"&gt;Quaternion's mind dump&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/1358941065293307736-7304865903057959722?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/7304865903057959722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/waaaarggggghhh.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7304865903057959722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7304865903057959722'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/waaaarggggghhh.html' title='Waaaarggggghhh'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-2105658504041783703</id><published>2009-12-01T09:43:00.001-08:00</published><updated>2009-12-01T09:43:02.233-08:00</updated><title type='text'>Perception of Twitter by the Masses - The Stats to Prove my Point.  Ha! There!</title><content type='html'>&lt;p&gt;&lt;span style="font-size: 12px;"&gt; &lt;strong&gt;AOL’s top “What Is… “ questions of 2009 &lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol&gt;&lt;li&gt;&lt;span style="font-size: 12px;"&gt;what is twitter &lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;Haha.  Via:  &lt;a href="http://tr.im/Gk8x"&gt;http://tr.im/Gk8x&lt;/a&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://quaternion.posterous.com/perception-of-twitter-by-the-masses-the-stats"&gt;Quaternion's mind dump&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/1358941065293307736-2105658504041783703?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/2105658504041783703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/12/perception-of-twitter-by-masses-stats.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2105658504041783703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2105658504041783703'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/12/perception-of-twitter-by-masses-stats.html' title='Perception of Twitter by the Masses - The Stats to Prove my Point.  Ha! There!'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-7848204744063550615</id><published>2009-11-25T09:16:00.000-08:00</published><updated>2009-11-25T09:30:54.605-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='microblogging'/><category scheme='http://www.blogger.com/atom/ns#' term='onion news'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Noveller</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.theonion.com/content/files/images/New-Noveller-redo.article.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 250px; height: 179px;" src="http://www.theonion.com/content/files/images/New-Noveller-redo.article.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now &lt;a href="http://www.theonion.com/content/news/new_noveller_allows_people_to_post"&gt;here's a great idea&lt;/a&gt;.  Make people write more, rather than less.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-7848204744063550615?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/7848204744063550615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/11/noveller.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7848204744063550615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7848204744063550615'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/11/noveller.html' title='Noveller'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-3234481165979368138</id><published>2009-11-23T12:49:00.000-08:00</published><updated>2009-11-23T13:24:04.778-08:00</updated><title type='text'>And the Preferred Character Encoding for stumbleupon is .... not UTF-8?</title><content type='html'>&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_kcQvXqqF6KM/Swr8bT2ZqEI/AAAAAAAAAfQ/tiPq1Qh-Ae0/s1600/mojibake.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 157px;" src="http://3.bp.blogspot.com/_kcQvXqqF6KM/Swr8bT2ZqEI/AAAAAAAAAfQ/tiPq1Qh-Ae0/s200/mojibake.png" alt="" id="BLOGGER_PHOTO_ID_5407411848726816834" border="0" /&gt;&lt;/a&gt;I've started using &lt;a href="http://www.stumbleupon.com/"&gt;stumbleupon&lt;/a&gt; recently to experiment with its &lt;a href="http://www.seomoz.org/blog/stumbleupons-fantastic-ability-to-drive-traffic"&gt;effectiveness in promoting content&lt;/a&gt;.  I stumbled a &lt;a href="http://aaku.tumblr.com/"&gt;story blog&lt;/a&gt; I'm building for &lt;a href="http://www.nanowrimo.org/"&gt;nanowrimo&lt;/a&gt; and was surprised to see the Japanese title appear in my favorites as complete jibberish.  Checking the response headers, they're using ISO-8859-1.  Wow.&lt;br /&gt;&lt;br /&gt;At of the time of this writing, Stumbleupon boasts 8,700,680 users.  Certainly some of these users would be interested in stumbling non-English pages as well?&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I imagine the developers have all sorts of esoteric reasons why they can't support unicode now, probably all of them rooted in something stupid, like a stubborn DBA who didn't bother configuring the database correctly.  It turns out my company has a &lt;a href="http://www.cnn.com/"&gt;small website&lt;/a&gt; where ISO-8859-1 is still considered the shit as well.&lt;br /&gt;&lt;br /&gt;So here I pronounce March 3rd, 2010 as "Stop Fucking using ISO-8859-1 Forever, For Fuck's Sake Day."  I think this event should be regarded with even more importance than &lt;a href="http://blog.enterthefoo.com/2009/10/february-1-2010-is-officialy-stop.html"&gt;Stop Microblogging Forever Day.&lt;/a&gt;  Lest all the web rot in &lt;a href="http://en.wikipedia.org/wiki/Mojibake"&gt;&lt;span style="font-style: italic;"&gt;mojibake&lt;/span&gt;&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-3234481165979368138?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/3234481165979368138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/11/and-preferred-character-set-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/3234481165979368138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/3234481165979368138'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/11/and-preferred-character-set-for.html' title='And the Preferred Character Encoding for stumbleupon is .... not UTF-8?'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_kcQvXqqF6KM/Swr8bT2ZqEI/AAAAAAAAAfQ/tiPq1Qh-Ae0/s72-c/mojibake.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6767819837008456292</id><published>2009-10-21T12:37:00.000-07:00</published><updated>2009-10-22T11:54:47.958-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='social media'/><category scheme='http://www.blogger.com/atom/ns#' term='marketing'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='rants'/><title type='text'>More on Those Things I Just Said about Microblogging</title><content type='html'>UPDATE: I still hate still hate twitter.  And I'm going to get a tasty pumpkin latte... woo hoo.&lt;br /&gt;&lt;br /&gt;Apparently I'm not alone at all in the universe of Twitter defectors or general micro-blogging haters.  Even some &lt;a href="http://www.seobook.com/social-media-guruism-mostly-harmless"&gt;SEO folks&lt;/a&gt; (who my gut intuition told me most love Twitter and more broader, everything in the 'Social Media' rubric) think it's &lt;a href="http://www.seobook.com/social-media-guruism-mostly-harmless"&gt;mostly irrelevant&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first great quote from this article follows:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;"No matter how inane, publicity stunts can work. Once. Early adopters can benefit from being first - they are remarkable simply because they are first. But once the followers arrive, the stunt is no longer remarkable, and the technique is no longer repeatable. The medium was the message, but not for long."&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Quite true.  A lot of companies jumped on the Twitter bandwagon to build brand recognition and I think initially people were listening and they were getting good CTRs.  Companies still are jumping on the bandwagon along with a new breed of consultants prodding them to do so.  I'd like to see a graph of CTR  over time from the initial hyping of Twitter to today.  Dwindling?  Probably.  I say because most end users (the microblogging platform audience) are trying to leverage Twitter as means of following the limited circle of friends they know - which is becoming increasingly impossible as people ... errmmm ... won't shut up.  The update overload effect is only reducing potential audience as people unfollow even the people they know in the flesh.  Can a company expect the same defectors or half-hearted microblogging participants to want to follow their updates on new shampoos or discount e-coupons on tires?  Probably not.  It requires too many hours to wade through the data.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;"Is it possible to have a conversation in Twitter or on Facebook? &lt;/p&gt; &lt;p&gt;"Perhaps, on a superficial level, but mostly it's quick blast of - and I use this phrase loosely - information. &lt;/p&gt; &lt;p&gt;"A lot of people who wrote some really interesting, deep, valuable stuff in forums and on blogs migrated to Twitter, used it a bit, then stopped. I think that happened because there was no value in it for the writer. Conversation didn't happen. Relationships weren't being built. "&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Microblogging does not provide a means of conversation.  If you want to start a conversation with me on Twitter or Facebook, please fucking don't.  I will not engage you any bit. That is not the way human beings converse.  Nor do I leave notes for people in the woods at some secret spot - oh, how neat and convenient.  As a means of notifying or broadcasting events - Facebook and Twitter are valid technologies, but they do not in any mean enable a damn conversation. Also, in case you think it does, I need to inform you also that when the PA announces a firedrill in your office, that's not a conversation either. Sorry, doesn't count.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;"People place a lot of importance on getting attention. They point to the number of followers as if that metric means something. It doesn't, of course. The important metric is how many of those followers are paying attention and then engaging in a way that contributes to the bottom line."&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This echoes my general skepticism with metrics provided by &lt;a href="http://feedburner.google.com/"&gt;FeedBurner&lt;/a&gt; and the likes.  If you work in a bakery should you install a smart camera to count how many times people look at your signs when they walk by or track how many pamphlets you've given out?  Isn't the metric of how many people go into your store something more worth your time to track, and more importantly the ratio of buyers to visitors or your Conversion Rate?  Your branding success is already evident in your CTRs and Conversion Rates and you already know your sources in basic site analytics scenario. Recognition isn't shit if you're not optimizing keyword-driven organic traffic (which doesn't boil down to one or two mediums - Twitter or Facebook) or running effective ad campaigns.  And what a wasted opportunity if you do become Twitter-famous or YouTube-famous accidentally and can only convert 0.0001% of your traffic.  Absolutely pitiful unless you're selling yachts.  Go buy the world a coke with all your shitty traffic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;"Find out how social media translates to your bottom line. If your social media guru can't demonstrate that, s/he is a waste of space. Social media must either increase sales, or cut costs, or both. If it doesn't, it's not business, it's just time wasting. If it can't be measured, then there's a good chance it isn't happening. &lt;/p&gt; &lt;p&gt;"Agree? Disagree?"&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Oh, do I agree.  There is no need to pay some blazer-over-CalvinKlein-t-shirt-wearing stubbly-chinned con artist to tell me how to put Twitter and RSS chicklets on my website.  The best advice is just try every outlet or inlet and test (and there are tools like &lt;a href="http://posterous.com/"&gt;Posterous&lt;/a&gt; that make this incredibly easy).  Your audience might be on Twitter.  Lucky you.  Just test and find out where your audience is then appreciate on those channels.  I say "appreciate," not focus because focus always needs to on conversion strategy - that's the key contributing factor to the bottom-line.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;UPDATE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Yet more &lt;/span&gt;&lt;a style="color: rgb(204, 0, 0);" href="http://www.seobook.com/google-bing-annouce-real-time-search-deals-twitter"&gt;appropriate microblogging-bashing from seo-book&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; - man I love these guys.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Hmmm..."product"? Obviously something a bit smarter that [sic] simply providing raw indexing and display.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-6767819837008456292?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6767819837008456292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/10/more-on-those-things-i-just-said-about.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6767819837008456292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6767819837008456292'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/10/more-on-those-things-i-just-said-about.html' title='More on Those Things I Just Said about Microblogging'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-4326913588562870629</id><published>2009-10-16T10:05:00.001-07:00</published><updated>2011-09-10T12:40:49.900-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='microblogging'/><category scheme='http://www.blogger.com/atom/ns#' term='predictions'/><category scheme='http://www.blogger.com/atom/ns#' term='hate'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='communication'/><title type='text'>February 1, 2010 is Officialy "Stop Microblogging Forever Day"</title><content type='html'>&lt;div style="border: 2px solid red; background-color: #fcc; color: black !important; padding: 10px;"&gt;The current me no longer ſticks to this prophecy. I like microblogging a lot, moſtly as a conſumer honeſtly.  And it has affected my life more than any other media I know of on the Internetz.  I've changed my long-held views on &lt;a href="http://twitter.com/#!/zooko/status/50179842389442560"&gt;diet&lt;/a&gt; and &lt;a href="http://twitter.com/#!/garytaubes"&gt;nutrition&lt;/a&gt;, I've gained inſights into previously denſe topics like &lt;a href="http://twitter.com/#!/nocombat"&gt;cryptography&lt;/a&gt; and &lt;a href="http://twitter.com/#!/moxie__"&gt;ſecurity&lt;/a&gt;, and countleſs other experiences ... But in celebration of being "wrong" on the Internet and humbly admitting it, I leave this poſt to rot with honor. Countdown to 2015 when we'll ſee if the paſt me was a prophet or not ;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This is a liberating experience. I'm typing.  And I can keep typing and not worry about some stupid artificial 140 character limit or having to go back through my post and trim down urls so it all fits in this tidy little space of this hour's pithy little thought.  It's also liberating knowing that what I type isn't going to pop up and distract a knowledge worker with their &lt;a href="http://growl.info/"&gt;notification&lt;/a&gt; &lt;a href="https://wiki.ubuntu.com/NotifyOSD"&gt;widget&lt;/a&gt; &lt;a href="http://twitterfox.net/"&gt;of choice&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The most liberating emotion of all though follows my uninstalling the last twitter client on my set of available &lt;a href="http://www.dell.com/us/en/dfb/notebooks/latit_d620/pd.aspx?refid=latit_d620&amp;amp;cs=28&amp;amp;s=dfb"&gt;computing&lt;/a&gt; &lt;a href="http://www.apple.com/macbookpro/"&gt;machinery&lt;/a&gt; and knowing that I don't have to be distracted by hourly shouts for attention, nearly each like a 50s paper boy on the street corner with a minor twist: "Extra! Extra! Read all about it, I exist! Me! Me! Me!"  Wait, was that 140 characters? Fuck it, even a goddamn paper-boy didn't have to worry about that kind of shit.&lt;br /&gt;&lt;br /&gt;If you have no fucking idea what I'm talking about (likely not since the 5 or more people who read this blog are probably programmers), then all I have to say is: "Awesome, you're one of the lucky people who hasn't suffered keeping up with many horrible trends in communication.  Let's have a beer sometime and communicate like real human beings do."&lt;br /&gt;&lt;br /&gt;If you do know what talking about, then yes, &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; or any &lt;a href="http://en.wikipedia.org/wiki/Microblogging"&gt;&lt;span style="font-style: italic;"&gt;microblogging&lt;/span&gt;&lt;/a&gt; platform in general - and I don't give a shit if it's &lt;a href="http://identi.ca/"&gt;open source&lt;/a&gt;, a bad idea coupled with a bad implementation is just bad.  What does any self-respecting human being think when they hear words like: "tweet" or "&lt;a href="http://twitterrific.com/"&gt;twitterific&lt;/a&gt;."  Our primordial fight or flight reactions should have told us that this is all so very "not cool" and any association with it will transmute into bad experiences of being picked on by the mean, fat bully  during recess.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;5 Years From Now No One Will Give a Shit About Twitter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm not profit, but I believe this with 90% certainty.  The more amusing background this claim is that right now virtually no one gives a shit about Twitter.  "Oh, but CNN uses Twitter!", you say as you watch the evening news and adore the little Twitter logo at the bottom of the screen, "Follow us on Twitter!"  But before you grab the lotion and tissue to celebrate mainstream media's "embrasing" the microblogging platform please open your eyes to another reality.  You know your other friends who don't work in the tech industry?  You know, that big fat slice of the demographics pie whose only exposure to the Internet is for the usual shit: &lt;a href="http://www.imeem.com/"&gt;listening to music&lt;/a&gt; at work, catching up with people on &lt;a href="http://www.facebook.com/"&gt;facebook&lt;/a&gt;, shopping on &lt;a href="http://craigslist.org/"&gt;craigslist&lt;/a&gt;, etc.  Ask them the question: "What do you think about Twitter?"  I can say 100% of the people I know in this category (and the majority of my friends are) fall into one of two response categories:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;What is Twitter?&lt;/li&gt;&lt;li&gt;Eh, isn't that the same thing as Facebook status updates?&lt;/li&gt;&lt;/ol&gt;To your friends in category (1) you can describe Twitter and microblogging in general and they'll then say: "Eh, isn't that the same thing as Facebook status updates?" Or if they fall into category (2) immediately you can try to sell them on Twitter and the "less is more" philosophy, yada yada.  And then they'll probably say something like: "Why not just write a normal blog, and when you feel like writing less, just write less."&lt;br /&gt;&lt;br /&gt;So broadly speeking, virtually everyone falls into a higher-level category, or the "Don't give a shit" bucket.  Over the next 5 years as Twitter &lt;a href="http://www.seomoz.org/blog/7-good-twitter-monetization-strategies-and-7-that-suck"&gt;tries&lt;/a&gt; to &lt;a href="http://www.localsearchnews.net/twitter-the-local-monetization-strategy/"&gt;make&lt;/a&gt; &lt;a href="http://www.techcrunch.com/2009/06/16/fred-wilson-the-value-of-twitter-is-in-the-power-of-passed-links/"&gt;money&lt;/a&gt; - god, I hope they don't - they'll be faced with this reality: people actually don't give a shit about microblogging.  And Twitter really is just like "Facebook status upates" as your "technically illiterate" friends claim.  The media will abandon of it's minor fling. (Let's describe this "fling" clearly: Twitter is basically the nerdy kid getting invited to the popular kid's table for a a few week before they find out he plays Dungeons and Dragons.)&lt;br /&gt;&lt;br /&gt;In closing let met say: People like reading.  People like reading more than 140 characters at a time, which shouldn't come as a surprise.  Long live writing in it's natural form. People don't like being notified when you finished &lt;a href="http://twitter.com/#search?q=pumpkin%20latte"&gt;drinking a tasty pumpkin latte&lt;/a&gt;.  If you use twitter, at least try providing links to content people might enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-4326913588562870629?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/4326913588562870629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/10/february-1-2010-is-officialy-stop.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/4326913588562870629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/4326913588562870629'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/10/february-1-2010-is-officialy-stop.html' title='February 1, 2010 is Officialy &quot;Stop Microblogging Forever Day&quot;'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6187085061128637043</id><published>2009-02-19T11:32:00.000-08:00</published><updated>2009-10-27T13:11:51.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twisted'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Twisted Sleep</title><content type='html'>&lt;p&gt;Q: "How do I &lt;i&gt;sleep()&lt;/i&gt; in the context of a &lt;a href="http://twistedmatrix.com"&gt;twisted&lt;/a&gt; application without blocking the reactor?"&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here's a simple way:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;&lt;br /&gt;def sleep(secs):&lt;br /&gt;    d = Deferred()&lt;br /&gt;    reactor.callLater(secs, d.callback, None)&lt;br /&gt;    return d&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And here's how you might use the sleep function:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;&lt;br /&gt;@inlineCallbacks&lt;br /&gt;def doSomeStuff(stuff, throttle):&lt;br /&gt;   for thing in stuff:&lt;br /&gt;      yield someThing.send(thing)&lt;br /&gt;      yield sleep(throttle)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;But it's better to just let the reactor schedule things for you:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;&lt;br /&gt;def doSomeStuff(stuff, throttle):&lt;br /&gt;    if not stuff:&lt;br /&gt;        return defer.succeed(None)&lt;br /&gt;    d = Deferred()&lt;br /&gt;    work = list(stuff)&lt;br /&gt;    def sendNext()&lt;br /&gt;        if not work:&lt;br /&gt;            loop.stop()&lt;br /&gt;            d.callback(None)&lt;br /&gt;        next = work.pop(0)&lt;br /&gt;        return someThing.send(next)&lt;br /&gt;    loop = LoopingCall(sendNext)&lt;br /&gt;    loop.start(throttle)&lt;br /&gt;    return d&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-6187085061128637043?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6187085061128637043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/02/twisted-sleep.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6187085061128637043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6187085061128637043'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/02/twisted-sleep.html' title='Twisted Sleep'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6897263361034349729</id><published>2009-02-09T09:17:00.000-08:00</published><updated>2009-02-09T14:06:39.849-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='messaging middleware'/><category scheme='http://www.blogger.com/atom/ns#' term='rabbitmq'/><category scheme='http://www.blogger.com/atom/ns#' term='amqp'/><title type='text'>Notes on Upgrading a RabbitMQ Cluster</title><content type='html'>&lt;strong&gt;SURGEON GENERAL'S WARNING:&lt;/strong&gt; This following is by no means a helpful guide to upgrading a &lt;a href="http://www.rabbitmq.com"&gt;RabbitMQ&lt;/a&gt; cluster ... yet.  In fact, my description here might very well be the "wrong" way to do it.  The purpose of this posting is to hopefully solicit comments from other RabbitMQ users and decide on the sanest way to upgrade a cluster - including methods for coping with live upgrades (zero downtime).&lt;br /&gt;&lt;br /&gt;Also note that the following assumes a RPM-based Linux distribution; although the instructions should be simple to adapt to non-RPM-based Linux distributions.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1.&lt;/strong&gt; If current node is disc node, remove from cluster and reset state.  For example, on disc nodeA which is part of disc cluster (hostA, hostB, hostC), run the following commands as root.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  $ rabbitmqctl stop_app&lt;br /&gt;  $ rabbitmqctl cluster rabbit@hostB rabbit@hostC&lt;br /&gt;  $ rabbitmqctl reset&lt;br /&gt;  $ rabbitmqctl start_app&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2.&lt;/strong&gt; Shutdown rabbitmq.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  $ /etc/init.d/rabbitmq-server stop&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3.&lt;/strong&gt; Remove mnesia files; hopefully there's a nicer way of doing this - for example, is there a safe way to preserve message journal across versions?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  $ rm -rf /var/lib/rabbitmq/mnesia/rabbit/*&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;4.&lt;/strong&gt; Upgrade with new rpm.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  $ rpm -U --force rabbitmq-server-&lt;version x&gt;.rpm&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;5.&lt;/strong&gt; Reconfigure rabbitmq node per requirements for your system; configure users, etc.  I believe this only should be done on first node in cluster.  The other nodes should use this to seed their configuration upon joining the cluster.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;6.&lt;/strong&gt; If current node is disc node, add to cluster (&lt;strong&gt;after&lt;/strong&gt; all nodes in disc cluster have been upgraded). For example if current node is hostA and part of cluster (hostA, hostB, hostC):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  $ rabbitmqctl stop_app&lt;br /&gt;  $ rabbitmqctl force_reset&lt;br /&gt;  $ rabbitmqctl cluster rabbit@hostA rabbit@hostB rabbit@hostC&lt;br /&gt;  $ rabbitmqctl start_app&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This last step is where I the least confidence.  For starters, without forcefully resetting the node, I got this error on trying to cluster the nodes: "Bad cookie in table definition amqqueue."  Secondly, I had not realized this before, but upon joining the cluster the local node will pick up &lt;b&gt;all&lt;/b&gt; the settings from the synchronized disc nodes - including configured users and passwords.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-6897263361034349729?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6897263361034349729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2009/02/notes-on-upgrading-rabbitmq-cluster.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6897263361034349729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6897263361034349729'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2009/02/notes-on-upgrading-rabbitmq-cluster.html' title='Notes on Upgrading a RabbitMQ Cluster'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-2632508158832058736</id><published>2008-11-05T07:50:00.000-08:00</published><updated>2008-11-05T07:57:00.595-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>finally</title><content type='html'>&lt;p&gt;I always thought I understand `finally' in the context of exception handling in either Java or Python.  Now, I'm not sure I &lt;b&gt;really&lt;/b&gt; understand it.  Riddle: What does the following print?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def f():&lt;br /&gt;    try:&lt;br /&gt;        return 1&lt;br /&gt;    finally:&lt;br /&gt;        return 2&lt;br /&gt;print f()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ah ... never mind ... I understand it again now.  It means: finally.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-2632508158832058736?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/2632508158832058736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/11/finally.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2632508158832058736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/2632508158832058736'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/11/finally.html' title='finally'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-7270234660102318516</id><published>2008-10-28T06:21:00.000-07:00</published><updated>2008-10-28T07:45:41.251-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python magazine'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Class Variables</title><content type='html'>&lt;p&gt;My &lt;a href="http://pymag.phparch.com/c/issue/view/83"&gt;dreaded multiple inheritance article&lt;/a&gt; was published in Python Magazine yesterday.  It was tricky enough &lt;a href="http://www.enterthefoo.com/static/prez/mro/index.html"&gt;giving a presentation&lt;/a&gt; on the subject, so I look at the article as somewhat of an achievement.  Someone contacted me shortly after concerning my use of &lt;i&gt;class variable&lt;/i&gt; in one of the examples:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Publishable(object):&lt;br /&gt;    published = False&lt;br /&gt;    def __init__(self, start_date, end_date):&lt;br /&gt;        self.start_date = start_date&lt;br /&gt;        self.end_date = end_date&lt;br /&gt;    def publish(self):&lt;br /&gt;        self.published = True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The inquirer's question:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;I've always been under the impression having class &amp; instance&lt;br /&gt;variables with the same name is just confusing and not a good way to&lt;br /&gt;write Python. Why did you do this?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Anyhow, on the subject of "class variables," here are my thoughts:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;[Begin email response]&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I guess it depends on who you ask.  The pattern of using class level&lt;br /&gt;variable as a default values for instances is one I like and don't&lt;br /&gt;find confusing.  But these kind of things are always subjective.  It's&lt;br /&gt;not my own pattern either, but one I've noticed in other projects.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twistedmatrix.com/trac/browser/tags/releases/twisted-8.1.0/twisted/internet/defer.py#L137"&gt;http://twistedmatrix.com/trac/browser/tags/releases/twisted-8.1.0/twisted/internet/defer.py#L137&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.pythonpaste.org/pythonpaste/browser/Paste/WebOb/trunk/webob/__init__.py#L474"&gt;http://trac.pythonpaste.org/pythonpaste/browser/Paste/WebOb/trunk/webob/__init__.py#L474&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I make a distinction, though, between a "class variable" and a&lt;br /&gt;variable defined at the class level.  In terms of the VM, they are of&lt;br /&gt;course the same thing, but are differentiated in human terms by uses&lt;br /&gt;cases.  The former "class variable" is useful if you are tracking&lt;br /&gt;state on a class - for example keeping a count of objects created&lt;br /&gt;through a class method:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Foo:&lt;br /&gt;   _created = 0&lt;br /&gt;   @classmethod&lt;br /&gt;   def create(cls):&lt;br /&gt;       foo = Foo()&lt;br /&gt;       cls._created += 1&lt;br /&gt;       return foo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The latter "class level variable" can be useful for defining default&lt;br /&gt;values for attributes (especially ones which cannot be specified in&lt;br /&gt;the constructor):&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Task:&lt;br /&gt;    completed = False&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.start_time = time.time()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;(This is same pattern I'm adopting in my article.)  Of course, when&lt;br /&gt;the "completed" attribute is looked up on an instance of Task, it has&lt;br /&gt;to take an extra step - first looking in dict of instance and then in&lt;br /&gt;the class.  However, this also means a decent space optimization if&lt;br /&gt;your ratio of incomplete tasks to complete tasks is very high - once a&lt;br /&gt;task is marked as completed it is likely to get discarded and hence&lt;br /&gt;garbage collected.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I think it's only confusing (again, this is very subjective) if you&lt;br /&gt;try to mix the two uses cases in one class:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Confusing:&lt;br /&gt;  completed = 0&lt;br /&gt;  def __init__(self):&lt;br /&gt;      self.completed = False&lt;br /&gt;  @classmethod&lt;br /&gt;  def complete(cls, confusingInstance):&lt;br /&gt;       cls.completed += 1&lt;br /&gt;       confusingInstance.completed = True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Thanks for the feedback.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;[End email response]&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-7270234660102318516?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/7270234660102318516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/10/pymag-multiple-inheritance.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7270234660102318516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7270234660102318516'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/10/pymag-multiple-inheritance.html' title='Class Variables'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-6087298860463553993</id><published>2008-10-09T05:38:00.000-07:00</published><updated>2008-10-09T09:08:14.943-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puzzles'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Lexical Scope</title><content type='html'>&lt;p&gt;So, briefly on the topic of &lt;a href="http://en.wikipedia.org/wiki/Scope_(programming)#Static_scoping_.28also_known_as_lexical_scoping.29"&gt;lexical scope&lt;/a&gt;, what does the following print?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def f():&lt;br /&gt;    funcs = []&lt;br /&gt;    for i in range(5):&lt;br /&gt;        def g():&lt;br /&gt;            print i&lt;br /&gt;        funcs.append(g)&lt;br /&gt;    return funcs&lt;br /&gt;&lt;br /&gt;funcs = f()&lt;br /&gt;for func in funcs:&lt;br /&gt;    func()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-6087298860463553993?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/6087298860463553993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/10/lexical-scope.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6087298860463553993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/6087298860463553993'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/10/lexical-scope.html' title='Lexical Scope'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-7617180940464207398</id><published>2008-10-08T06:00:00.000-07:00</published><updated>2008-10-09T05:32:52.806-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twisted'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>Deferred Task Queue</title><content type='html'>&lt;p&gt;&lt;b&gt;Problem&lt;/b&gt;: You have a queue of tasks to manage but only &lt;em&gt;n&lt;/em&gt; should run at a time.  An example of this is some CPU-intensive task where running more than a fixed number of tasks decreases your overall throughput due to context switching.  Sometimes the precise number is simplified to the number of CPUs you have to work with. ( Insert actual numbers here ;)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A simple queuing mechanism is the perhaps the most obvious solution to the above problem.  I wrote one Task Queue implementation which was pretty terrible and required you to "pump" initial events - but only a certain number to "start" the queue.  I won't post the code for that here.  However, I revisited the problem yesterday and came up with some simple code which seems to do the job nicely.  (Note, this is for an application using &lt;a href="http://twistedmatrix.com"&gt;Twisted&lt;/a&gt;, hence "Deferred Task Queue".  In a producer/consumer thread-based model where consumers are threads in fixed-size thread-pool, the problem is already solved by just using Python's Queue and letting the consumers pull jobs off the queue - i.e. the size of thread pool dictates how many jobs can run concurrently.)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class TaskQueue:&lt;br /&gt;&lt;br /&gt;    def __init__(self, concurrentMax=cpuCount()):&lt;br /&gt;        self.concurrentMax = concurrentMax&lt;br /&gt;        self._running = 0&lt;br /&gt;        self._queued = []&lt;br /&gt;&lt;br /&gt;    def push(self, f, *args, **kwargs):&lt;br /&gt;        if self._running &lt; self.concurrentMax:&lt;br /&gt;            self._running += 1&lt;br /&gt;            return f(*args, **kwargs).addBoth(self._try_queued)&lt;br /&gt;        d = defer.Deferred()&lt;br /&gt;        self._queued.append((f, args, kwargs, d))&lt;br /&gt;        return d&lt;br /&gt;&lt;br /&gt;    def _try_queued(self, r):&lt;br /&gt;        self._running -= 1&lt;br /&gt;        if self._running &lt; self.concurrentMax and self._queued:&lt;br /&gt;            f, args, kwargs, d = self._queued.pop(0)&lt;br /&gt;            self._running += 1&lt;br /&gt;            actuald = f(*args, **kwargs).addBoth(self._try_queued)&lt;br /&gt;            actuald.chainDeferred(d)&lt;br /&gt;        if isinstance(r, failure.Failure):&lt;br /&gt;            r.trap()&lt;br /&gt;        return r&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;Note that the above implementation is missing a notion of "capacity" - which might be important for a more general solution. My application actually handles capacity external to queue, but there might be some benefit in internalizing the concept and raising exceptions on push() when capacity is exceeded.  I'm still undecided on this.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The interface is pretty straightforward.  You have a function &lt;em&gt;f&lt;/em&gt; (and its arguments) that returns a Deferred and that you want to call (eventually).  For example, &lt;em&gt;doSomeStuff()&lt;/em&gt; below simply returns a Deferred object that will fire after 2 seconds have elapsed:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def doSomeStuff(a, b=None):&lt;br /&gt;    print 'doSomeStuff(%s, %s) called: %f' % (a, b, time.time())&lt;br /&gt;    def finishUp():&lt;br /&gt;        print 'doSomeStuff(%s, %s) finished: %f' % (a, b, time.time())&lt;br /&gt;        d.callback('done %d %d' % (a, b))&lt;br /&gt;    d = defer.Deferred()&lt;br /&gt;    reactor.callLater(2.0, finishUp)&lt;br /&gt;    return d&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Let's queue up some calls to &lt;em&gt;doSomeStuff()&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;taskq = TaskQueue(3)&lt;br /&gt;taskq.push(doSomeStuff, 1, b=2)&lt;br /&gt;taskq.push(doSomeStuff, 2, b=3)&lt;br /&gt;taskq.push(doSomeStuff, 3, b=4)&lt;br /&gt;taskq.push(doSomeStuff, 4, b=5)&lt;br /&gt;taskq.push(doSomeStuff, 5, b=6)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output of the above would be something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;doSomeStuff(1, 2) called: 1223472790.943929&lt;br /&gt;doSomeStuff(2, 3) called: 1223472790.944112&lt;br /&gt;doSomeStuff(1, 2) finished: 1223472792.947769&lt;br /&gt;doSomeStuff(3, 4) called: 1223472792.947887&lt;br /&gt;doSomeStuff(2, 3) finished: 1223472792.948004&lt;br /&gt;doSomeStuff(4, 5) called: 1223472792.948162&lt;br /&gt;doSomeStuff(3, 4) finished: 1223472794.951818&lt;br /&gt;doSomeStuff(5, 6) called: 1223472794.951937&lt;br /&gt;doSomeStuff(4, 5) finished: 1223472794.952080&lt;br /&gt;doSomeStuff(5, 6) finished: 1223472796.955836&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;As you can see, as soon as one of the called functions completes its job, the next one queued is called.  There is no need to tell the queue to start doing its work - just push jobs onto the queue.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The technique that makes this work is simply exploiting the elegance of Deferreds by "sneaking" in a check for pushed jobs that have been queued via Deferred's &lt;em&gt;addBoth()&lt;/em&gt; method.  For those of you unfamiliar with how a Deferred works in Twisted, you should &lt;a href="http://twistedmatrix.com/projects/core/documentation/howto/async.html#deferreds"&gt;the deferred section of Twisted's asynchronous programming guide&lt;/a&gt; and then &lt;a href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html"&gt;this document on Deferreds&lt;/a&gt; ... and maybe &lt;a href="http://twistedmatrix.com/projects/core/documentation/howto/gendefer.html"&gt;this one too&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What makes this useful is that I can treat a call to &lt;em&gt;push()&lt;/em&gt; as if it were simply a call to the function being queued - no other messy API to tell the queue which callbacks or errbacks need to be invoked when the function is finally called.  The internal function &lt;em&gt;_try_queued()&lt;/em&gt; acts as a transparent pass-through gateway so the caller to &lt;em&gt;push()&lt;/em&gt; doesn't need to worry about adding a funky callback to translate some wrapped value or otherwise - again I'm eschewing unnecessary API details.  So for example:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# this&lt;br /&gt;taskq.push(doSomeStuff, 1, b=2).addCallback(cb).addErrback(eb)&lt;br /&gt;&lt;br /&gt;# is the same as&lt;br /&gt;doSomeStuff(1, b=2).addCallback(cb).addErrback(eb)&lt;br /&gt;&lt;br /&gt;# ... just with queuing behavior under the hood&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In closing, in the context of asynchronous programming or otherwise, I've begun to strongly believe "&lt;a href="http://blog.ianbicking.org/pytest.html"&gt;the best API is no API&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/1358941065293307736-7617180940464207398?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/7617180940464207398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/10/deferred-task-queue.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7617180940464207398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7617180940464207398'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/10/deferred-task-queue.html' title='Deferred Task Queue'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-1253029271805298611</id><published>2008-08-29T11:30:00.000-07:00</published><updated>2008-08-29T12:44:54.281-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python's vars()</title><content type='html'>&lt;p&gt;The builtin function &lt;em&gt;vars()&lt;/em&gt; in Python will give you the argument's &lt;em&gt;__dict__&lt;/em&gt; or the namespace of the object. That is the namespace of the object not the object and the names belonging to its class - an important distinction.  In short, it is simple a syntactic nicety over referencing the property &lt;em&gt;__dict__&lt;/em&gt; directly.  For example, contrast the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    &gt;&gt;&gt; namespace = vars(o)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;With:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    &gt;&gt;&gt; names = o.__dict__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;But for introspecting objects to produce some custom serialized form (&lt;a href="http://www.json.org/js.html"&gt;json&lt;/a&gt; comes to mind), this is likely not what you want to do.  This post will attempt to explain why not.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Say we want to explicitly convert an object to some more primitive form (a dictionary or list) and we use &lt;em&gt;vars()&lt;/em&gt; to introspect the attributes of the object.  Maybe our serialization function will also account for things we don't want to serialize - like things we don't want to expose over the network for security or bandwidth reasons.  Here's a simple example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    class Thing(object):&lt;br /&gt;        def __init__(self, a, b, secret=None)&lt;br /&gt;            self.a = a&lt;br /&gt;            self.b = b&lt;br /&gt;            self.secret = secret&lt;br /&gt;            self._fd = open('file.txt')&lt;br /&gt;&lt;br /&gt;    def dictifyThing(thing):&lt;br /&gt;        blacklisted = ['secret', '_fd']&lt;br /&gt;        data = dict(vars(thing))&lt;br /&gt;        for bl in blacklisted:&lt;br /&gt;            del data[bl]&lt;br /&gt;        return data&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That will work fine for this example. And so we're happy:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    &gt;&gt;&gt; thing = Thing( 1, 2, "don't tell anyone" )&lt;br /&gt;    &gt;&gt;&gt; dictifyThing(thing)&lt;br /&gt;    {'a': 1, 'b': 2}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A great (though not unique) feature of Python are &lt;a href="http://www.python.org/download/releases/2.2/descrintro/#property"&gt;properties&lt;/a&gt; which allows us to make derived read-only attributes on an object or attributes that carry side-effects upon setting.  For example, we might have an extension of &lt;em&gt;Thing&lt;/em&gt; where &lt;em&gt;a&lt;/em&gt; is read-only and derived from the value of &lt;em&gt;b&lt;/em&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    AnotherThing(Thing):&lt;br /&gt;&lt;br /&gt;       def __init__(self, b, secret=None):&lt;br /&gt;          self.b = b&lt;br /&gt;          self._fd = open('data.txt')&lt;br /&gt;&lt;br /&gt;       @property&lt;br /&gt;       def a(self):&lt;br /&gt;           return self.b - 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;However, &lt;em&gt;dictifyThing()&lt;/em&gt; will no longer work the way we want it to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    &gt;&gt;&gt; thing = AnotherThing(2, "open sesame")&lt;br /&gt;    &gt;&gt;&gt; dictifyThing(thing)&lt;br /&gt;    { 'b': 2 }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One should expect this behavior, because &lt;em&gt;a&lt;/em&gt;, being a derived property, isn't actually part of the namespace of an instance of &lt;em&gt;AnotherThing&lt;/em&gt;.  This conversely illustrates another advantage of properties: calculating the value of &lt;em&gt;a&lt;/em&gt; and setting as a normal attribute is undesirable both for space efficiency reasons and the fact that we wouldn't have a definite way of constraining the numerical relationship between &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Does this mean we can't write a decent version &lt;em&gt;dictifyThing()&lt;/em&gt;? No, probably the more commonly known &lt;em&gt;dir()&lt;/em&gt;  will give us all the referenceable names of an object - which then must include class attributes.  We can use this to write something nicer:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def dictifyThing(thing):&lt;br /&gt;        blacklisted = ['secret']&lt;br /&gt;        data = {}&lt;br /&gt;        for name in ( n for n in dir(thing) if n[0] != '_' and&lt;br /&gt;                      n not in blacklisted ):&lt;br /&gt;           data[name] = getattr(thing, name)&lt;br /&gt;        return name&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now our encoding scheme works nicely for both &lt;em&gt;Thing&lt;/em&gt; and &lt;em&gt;AnotherThing&lt;/em&gt;.  A small improvement would be to use a higher-level function make defining new encoders simpler:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def _encode(include=(), exclude=()):&lt;br /&gt;        def f(o):&lt;br /&gt;            data = {}&lt;br /&gt;            if include:&lt;br /&gt;                for name in include:&lt;br /&gt;                    data[name] = getattr(o, name)&lt;br /&gt;                return data&lt;br /&gt;            for name in ( n for n in dir(thing) if n[0] != '_' and&lt;br /&gt;                          n not in exclude ):&lt;br /&gt;                data[name] = getattr(thing, name)&lt;br /&gt;            return data&lt;br /&gt;        return f&lt;br /&gt;&lt;br /&gt;    encodeThing = _encode(exclude=('secret'))&lt;br /&gt;    encodeFoo = _encode(include=('a','b','c'))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-1253029271805298611?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/1253029271805298611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/08/pythons-vars.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1253029271805298611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1253029271805298611'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/08/pythons-vars.html' title='Python&apos;s &lt;em&gt;vars()&lt;/em&gt;'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-1600061826358904782</id><published>2008-08-21T13:38:00.000-07:00</published><updated>2008-08-29T12:28:48.692-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='frameworks'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>I Smell Fear</title><content type='html'>&lt;p&gt;&lt;em&gt;I though it would be amusing to do a redacted blogpost.  After all, the assholes with power do this stuff all the time and for things that really  matter - life or death matters ... seriously.  The stupid blog post is the exact antithesis - things of relatively no matter whatsoever.  Were it to provoke one, such a reaction would be quite absurd.  So here it is - a repost of an internal blogpost from work replete with inked out sections (or "so much whiteout") like &lt;span style="background-color: #444; color: #444;"&gt;xxxx xxxx&lt;/span&gt;.  I hope the all-seeing corporate eye of Sauron  looming down on the piteous ant I am - above my head, my cube our ceiling and piercing through the clouded firmament shading all humble living beings on this green earth - looks kindly upon my ramblings here.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;[Begin repost]&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="background-color: #444; color: #444;"&gt;xxxxx xx xxxxxxxxxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxx,&lt;/span&gt; here's a little splash on the fire from my whiskey flask:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://antoniocangiano.com/2008/03/04/rails-is-the-best-thing-that-ever-happened-to-python/"&gt;http://antoniocangiano.com/2008/03/04/rails-is-the-best-thing-that-ever-happened-to-python/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;... Some great humor relating to differing attitudes towards marketing (that's the `sexy', in case you're wondering) between the Ruby and Python communities.  My favorite quote from the above:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;If Twisted Matrix was implemented in Ruby it would be advertised as the second coming ...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Anyhow, read on, because he's not really bashing Rails:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;So what does this mean for me personally? I’ll use them both, as I’m a firm believer in using the right tool for the right job.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The last point is the single most important: Use the Right Tool for the Right Job.  For the last few years (lets call them the Dark Ages now) in Enterprisey-Land, the motto has been One F***ing Tool for Every F***ing Job.  The are also variations on the motto that end in "... Or Else!"  &lt;span style="color: #444; background-color: #444;"&gt;x xxxx xxxx xxxxxx xxxxx xxxxxx xxxxx xx xxxxxx xx xxxxx xxxxxxxx xx xxxxxx xxx xxxx xxxx xxxxxx xxxx xxxxxx xxx xxxx x xxxxxx xxxxxxxx xxxx xxxxxxxxxxxxxx xxxx xx xxxxx xx xx xxxxxxx xxxxx xxxxx xx xxxxx xxxxxxxxx xx xxxxx xxxxxxx xxxx xx x xxxxxxxx xx xx xxx xxxxxxxxxxxxx  xxxxxx  xxxxx xxxx x xxxxxxxxxx xxxxxxxxxx xxxx xxxx xxxx xxxx xxx x xxx xx xxxxx xxx xxxxx xxx x xxxxxxx xxxxxxx xx xxxxxxx xx xx xxxx xx xx xxx xxxxxxxxx xx xxx xxxxx xx xxxxxxx xxx xxx xxx xxx xxx&lt;/span&gt; &lt;a href="#ismellfear-1"&gt;[1]&lt;/a&gt;&lt;span style="color: #444; background-color: #444;"&gt;x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Of course I don't have the statistics to back this (who does?), buy my perception (which is arguably valid considering I work day and night as a Java developer and mingle with other prisoners of the `Enterprise'), homebrew Java projects outside the scope of well-understood &lt;a href="#ismellfear-2"&gt;[2]&lt;/a&gt; frameworks (Spring MVC, Webwork) almost always necessitate a great amount of design decisions to be made up front.  To quote Glyph Lefkowitz &lt;span style="color: #444; background-color: #444;"&gt;xxxxx xxx x xxxxxxx&lt;/span&gt; in a recent &lt;a href="http://twistedmatrix.com/pipermail/twisted-python/2008-April/017352.html"&gt;discussion&lt;/a&gt; on &lt;a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python"&gt;twisted python&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;A design discussion is an unverified hypothesis.  There's no point in developing it into a theory until you have some further indication that it might be implemented.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The Spring team realized this and began a successful political campaign &lt;a href="#ismellfear-3"&gt;[3]&lt;/a&gt; against all things J2EE, and focused on implementations, instead of bullsh**, I-Smell-Fear, specifications.  (Notice, how politically correct I am in censoring my own writings.  I wish I could put asterisks in my speech as well.)&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Design decisions are made up front with most Java projects.  However, at a higher level, that a matter of individual programmer/architect or wider spanning community philosophy.  The same philosophy could be adopted by Pythonistas, Rubyists or Lispers (and it unfortunately is by some &lt;a href="http://springpython.python-hosting.com"&gt;people&lt;/a&gt; who haven't read &lt;a href="http://dirtsimple.org/2004/12/python-is-not-java.html"&gt;this&lt;/a&gt;), and you would end up with similar issues.  Note that I use the word `similar', not `same', because the issue is compounded in Java by the instilling of the up-front design into the lower-level implementation.  The instilling process isn't optional - it's demanded by static typing.  Static typing is not (always) a bad thing, and the rigid stance taken by static type puritans who love languages like Java and &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt; makes some sense when considering the legacy of weakly typed languages like C.  But that's a whole another story - but briefly, let's remind ourselves that Python and Ruby are strongly (not weakly) typed, but also dynamically typed which essentially enables you to punch an API in the face (with 2-5 lines of &lt;strong&gt;readable&lt;/strong&gt; code) if you don't like it, or even modify is ill behavior at runtime &lt;a href="#ismellfear-4"&gt;[4]&lt;/a&gt; if you can't convince the stubborn maintainer to fix bugs or funny smells.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now, one meme that remains in the sinking ship of Enterprise Snake-Oil &lt;a href="#ismellfear-5"&gt;[5]&lt;/a&gt; is that all the conveniences provided by dynamic languages are a wash because the end result is a bundle of cute little scripts &lt;a href="#ismellfear-6"&gt;[6]&lt;/a&gt; which suffer in performance and are hacked out and difficult to maintain.  Let me go ahead and call bullsh** on that. &lt;span style="color: #444; background-color: #444;"&gt;x xxxx xxxxx xx xxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxx xxx xxxxxxxxxxxxx xx xxx xxxxxxx xxxxxxxxx xxx xxxxx xxx xxxxxx xx xxxxxx xxxx xxxxxxxxxxxxxxx xxxxx xx xxxxxxx xxxxxxxxx xx xxxxxxxx xxxxx xx xxxxxxxxxxxx xxxxxxxxxxx xx xxx xxxxxxxx xxxxxxxxxxx xxxxxxxx xxxx xx xxxxxxxx&lt;/span&gt; Java  combined with our fancy-schmancy IDE and all their attempts to slap developers on the wrist while they pound away on source code have done very little to keep us from sinning.  The only solutions to the problems that arise in bad Java programming are enforcing design patterns we're all slow to adopt: beware of the singleton, write components instead of final service classes with static methods (so you can actually write unit tests around things), use Spring (or replace Java with XML), etc.  In sum, understand &lt;strong&gt;all&lt;/strong&gt; the esoteric details of the Java programming language (event the &lt;em&gt;transient&lt;/em&gt; modifier, if serialization is important to you) while laying out classes and deciding on method signatures - again, these will be irreversible decisions that will lead to hate from your fellow developers who can't pragmatically work around your anti-patterns to facilitate better unit-testing, adaptive integration points, proper serialization, and other goals easily attained with dynamic languages.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Another meme is that Java (or more generally, static typing) facilitates quality (and security) through type safety.  On the security front, this is true in some &lt;a href="http://www.erights.org/"&gt;extreme cases&lt;/a&gt; - though it's a problem easily overcome in distributed computing by &lt;a href="http://allmydata.org/trac/tahoe"&gt;people with smarts&lt;/a&gt;.  Quality ensured through compilation is of course a joke - compilers don't know the requirements, they only speak 1s and 0s.  Ultimately, the larger task is preventing regressions, which can be done only with unit tests.  And there are plenty of Python projects that get this very right.  Take the unit test suite for the &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted project&lt;/a&gt; as an example: &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Ran 4113 tests in 172.023s&lt;br /&gt;&lt;br /&gt;PASSED (skips=62, expectedFailures=19, successes=4032)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Yeah, just a few tests there.  And yes, that's 172 seconds (not minutes).  I guess there are some equivalents in open source Ruby projects.  Ruby people?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ok, so my little blog entry is supposed to be about how the next alternatives to Java are apparently Ruby and Python and my own personal fear is that Ruby will be just the next Java - and people will claim I'm not &lt;em&gt;sexy&lt;/em&gt; enough with my old bag-o-tricks in Python &lt;a href="#ismellfear-7"&gt;[7]&lt;/a&gt; .. blah, blah, even though I know in my heart of hearts that "Python is the only acceptable implementation of Ruby".  Really, it takes more energy than I'm willing to expend to get into these silly arguments.  &lt;span style="color: #444; background-color: #444;"&gt;xx xx xxxx xxxxxxx xx xxx xxxxxxxxxxxxx xxx xxxx xxxxxxxx xxx xxx xxx xx x xxxx x xxxxx x xxx xxxxxxxxxx xxxx xxxxxxxx xxxx xxxxxxxxxx xxxxxxxxx xxxxxxx xxx xxxxxxxxxx xxxx x xxx xxxxxxxxxx xxxx xxxx xxxxx xxx xxxx xxxx xx xxxxxx xxxxxxxxxx xx xxxxxxxxx  xxx xx xx xxxxxx xxx xxx xxxx xxxx xxxx xxxx xxx xxxxxxxxx xxx xxx xxx xxxxxxxxxx xx xxxxx xxxxxxxxx xxxxxxxx xxx xxxxxxx xxx xxxxxxxxxxxx xx xxxxx xxxxx xx xxxxxx xxxx xxxx xxxx xxx x xxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxx xxx xxxxx xxxxxxxx xxxx&lt;/span&gt; at least one painful piledriver.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-1"&gt;[1]&lt;/a&gt; EST is an acronym for Enterprise Service Toilet.&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-2"&gt;[2]&lt;/a&gt; Well, let's just wave our hands and pretend like they're really well understood.&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-3"&gt;[3]&lt;/a&gt; There were some problems here as well.  It appeared the platform they were running on was build of some space-age cardboard, but on closer inspection, it ended be highly compressed XML - about 500K lines of it.  Oh ... And they basically reimplemented J2EE all over again - since that stuff is so tasty, right?  The best approach, in my jaded world-view, would have been to slit the Hegemon's throat, instead of knocking it's head with a bat and then proceed to built a neck brace for it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-4"&gt;[4]&lt;/a&gt; In Python, this is called monkey-patching (which involves trivial reassignment of unbound methods, functions in a module's namespace, etc), and Ruby facilitates `stepping into' classes.  Java offers some incomprehensible &lt;a href="http://jakarta.apache.org/bcel/index.html"&gt;bullsh**&lt;/a&gt; on this front, which will only necessitate 3 months of training before any developer can partially utilize it - of course it will likely continue to feel like acupuncture in your eyeballs when you revisit code leveraging such awe-inspiring byte-code futzing libraries.&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-5"&gt;[5]&lt;/a&gt; Ahh, rhetoric ... gotta love it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-6"&gt;[6]&lt;/a&gt; Yes, you can write applications with modules and namespaces.  Isn't that nifty?&lt;br /&gt;&lt;br /&gt;&lt;a name="ismellfear-7"&gt;[7]&lt;/a&gt; This is yet another meme affecting at least part of the Ruby community - Python is some old crusty crap no-one hacks with except dorky &lt;a href="http://www.enthought.com"&gt;research scientists&lt;/a&gt; who wear their pants up too high.  This is of course nonsense - and to paraphrase Zed Shaw: "Ruby will not lend you more appeal to the ladies."  Of course, Zed used his own branded terminology to convey the equivalent concept.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-1600061826358904782?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/1600061826358904782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/08/i-smell-fear.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1600061826358904782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1600061826358904782'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/08/i-smell-fear.html' title='I Smell Fear'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-630177145020047212</id><published>2008-08-11T05:39:00.000-07:00</published><updated>2008-08-29T12:25:31.528-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pyglet'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='opengl'/><title type='text'>Devil in the Shadows</title><content type='html'>&lt;p&gt;I've taken the first steps towards implementing shadows for &lt;a href="http://miru.enterthefoo.com"&gt;miru&lt;/a&gt; -- glorified 3d extensions (and a handful of arbitrary features) for &lt;a href="http://www.pyglet.org"&gt;pyglet&lt;/a&gt;.  I had avoided implementing a shadowing effect for miru for some time, for fear that my brain wouldn't be able to handle the math, or I'd get lost in the gnarlier details of the &lt;a href="http://www.glprogramming.com/red/"&gt;OpenGL&lt;/a&gt; API and just throw my hands up after hours of time trying to get it right.  Last night I was able to finally hammer out a proof of concept which still needs a lot more work (and maybe even more underlying library support) before I can build something decently generalized.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3043/2753475364_344a4f53b4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="http://farm4.static.flickr.com/3043/2753475364_344a4f53b4.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The technique I used to generate the shadows is referred to as shadow mapping - which is simply in theory but gets somewhat complicated in the implementation - in particular when you consider limitations of texture sizes for many common OpenGL drivers and other potential texture artifacts in a scene.  My own implementation was borrowed mostly from an examples in the excellent &lt;a href="http://www.amazon.com/OpenGL-SuperBible-Comprehensive-Tutorial-Reference/dp/0321498828/ref=pd_bbs_1?ie=UTF8&amp;s=books&amp;qid=1218464694&amp;sr=8-1"&gt;OpenGL(R) Super Bible&lt;/a&gt;--I guess I should return this to my company's library someday since I've been hogging it for several months now. Shadow mapping entails creating a depth texture which means copying the z-buffer from the perspective of a light looking down onto the scene into a texture region to be applied to objects in the scene using eye-linear texture coordinates.&lt;br /&gt;&lt;br /&gt;(&lt;em&gt;It should be noted here that the process I use is a somewhat old school way of shadow mapping, though not as old-school and crude as stencil testing.  With modern graphics hardware, vertex shaders and per-pixel lighting can be used to achieve much nicer and softer shadows and their penumbra. My goal is to first implement something using a traditional multipass technique and then try something more sophisticated with shaders--again, if my brain can deal with the math.&lt;/em&gt;)&lt;br /&gt;&lt;br /&gt;To illustrate the first step in the shadow mapping process, the following code (which assumes there is single globally bound texture object) could be run at start of a program and whenever the light moves in the scene:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        scene_radius = 95.0&lt;br /&gt;        light_to_scene_distance = math.sqrt(&lt;br /&gt;                light_pos[0]**2 + light_pos[1]**2 + light_pos[2]**2)&lt;br /&gt;        near_plane = light_to_scene_distance - scene_radius&lt;br /&gt;        field_of_view = miru.math3d.radians_to_degrees(2.0 *&lt;br /&gt;                math.atan(scene_radius / float(light_to_scene_distance)))&lt;br /&gt;&lt;br /&gt;        tmp = ( GLfloat * 16)()&lt;br /&gt;&lt;br /&gt;        glMatrixMode( GL_PROJECTION )&lt;br /&gt;        glLoadIdentity()&lt;br /&gt;        gluPerspective( field_of_view, 1.0, near_plane,&lt;br /&gt;                near_plane + (2.0 * scene_radius) )&lt;br /&gt;        glGetFloatv( GL_PROJECTION_MATRIX, tmp )&lt;br /&gt;        light_projection = euclid.Matrix4()&lt;br /&gt;        light_projection[:] = tmp[:]&lt;br /&gt;&lt;br /&gt;        # Move to light's perspective&lt;br /&gt;        glMatrixMode( GL_MODELVIEW )&lt;br /&gt;        glLoadIdentity()&lt;br /&gt;        gluLookAt( light.pos.x, light.pos.y, light.pos.z,&lt;br /&gt;                  0.0, 0.0, 0.0, 0.0, 1.0, 0.0 )&lt;br /&gt;        glGetFloatv( GL_MODELVIEW_MATRIX, tmp )&lt;br /&gt;        light_mview = euclid.Matrix4()&lt;br /&gt;        light_mview[:] = tmp[:]&lt;br /&gt;&lt;br /&gt;        # Clear the depth buffer only&lt;br /&gt;        glClear( GL_DEPTH_BUFFER_BIT )&lt;br /&gt;&lt;br /&gt;        # Remember the current shade model and setup driver state&lt;br /&gt;        ...&lt;br /&gt;&lt;br /&gt;        # do a render pass&lt;br /&gt;        render()&lt;br /&gt;&lt;br /&gt;        # Copy depth values into depth texture&lt;br /&gt;        glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,&lt;br /&gt;                         0, 0, shadow_width, shadow_height, 0 )&lt;br /&gt;&lt;br /&gt;        # Restore prior driver state&lt;br /&gt;        ...&lt;br /&gt;&lt;br /&gt;        # Setup up the texture matrix which will be use in eye-linear&lt;br /&gt;        # texture mapping&lt;br /&gt;        tex_matrix = euclid.Matrix4()&lt;br /&gt;        tex_matrix.translate(0.5, 0.5, 0.5).scale(0.5, 0.5, 0.5)&lt;br /&gt;        tex_matrix = (tex_matrix * light_projection) * light_mview&lt;br /&gt;        tex_matrix.transpose()&lt;br /&gt;        # Give us immediate access to ctypes arrays&lt;br /&gt;        tex_matrix = (&lt;br /&gt;            (GLfloat * 4)(*self.tex_matrix[0:4]),&lt;br /&gt;            (GLfloat * 4)(*self.tex_matrix[4:8]),&lt;br /&gt;            (GLfloat * 4)(*self.tex_matrix[8:12]),&lt;br /&gt;            (GLfloat * 4)(*self.tex_matrix[12:16])&lt;br /&gt;        )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the above I omitted some details such as setting up and tearing down the required driver state. (I'll post a link to the completed source code at a later time.)  The import parts are all intact, though, which include copying over the depth buffer to the current bound texture:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,&lt;br /&gt;                         0, 0, shadow_width, shadow_height, 0 )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It is important to note that this is done after rendering the scene, of course, and setting the view matrix according to the light's perspective.  This are just simple API details, but the math comes at the end (saving the best for last):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        tex_matrix = euclid.Matrix4()&lt;br /&gt;        tex_matrix.translate(0.5, 0.5, 0.5).scale(0.5, 0.5, 0.5)&lt;br /&gt;        tex_matrix = (tex_matrix * light_projection) * light_mview&lt;br /&gt;        tex_matrix.transpose()&lt;br /&gt;        ... translate into ctypes array&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;All the matrix operations are done using &lt;a href="http://partiallydisassembled.net/euclid.html"&gt;pyeuclid&lt;/a&gt; which is a pure-python library well-suited for graphics programming being focused on vector, matrix and quaternion operations; however, I've submitted a patch to add transpose() methods which are not currently provided.  In first two lines we translate and scale an initial identity matrix by 0.5 along each axis to create a &lt;em&gt;bias&lt;/em&gt; which allows us to translate the actual coordinates captured in the range (-1,1) to the range (0,1)--&lt;em&gt;normalized device coordinates&lt;/em&gt;, or screen coordinates.   We multiple the bias matrix by the light projection and model view matrix acquired in earlier steps and transpose the result to produce the final texture matrix we'll use to map the texture onto objects in the scene. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Once we have the texture matrix, we're ready to apply the texture.  First of all, the texture should be bound as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY)&lt;br /&gt;    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)&lt;br /&gt;    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)&lt;br /&gt;    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)&lt;br /&gt;    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can draw the objects in the scene with the usual dizzying array of OpenGL calls:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    if not ambient_shadow_ext:&lt;br /&gt;       # do an ambient pass&lt;br /&gt;       ...&lt;br /&gt;&lt;br /&gt;    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light)&lt;br /&gt;    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light)&lt;br /&gt;&lt;br /&gt;    glPushAttrib(GL_ENABLE_BIT)&lt;br /&gt;&lt;br /&gt;    glEnable(GL_TEXTURE_2D)&lt;br /&gt;    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,&lt;br /&gt;                    GL_COMPARE_R_TO_TEXTURE)&lt;br /&gt;&lt;br /&gt;    glEnable(GL_TEXTURE_GEN_S)&lt;br /&gt;    glEnable(GL_TEXTURE_GEN_T)&lt;br /&gt;    glEnable(GL_TEXTURE_GEN_R)&lt;br /&gt;    glEnable(GL_TEXTURE_GEN_Q)&lt;br /&gt;    glTexGenfv(GL_S, GL_EYE_PLANE, tex_matrix[0]))&lt;br /&gt;    glTexGenfv(GL_T, GL_EYE_PLANE, tex_matrix[1]))&lt;br /&gt;    glTexGenfv(GL_R, GL_EYE_PLANE, tex_matrix[2]))&lt;br /&gt;    glTexGenfv(GL_Q, GL_EYE_PLANE, tex_matrix[3]))&lt;br /&gt;&lt;br /&gt;    ... render objects in scene&lt;br /&gt;&lt;br /&gt;    glPopAttrib()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The most interesting part of the above is the fact we get to use all texture coordinates: S, T, R, and Q.  For the uninitiated, only S and T coordinates are explicitly set for more common texture operations which correspond to (row, column) pixel coordinates in the image.  The OpenGL programming guide gives a brief overview of the R, Q coordinates and their role in &lt;a href="http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node79.html#projtex.section"&gt;projective textures&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So I only have more hurdles ahead to get this into decent shape for use in most any 3d application.  The current form so far is more or less a direct translation of the example from the aforementioned book and inherits its limitations.  First of all, by convenience all the objects rendered use color as their sole material for shading.  Were we to have textured objects in the scene some additional work would have to be done (namely, better &lt;a href="http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node60.html"&gt;multitexture&lt;/a&gt; abstractions in miru or pyglet) and some details regarding this would be incorporated in the resulting API for ShadowMap requiring specification of a texture unit as not to interfere with other multitexture applications beneath the shadow.  Next, the current application requires the screen to have dimensions that are powers of 2 - hence, the non-standard resolution of the screenshot above.  This is less than ideal of course, but can be remedied by rendering to an &lt;a href="http://en.wikipedia.org/wiki/Framebuffer_Object"&gt;FBO&lt;/a&gt; - which also calls for some more underlying library work.  I've seen some very cool work done with FBOs in the &lt;a href=" http://cocos2d.org/"&gt;cocos&lt;/a&gt; framework and hope to see this sink down into pyglet someday.  Otherwise I might try ripping pieces of it out for miru ;)&lt;br /&gt;&lt;br /&gt;&lt;p&gt;On a final note, I'm in the midst of some drastic &lt;a href="http://groups.google.com/group/pyglet-users/msg/94c221088e635e49"&gt;rewriting and reorganization of miru&lt;/a&gt;, phasing out the dirty bits--&lt;a href="http://hg.enterthefoo.com/Miru/file/95ce7e6dcf31/miru/mesh.py"&gt;miru.mesh&lt;/a&gt; and &lt;a href="http://hg.enterthefoo.com/Miru/file/95ce7e6dcf31/miru/environment.py"&gt;miru.environment&lt;/a&gt; in favor of &lt;a href="http://hg.enterthefoo.com/Miru/file/95ce7e6dcf31/miru/graphics.py"&gt;miru.graphics&lt;/a&gt; and &lt;a href="http://hg.enterthefoo.com/Miru/file/95ce7e6dcf31/miru/context.py"&gt;miru.context&lt;/a&gt;, respectively--and changing, or actually removing, some interfaces to defer directly to &lt;a href="http://pyglet.org/doc/api/pyglet.graphics-module.html"&gt;pyglet.graphics&lt;/a&gt; instead. This means things are proceeding slowly with some subtle breakage here and there.  In the long run, I think it will make miru a more coherent and useful library and provide smoother integration for other projects already exploiting pyglet for OpenGL state management.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-630177145020047212?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/630177145020047212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/08/devil-in-shadows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/630177145020047212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/630177145020047212'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/08/devil-in-shadows.html' title='Devil in the Shadows'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3043/2753475364_344a4f53b4_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-1820838949027868516</id><published>2008-08-01T10:00:00.000-07:00</published><updated>2008-08-01T10:10:34.064-07:00</updated><title type='text'>Iterators are of course not Iterable!</title><content type='html'>&lt;p&gt;This amuses me to no end:&lt;p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  Iterator&lt;String&gt; iter = properties.getKeys();&lt;br /&gt;  for (String key : iter) {&lt;br /&gt;    // do something with the key&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The above java will not compile, and the error is "Can only iterate over an array or an instance of java.lang.Iterable."  Apparently an Iterator isn't iterable!  Wow!  Isn't that so convenient?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-1820838949027868516?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/1820838949027868516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/08/this-amuses-me-to-no-end-iterator-iter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1820838949027868516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/1820838949027868516'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/08/this-amuses-me-to-no-end-iterator-iter.html' title='Iterators are of course not Iterable!'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-7326013055747634305</id><published>2008-07-08T10:47:00.000-07:00</published><updated>2008-07-08T10:50:41.122-07:00</updated><title type='text'>New Blog</title><content type='html'>To the incomprehensibly vast readership of my previous blog (&lt;a href="http://djfroofy.livejournal.com"&gt;http://djfroofy.livejournal.com&lt;/a&gt;).  I've started a new blog &lt;a href=""&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-7326013055747634305?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/7326013055747634305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/07/new-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7326013055747634305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/7326013055747634305'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/07/new-blog.html' title='New Blog'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1358941065293307736.post-298638615161565145</id><published>2008-07-08T09:29:00.000-07:00</published><updated>2008-08-29T12:26:00.374-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Arrogant Maven, You Fill my Soul with Hatred</title><content type='html'>&lt;p&gt;Unfortunately, I have to do work with java a lot.  But even more unfortunately, I have to cope with a bloated all-in-one build tool called &lt;a href="http://maven.apache.org/"&gt;maven&lt;/a&gt;.  Today I was doing a local build for testing some changes in a web application and typed the usual command:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ mvn -Dmaven.test.skip=true -Denv=local war:war-exploded&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;For the curious, this builds a web application.  Notice how I've specified "maven.test.skip=true" - this means to skip testing and just go straight to the build.  That's right, &lt;em&gt;maven&lt;/em&gt; by default wants to run unit tests for you amongst other miscellaneous tasks unrelated to compiling code.  The problem is, by munging this functionality into one tool, the other roles of the tool are taken for granted - our association with it is linked most often to its primary role (building a jar or web application).  Many developers pick up the habit of always using the &lt;em&gt;skip tests&lt;/em&gt; flag because the perception of testing in the context of a build tool becomes: "Oh, that's the thing that slows down my build."&lt;/p&gt;&lt;br /&gt;&lt;p&gt;My argument is almost a wash, because ultimately unit testing on any production code base should be done in automated fashion leveraging tools like &lt;a href="http://buildbot.net"&gt;buildbot&lt;/a&gt;.  Nonetheless, in an ideal world, a developer should assume the responsibility of running tests before pushing changes to the repository.  I believe the steps to follow become clearer to a developer when these roles are cleanly separated into the right tools for the right job.  A generic example:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ build&lt;br /&gt;$ runtests&lt;br /&gt;$ generate-docs&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Yes, &lt;em&gt;maven&lt;/em&gt; wants to do all these things for you (and oh so much more) because the developers failed to appreciate an important tenet of the Unix philosophy: &lt;a href="http://en.wikipedia.org/wiki/Unix_philosophy#Mike_Gancarz:_The_UNIX_Philosophy"&gt;"Make each program do one thing well."&lt;/a&gt;  &lt;em&gt;maven&lt;/em&gt; might be argued to do a few very simple things well once you've spent a few weeks mastering its dense XML-based &lt;a href="http://maven.apache.org/pom.html"&gt;configuration&lt;/a&gt;.  Even once you've mastered the ugly nuances of the project object model, &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html"&gt;transitive dependencies&lt;/a&gt; (which invariably get in a tangle when you introduce in-house repositories), &lt;a href="http://maven.apache.org/settings.html"&gt;site-specific configurations&lt;/a&gt; (which often breaks &lt;em&gt;maven&lt;/em&gt;'s design for portability), the convoluted &lt;a href="http://maven.apache.org/developers/mojo-api-specification.html"&gt;plugin system&lt;/a&gt;, etc., etc., you just end with radically different aspects of a project's build life-cycle all munged into one tool.  And developers on your team who are smart enough not to waste time becoming a guru at all this mess, will only learn:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ mvn -Dmaven.test.skip=true ...&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1358941065293307736-298638615161565145?l=blog.enterthefoo.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.enterthefoo.com/feeds/298638615161565145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.enterthefoo.com/2008/07/arrogant-maven-you-fill-my-soul-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/298638615161565145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1358941065293307736/posts/default/298638615161565145'/><link rel='alternate' type='text/html' href='http://blog.enterthefoo.com/2008/07/arrogant-maven-you-fill-my-soul-with.html' title='Arrogant Maven, You Fill my Soul with Hatred'/><author><name>djfroofy</name><uri>http://www.blogger.com/profile/16090531726775133893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_kcQvXqqF6KM/St92ZJj7osI/AAAAAAAAAeM/qLSef2ndk6I/S220/pigeonhill-logo2-md.png'/></author><thr:total>0</thr:total></entry></feed>
