<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>So Jake Says &#187; Misc</title>
	<atom:link href="http://www.jakevoytko.com/blog/category/that-which-belongs-nowhere-else/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jakevoytko.com/blog</link>
	<description>Ye Olde Computer Science Blogge</description>
	<lastBuildDate>Sun, 17 Jan 2010 15:16:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>A Code Workaround for a Busted Furnace</title>
		<link>http://www.jakevoytko.com/blog/2010/01/17/a-code-workaround-for-a-busted-furnace/</link>
		<comments>http://www.jakevoytko.com/blog/2010/01/17/a-code-workaround-for-a-busted-furnace/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 15:16:00 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[furnace]]></category>
		<category><![CDATA[threading]]></category>
		<category><![CDATA[workaround]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=406</guid>
		<description><![CDATA[warmup.cpp: [code] Late last December, I woke up and it was freezing in my apartment. I checked the thermostat, and it was already less than 60 degrees! I turned it from hot to cold to hot. And again. I turned it all the way up. The furnace never clicked on. COME ON! I checked, and [...]]]></description>
			<content:encoded><![CDATA[<p>warmup.cpp: [<a href="http://github.com/jakevoytko/warmup">code</a>]</p>
<p>Late last December, I woke up and it was <strong>freezing</strong> in my apartment. I checked the thermostat, and it was already less than 60 degrees! I turned it from hot to cold to hot. And again. I turned it all the way up. The furnace never clicked on. COME ON! I checked, and the pilot light was on, so I had no choice but to call maintenance to get it fixed.</p>
<p>Most days this wouldn&#8217;t have been a problem, since it would be fixed while I was at work, but I was in my end-of-year vacation-burning crunch. Maintenance always fix minor problems really fast, so I knew it would take all day to come and fix the heater. Sure enough, help didn&#8217;t arrive until 6PM.</p>
<p>I tried lying motionless on the floor under some blankets and played some Assassin&#8217;s Creed 2. This worked for an hour or so, but if I&#8217;m at home all day and not working on something on the computer, I start to feel like a waste. This was in the middle of trying to get <a href="http://www.vocabdojo.com/">a side project</a> of mine off the ground, and I wanted to get a beta version working before returning to work in January.</p>
<p>Could I use my laptop as a heater? It gets pretty warm when the CPU runs at full blast on one core. If I kept both going for hours, would that be enough?</p>
<p>8 minutes later, I had a C++ program that ran 2 CPUs at full blast. I hate picking C++ for a personal project, but I&#8217;ve used it for 10 years and I&#8217;m just not familiar enough with any other language&#8217;s CPU usage patterns to do the work that quickly. I probably didn&#8217;t have to worry, but I was cold!</p>
<p>The program, <code>warmup</code>, runs NUM_CPU copies of this thread:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> fn<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">bool</span> <span style="color: #000040;">*</span>go<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">double</span> a <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">static</span> mt19937 rng<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">static_cast</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #0000ff;">unsigned</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">time</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  normal_distribution<span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #0000ff;">double</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span> norm_dist<span style="color: #008000;">&#40;</span><span style="color:#800080;">1.0</span>, <span style="color:#800080;">1.0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  variate_generator<span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span>mt19937<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>, normal_distribution<span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #0000ff;">double</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span> <span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span>
  normal_sampler<span style="color: #008000;">&#40;</span>rng, norm_dist<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>go<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">double</span> val <span style="color: #000080;">=</span> normal_sampler<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    a <span style="color: #000040;">+</span><span style="color: #000080;">=</span> val<span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
  <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>I already had Boost, and I&#8217;d never used their pRNGs before, so I decided if it was a copy/paste job, I would give them a test run. Sure enough, it plugged right in.</p>
<p>The main function is even simpler:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">bool</span> go <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
  boost<span style="color: #008080;">::</span><span style="color: #007788;">scoped_ptr</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">thread</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span> threads<span style="color: #008000;">&#91;</span>NUM_THREADS<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i<span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span>NUM_THREADS<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
  threads<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">reset</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">thread</span><span style="color: #008000;">&#40;</span>fn, <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>go<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
  std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> asdf<span style="color: #008080;">;</span>
  <span style="color: #0000dd;">cout</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #FF0000;">&quot;enter any input and hit &amp;lt;Enter&amp;gt; to kill&quot;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span>endl<span style="color: #008080;">;</span>
  <span style="color: #0000dd;">cin</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span>asdf<span style="color: #008080;">;</span>
&nbsp;
  go <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i<span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span>NUM_THREADS<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    threads<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #000040;">-</span><span style="color: #000040;">&amp;</span>gt<span style="color: #008080;">;</span>join<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Within 12 minutes of starting, I was nice and toasty!</p>
<p>I posted the code on Github in case I needed it somewhere else: [<a href="http://github.com/jakevoytko/warmup">code</a>]<br />
﻿</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=406&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2010/01/17/a-code-workaround-for-a-busted-furnace/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Languages and Axioms</title>
		<link>http://www.jakevoytko.com/blog/2009/03/10/languages-and-axioms/</link>
		<comments>http://www.jakevoytko.com/blog/2009/03/10/languages-and-axioms/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 04:00:04 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Programming Languages]]></category>
		<category><![CDATA[Clojure]]></category>
		<category><![CDATA[Paul Graham]]></category>
		<category><![CDATA[reaxiomization]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=378</guid>
		<description><![CDATA[I learned Common Lisp last summer. I had been using some combination of Python, C++, C, and Java for about 8 years, and I wanted to break out of my popular language box. I was more or less attracted to the &#8220;data as code&#8221; idea, but really it had a bunch of selling points that [...]]]></description>
			<content:encoded><![CDATA[<p>I learned Common Lisp last summer. I had been using some combination of Python, C++, C, and Java for about 8 years, and I wanted to break out of my popular language box. I was more or less attracted to the &#8220;data as code&#8221; idea, but really it had a bunch of selling points that I would have appreciated:</p>
<ul>
<li> Its data was stored in the same structures as its program.</li>
<li> It had macros that were powerful and simple. That&#8217;s huge coming from C++.</li>
<li> It was REPL-based, something I never took advantage of with Python.</li>
<li> You could create new code on-the-fly at runtime from lists.</li>
<li> Completely dynamic and backed by garbage collection.</li>
<li>The language itself is very mutable.</li>
</ul>
<p>The sum of its parts was greater than anything that I had ever used before, and it quickly became my favorite language. I learned quite a bit about functional programming techniques, did some experimentation with image processing and database application programming, and worked through all of Graham&#8217;s  <a href="http://www.amazon.com/ANSI-Common-Prentice-Artificial-Intelligence/dp/0133708756?ie=UTF8&amp;s=books&amp;qid=1215999519&amp;sr=8-1">ANSI Common Lisp</a> and large swaths of Norvig&#8217;s <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FParadigms-Artificial-Intelligence-Programming-Studies%2Fdp%2F1558601910%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1216001266%26sr%3D8-1&amp;tag=jakvoyshom-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325">Paradigms of Artificial Intelligence Programming.</a></p>
<p>Recently, a nagging though started to cross my mind: <strong>What if I didn&#8217;t go far enough to break out of my box?</strong></p>
<p>That didn&#8217;t happen until two weeks ago, when I started porting <a href="http://github.com/jakevoytko/genesis/tree/master">Genesis</a>, my toy <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">genetic algorithm</a> framework, to <a href="http://clojure.org/">Clojure</a> for fun. I wasn&#8217;t very aware of the features of Clojure: I knew that it was a Lisp on the JVM and that it supported <a href="http://en.wikipedia.org/wiki/Software_Transactional_Memory">Software Transactional Memory</a>, but I didn&#8217;t think it would be  that different from Common Lisp aside from Java interoperability.</p>
<p>To clarify, I expected that the primary method of manipulating Clojure would be list-based, and that it would still mostly turn a blind eye towards mutable data and multithreading issues, with the option of phrasing memory updates in terms of transactions if you were using multithreaded applications.</p>
<p>Clojure turned out to be different than any language that I had ever tried &#8211; save my forays into <a href="http://haskell.org/">Haskell</a> to grok enough syntax to follow <a href="http://blog.sigfpe.com/">sigfpe</a>&#8216;s easier articles.  If you trust the language and work with the core Clojure data structures, it takes a lot of the worrying about parallel programming out of your hands. Its creator, Rich Hickey, ended up with a language that has a good balance between functional programming and practicality. It is definitely a good Modern Programming Language.</p>
<h2>You Said Something About A Box..?</h2>
<p>Right, I said I didn&#8217;t go far enough outside of my comfort zone when learning Common Lisp. That&#8217;s really only half true.</p>
<p>From the perspective of programming, Common Lisp is a great language. Using the functional programming primitives provided on top of lists feels very natural, and I was able to work on complicated problems with relative ease. Even though I don&#8217;t use the macro system in Common Lisp very often, it usually provides a great fallback for either refactoring or changing the way the problem can be represented. The REPL is just icing on the cake.</p>
<p>However, not all is flowers and roses. Looking at Common Lisp from perspectives other than single-threaded programming, it begins to look mortal! For instance, the Common Lisp standard was written without a thought to having multiple threads of execution. Although most implementations provide extra support for multithreading, you&#8217;re back in the same locking boat that you were with any of the other popular languages once you need to share mutable data. Naturally, the syntax for things like grabbing mutexes is easier with Lisp than with other languages thanks to the &#8220;with-&#8221; design pattern for macro writing, but you&#8217;re not gaining much with respect to avoiding race conditions.</p>
<p>Looking at it from a data-processing perspective, functional programming is easy in Common Lisp, but it isn&#8217;t required at all. There&#8217;s nothing stopping the programmer from falling back into using local mutable state, functions with side-effects on global variables, and destructive functions. Combined with the single-thread design, that&#8217;s fine. You can&#8217;t avoid state all of the time, and I don&#8217;t go out of my way to be strictly functional. That&#8217;s how most other languages are designed. Hell, the Common Lisp standard even offers a whole slew of functions that are destructive for the sake of efficiency!</p>
<p>I&#8217;m only really getting at the fact that even the ultra-flexible of Common Lisp wasn&#8217;t written to handle all computing scenarios.</p>
<p>Some languages have support for neat automatic threading features: Haskell has extensions where type annotations can allow automatic parallelization, and you can use <a href="http://openmp.org/wp/">OpenMP</a> in C++ for automatic parallel processing. For those wondering, Erlang is somewhere on my list of languages to take a look at, but it has to wait its turn! I&#8217;m still having too much fun with Lisps.</p>
<h2>Axiomization and Language Design</h2>
<p>Love him or hate him, Paul Graham has written quite a bit about the design of Arc. I&#8217;m not going to talk about it directly, but I will borrow his idea of <a href="http://www.paulgraham.com/core.html">reaxiomizing the core of a language</a> as a means of producing better code on top of it. He mentions axioms as neither primitives nor library functions, but I will consider primitives as well.</p>
<p>I&#8217;ve talked about this a little in the past. For instance, I&#8217;ve made the case for operator overloading in Java. It was explicitly verboten in Java, as decreed by the designers. In fact, written in an early Java whitepaper titled &#8220;<a href="http://java.sun.com/docs/white/langenv/Simple.doc2.html#4098">The Java Language Environment</a>&#8220;,</p>
<blockquote><p><strong>2.2.7 No More Operator Overloading</strong></p>
<p>There are no means provided by which programmers can overload the standard arithmetic operators. Once again, the effects of operator overloading can be just as easily achieved by declaring a class, appropriate instance variables, and appropriate methods to manipulate those variables. Eliminating operator overloading leads to great simplification of code.</p></blockquote>
<p>By the letter of their assertions, they were correct. A lot of programmers would <em>never</em> need operator overloading to produce good code. In fact, if you&#8217;re using it just for the sake of expressiveness, you&#8217;re going to produce an unintuitive hodgepodge most of the time. However, a small but powerful minority &#8211; particularly those who do mathematical work for a living &#8211; would absolutely benefit from being able to write inline operators. I mean honestly, have you ever tried to use a <code>BigInteger</code> to implement something more complicated than RSA?  The best that will happen is that it will end up&#8230; verbose.</p>
<p>Essentially, leaving out operator overloading forced Java to be more verbose and/or less readable than it needed to be. Leaving it in as an &#8216;axiom&#8217; could measurably produce more compact, readable code for programmers who used it judiciously.</p>
<p>As an aside for those who think I&#8217;m just trolling Java, there is definitely a great Java feature for each one that misses the mark. For instance, the <code>enum</code>s in Java follow the idea to its logical conclusion.</p>
<p>If you&#8217;ve been incensed by my Java discussion or are otherwise unsure that axiomization could lead to a better language, let&#8217;s look back at Lisp. Lisp changes quite a bit if you remove utility functions like <code>reduce</code>: it would break a lot of the compactness of the language and ruin some otherwise good functional programming. Now, it doesn&#8217;t support operator overloading, per se, but there&#8217;s nothing stopping you from changing the language to support it.</p>
<h2>Where the Hell is All of This Going?</h2>
<p>Back to Clojure! Clojure is based on a much different set of axioms than many of the popular languages. At its core, we see support for thread-safe data structures whose data are immutable and persistent. These were written in as axioms to the language, and you can make some good predictions for the language, assuming people stick with it.</p>
<p>The biggest one is that as libraries are converted to Clojure or abstract away their Java API, Clojure will develop a large set of libraries that could be given a thread-safe guarantee.  For my day job, I work in a C++ shop that uses a bunch of C libraries, and we need to constantly be aware of whether or not our base libraries are thread-safe. My workplace recently developed a non-Clapack fork of our linear algebra abstraction for this reason: using libraries that aren&#8217;t designed to be threadsafe in a multithreaded environment builds bombs.</p>
<p>I&#8217;m too young to get a sense of what the next 10 years of programming languages might look like &#8211; but if you pressed me, it would look a lot like it does today, and we wouldn&#8217;t be better off for it. The languages that are currently in the design phase are slowly adding quite a bit of features while remaining mostly the same: for instance, C++ is getting a makeover that includes concepts, lambdas, futures, and a multithreading primitive.  I&#8217;ve known C++ for over half of my life (holy shit!), and a lot of the features are sorely needed. However, it&#8217;ll be an incremental improvement at the cost of obscure compiler bugs and increased complexity.</p>
<p>These aren&#8217;t easy problems: for instance, if you didn&#8217;t care a lick about any external concerns like backwards compatibility and wanted to change C++ to support lambdas, how could you without just tacking it on? However, we have new languages that can pick up where the old languages left off, and continuing Fred Brooks&#8217; prediction, there will be no silver bullet, only incremental improvements. Languages like Clojure are a step in the right direction as far as testing new computing ideas.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=378&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2009/03/10/languages-and-axioms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Starting From Scratch</title>
		<link>http://www.jakevoytko.com/blog/2009/02/02/starting-from-scratch/</link>
		<comments>http://www.jakevoytko.com/blog/2009/02/02/starting-from-scratch/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 05:00:36 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[Linus Torvalds]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Podcast]]></category>
		<category><![CDATA[starting from scratch]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=367</guid>
		<description><![CDATA[I believe that everyone hates the feeling of starting from scratch, regardless of age or experience. This will cause people who should know better to make bad decisions, even misleading people who are conscious of the effect. In my mental model of knowledge, I split skills between three major mastery levels: Those we can use [...]]]></description>
			<content:encoded><![CDATA[<p>I believe that everyone <em>hates</em> the feeling of starting from scratch, regardless of age or experience. This will cause people who should know better to make bad decisions, even misleading people who are conscious of the effect.</p>
<p>In my mental model of knowledge, I split skills between three major mastery levels:</p>
<ul>
<li><strong>Those we can use professionally</strong>. I program professionally, and I practice daily to strive for mastery. I&#8217;m getting to the point where I can handle any task that is thrown at me.</li>
<li><strong>Those we can use</strong>. I can cook without killing myself of burning down my apartment complex, even though I can&#8217;t make many types of food and wouldn&#8217;t recognize a Mother Sauce if it was poured down my shirt.</li>
<li><strong>Those we couldn&#8217;t <em>really</em> use if our life depended on it.</strong> I&#8217;m not good at drawing. I&#8217;ve never spent time on it, and I have no motivation to learn. I can &#8220;draw&#8221; diagrams and get my point across, and this is enough for me.</li>
</ul>
<p>All people treat the skills from the first category differently than the other two: we use them with confidence. Some people use them with arrogance. We know these fields well enough to absorb innovations and new ways of thinking. We can confidently discuss them with other people.</p>
<p>In my mental model, starting from scratch in our expert area causes people to reject a change. For instance: an Excel or Word guru would never willingly switch to a completely unrelated product. Relearning things line inserting line-breaks and adding pictures to a text document is completely orthogonal to anything they actually have to do on the job, much less something more complicated like Mail Merge. Instead of using it like it should be used, they would likely try using it like they used their old product, declare that it can&#8217;t ramrod the flimjam, and switch back to their old way of doing things, <em>regardless of which is really better.</em></p>
<h2>Interfaces and APIs</h2>
<p>Altered interfaces are difficult for the end user. This isn&#8217;t just about GUIs or the placement of buttons in a menu; this extends to software APIs as well.</p>
<p>An altered menu causes all users to waste time looking for new ways to do something they could do 5 minutes ago. Changes to an API cause the programmers relearn a library they already knew &#8212; not to mention the laundry list of changes that need to happen to the new stuff!</p>
<h3>APIs and Interfaces</h3>
<p>The interface for a library or class develops massive unavoidable dependencies with use. I&#8217;ve called this &#8220;<a href="http://www.jakevoytko.com/blog/2008/11/17/inertia-and-large-code-bases/">code inertia</a>&#8221; in the past. Joel and Jeff&#8217;s <a href="http://www.joelonsoftware.com/items/2009/01/31.html">recent discussion</a> of dependencies between unit tests and code is a perfect example of code inertia: making nontrivial changes to an application can force a nontrivial number of changes to your automated testing environment.</p>
<p>This has not only a physical effect on the code, but also a mental effect for programmers! I&#8217;ve actually heard arguments from programmers based on the IDEA of possible future change: <em> we shouldn&#8217;t use this library because it&#8217;s changed significantly in the past, and it might change again!</em> Having to relearn the API combined with the frustration of updating broken code leaves a giant red flag in a programmer&#8217;s mind, even though <strong>any</strong> codebase that is being properly maintained will go through interface changes as new versions are released.</p>
<h3>Excel</h3>
<p>I was fortunate enough to take a Numerical Methods and Analysis class during my senior year of college.</p>
<p>If you&#8217;re not familiar, it&#8217;s the mathematics of computation: finding efficient approximations, determining rate of convergence, and knowing the margin of error at each stage.</p>
<p>This was my only college class where a calculator was ever useful. Most of our homework involved finding the values and error in iterative processes, so the professor suggested a &#8220;complex math package&#8221; for our homework: Excel.</p>
<p>Despite my initial skepticism, Excel is <em><strong>AWESOME</strong></em> with iterative numerical computation: type in a relative formula, highlight 50 rows, and click &#8220;fill down.&#8221; Voila! You can put a bunch of results in adjacent columns and compare convergence rates visually before you even prove that it converges at a certain rate. It&#8217;s quick, it&#8217;s interactive, and it supports easy experimentation.</p>
<p>Why is this relevant? My college upgraded to the Microsoft Office 2007 suite the previous summer, <a href="http://lifehacker.com/software/screenshot-tour/screenshot-tour--microsoft-word-and-excel-2007-225875.php">toolstrip and all</a>. Every single class was punctuated by my professor loudly complaining that she HATED the new Excel because the interface was WORSE and she couldn&#8217;t find anything.</p>
<p>Even though she knew where everything was after 2 weeks of use, we got the same complaint every week. She had already made up her mind: it was worse.</p>
<h3>KDE and Linus</h3>
<p>A few years ago, Linus Torvalds <a href="http://mail.gnome.org/archives/usability/2005-December/msg00021.html">publicly</a> announced his Linux desktop preference on the GNOME message boards:</p>
<blockquote><p>I personally just encourage people to switch to KDE.</p>
<p>This &#8220;users are idiots, and are confused by functionality&#8221; mentality of Gnome is a disease. If you think your users are idiots, only idiots will use it. I don&#8217;t use Gnome, because in striving to be simple, it has long since reached the point where it simply doesn&#8217;t do what I need it to do.</p>
<p>Please, just tell people to use KDE.</p>
<p>Linus</p></blockquote>
<p>The different camps typed their representative emoticons &#8212; <img src='http://www.jakevoytko.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  and D: &#8212; and then life continued as normal. However, Linus was eventually forced to switch when the next version of KDE <a href="http://www.techworld.com.au/article/273956/open_source_identity_linux_founder_linus_torvalds?pp=4">changed too much</a>:</p>
<blockquote><p><strong>Interviewer</strong>: Another open source project that underwent a big change was KDE with version 4.0. They released a lot of fundamental architectural changes with 4.0 and it received some negative reviews. As a KDE user how has this impacted you?</p>
<p><strong>Linus</strong>: I used to be a KDE user. I thought KDE 4.0 was such a disaster I switched to GNOME. I hate the fact that my right button doesn&#8217;t do what I want it to do. But the whole &#8220;break everything&#8221; model is painful for users and they can choose to use something else.</p>
<p>I realise the reason for the 4.0 release, but I think they did it badly. They did so may[sic] changes it was a half-baked release. It may turn out to be the right decision in the end and I will re-try KDE, but I suspect I&#8217;m not the only person they lost.</p>
<p>I got the update through Fedora and there was a mismatch from KDE 3 to KDE 4.0. The desktop was not as functional and it was just a bad experience for me. I&#8217;ll revisit it when I reinstall the next machine which tends to be every six to eight months.</p>
<p>The GNOME people are talking about doing major surgery so it could also go the other way.</p></blockquote>
<p>Linus realizes that it might be the <em>right</em> decision in the long run, but there&#8217;s no escaping the fact that even the big guns in the field can&#8217;t spend his time relearning the basics every day, even if it&#8217;s the right thing to do. He has a mental model of how the desktop is supposed to work, and when KDE broke it, he fixed the problem.</p>
<h2>Adult Learning and Malcolm Knowles</h2>
<p>To me, a lot of the principles of API and interface design fall under adult learning. To state the obvious, most of the indended clients for interfaces are adults. We&#8217;d like them to learn how to use our products with the minimal amount of fuss.</p>
<p>However, if your interface is exactly like every other interface, there would be no reason to use it. You&#8217;re trying to solve a problem for yourself, and you&#8217;re trying to solve a problem for your intended users. Your users will have to learn how to solve their problems with your interface, and it had better be easy.</p>
<p>Enter the research of <a href="http://www.infed.org/thinkers/et-knowl.htm">Malcolm Knowles</a>. He is one of the big-shots in the field of adult learning, having done a lot of the early theoretical work. <a href="http://www.infed.org/thinkers/et-knowl.htm&gt;Here&lt;/a&gt; are his listed assumptions about what drives the education of adults:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt; 1. Self-concept: As a person matures his self concept moves from one of being a dependent personality toward one of being a self-directed human being.&lt;br /&gt; 2. Experience: As a person matures he accumulates a growing reservoir of experience that becomes an increasing resource for learning.&lt;br /&gt; 3. Readiness to learn. As a person matures his readiness to learn becomes oriented increasingly to the developmental tasks of his social roles.&lt;br /&gt; 4. Orientation to learning. As a person matures his time perspective changes from one of postponed application of knowledge to immediacy of application, and accordingly his orientation toward learning shifts from one of subject-centeredness to one of problem centredness.&lt;br /&gt; 5. Motivation to learn: As a person matures the motivation to learn is internal. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I highly recommend looking through either the above link, or this one from the &lt;a href=">This site</a> has a good description of his life&#8217;s work with researching, for the interested.</p>
<p>In particular, Knowles attempted to find the theory of what caused adults to best learn. Believe it or not, there hadn&#8217;t been extensive research in the field before he started. The closest that he was able to come was his theory of <em>informal learning</em>, through group sessions or other kinds of informal meetings. He also developed his assumptions by which adults learn:</p>
<blockquote><p><strong>Malcolm Knowle&#8217;s Assumptions on Adult Learning</strong></p>
<ol>
<li>Self-concept: As a person matures his self concept moves from one of being a dependent personality toward one of being a self-directed human being.</li>
<li>Experience: As a person matures he accumulates a growing reservoir of experience that becomes an increasing resource for learning.</li>
<li>Readiness to learn. As a person matures his readiness to learn becomes oriented increasingly to the developmental tasks of his social roles.</li>
<li>Orientation to learning. As a person matures his time perspective changes from one of postponed application of knowledge to immediacy of application, and accordingly his orientation toward learning shifts from one of subject-centeredness to one of problem centredness.</li>
<li>Motivation to learn: As a person matures the motivation to learn is internal.</li>
</ol>
</blockquote>
<p>The salient bullet point is #2: experience. It&#8217;s <em>directly</em> listed as a basis for adult learning. I&#8217;m not saying that this is a direct proof of my mental model of knowledge, because quite honestly it&#8217;s just not a proper conclusion. However, designers of APIs and GUIs should take this as an indication that experience is something to build on, not disregard.</p>
<p>To use an aforementioned example, I really like the ribbon interface in Office 2007! I was proficient after only a few hours, and I enjoyed using fewer keystrokes to achieve my goals. I thought that it mapped pretty well to the old menu-based methods, and it was pretty obvious when it didn&#8217;t. If I could use only keyboard shortcuts to navigate, it would be the ideal control.</p>
<p>However, it&#8217;s probably a bad idea releasing it in the same year as Vista, which already scrambled some menus, changed some positions, altered some interfaces, renamed some popular folders, added UAC, etc. It all added up to too much of a change: when people sat down at it for the first time, nobody couldn&#8217;t <strong>use</strong> the darned thing.</p>
<p>Live and learn!</p>
<blockquote><p><strong>Footnote</strong></p>
<p>I remember a minor fuss when Linux 2.6.0 came out because the device driver interface changed. Linus himself descended from the cloud to state that he makes the right design choices for Linux without regard to compatibility issues. It was going to tie in really nicely with my point, and my Google Fu has failed me. up. The <a href="http://lwn.net/Articles/driver-porting/">device driver interface changed</a> from 2.4 to 2.6, and that there was a <a href="http://www.google.com/search?q=2.6.0+device+driver+problem&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=com.ubuntu:en-US:unofficial&amp;client=firefox-a"></a>of device driver complaints. At this point, I just want to know if I was making this up.</p></blockquote>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=367&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2009/02/02/starting-from-scratch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Human Numerical Methods</title>
		<link>http://www.jakevoytko.com/blog/2008/10/20/human-numerical-methods/</link>
		<comments>http://www.jakevoytko.com/blog/2008/10/20/human-numerical-methods/#comments</comments>
		<pubDate>Mon, 20 Oct 2008 04:00:34 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[Abacus]]></category>
		<category><![CDATA[Affine]]></category>
		<category><![CDATA[Feynman]]></category>
		<category><![CDATA[Kilometers to Miles]]></category>
		<category><![CDATA[Miles to Kilometers]]></category>
		<category><![CDATA[Numerical Methods]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=175</guid>
		<description><![CDATA[Or: I thought about calling this &#8220;Humerical Methods&#8221;, but there&#8217;s nothing funny here. My girlfriend and I recently went on vacation to Germany. Distant relatives of mine (Wolfgang and Birgit), agreed to host us for a few days, which turned out to be a great break from cheap hostels. One day, Wolfgang tells us that [...]]]></description>
			<content:encoded><![CDATA[<p><em>Or: I thought about calling this &#8220;Humerical Methods&#8221;, but there&#8217;s nothing funny here.</em></p>
<p>My girlfriend and I recently went on vacation to Germany. Distant relatives of mine (Wolfgang and Birgit), agreed to host us for a few days, which turned out to be a great break from cheap hostels.</p>
<p>One day, Wolfgang tells us that they are taking us to Öhringen, and town about 16 kilometers away.</p>
<p>He quickly corrects himself for the benefit of the Americans. &#8220;That should be about nine miles.&#8221;</p>
<p>&#8220;It&#8217;s closer to 9.6&#8243; I said without skipping a beat.</p>
<p>The speed of my answer surprised him. &#8220;Are you a quick multiplier?&#8221;</p>
<p>&#8220;Well, not exactly. Each kilometer is a little over .6 miles, so I add 1/2 and 1/10 the original number. It&#8217;s usually really faster than multiplying or dividing.&#8221;</p>
<p>It should be noted that this is an approximate method. The error is around 3.5%, as the conversion factor is closer to .621371. Most of the time, approximation are good enough with respect to distances. Once you have a handle on the distance, you can make all sorts of reasonable estimations, like driving time.</p>
<p><strong>Figuring it out</strong></p>
<p>Last March, I went on a road trip to Canada to compete in the <a href="http://www.csgames.org/2009/?page=news&amp;lang=en">CS Games</a> with my fellow Computer Science majors. Since it&#8217;s a <a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;q=2000+Pennington+Rd,+Trenton,+NJ+08618+to+Sherbrooke,+Canada&amp;sll=42.88908,-74.105515&amp;sspn=6.743637,19.753418&amp;ie=UTF8&amp;ll=42.795401,-73.344727&amp;spn=6.754174,19.753418&amp;z=6">long effing way</a> from TCNJ to Sherbrooke in Canada, we needed something to do. My buddy <a href="http://www.stephenlombardi.com/blog/">Steve</a> realized that we accidentally printed our return directions in kilometers instead of miles. He read out one of the distances on the map and asked what it was in miles/hour.</p>
<p>We thought for a second, and then I looked at the speedometer and read off the corresponding speed in miles per hour.</p>
<p>&#8220;How did you do it so fast?&#8221;</p>
<p>&#8220;Mental math,&#8221; I replied.</p>
<p>&#8220;What&#8217;s the conversion factor?&#8221; somebody asked. I saw that 100km/hr was roughly 60 miles, so I said &#8220;about .6.&#8221;</p>
<p>Luckily for me, all of the distances Steve read off were under 160km (the limit of my speedometer), so I was able to use the speedometer trick for a while. I figured that charade couldn&#8217;t last long, so I broke down the problem (multiplying by ~.6), and saw easy fractions I could use. I continued using this flawlessly.</p>
<p>Going from miles to kilometers is just as easy. Since a mile is ~1.609 kilometers, you can get an even better answer with identical math.</p>
<p>For a distance <em>n</em>, just add together <em>n</em> + <em>n</em>/2 + <em>n</em>/10. This approximation leaves you within .6%!</p>
<p>It&#8217;s a piece of cake to develop new methods along these lines. Take the expansion of the multiplicative constant, <em>c</em>, pick the first few digits of <em>c</em>, and break it up however mental arithmetic is easiest. Each digit of <em>c</em> that you use gives you a better approximation.</p>
<p>Determining the relative error is easy: it&#8217;s the unused digits of <em>c</em> divided by <em>c</em>.</p>
<p>You probably use this method for calculating tips already. If <em>n</em> is the dollar amount of the tip, it is easy to calculate 10% of the tip: <em>x</em> = .1 * <em>n</em>. The full amount of the tip is <em>x</em> + <em>x</em>/2, giving you 15%. That&#8217;s 1/10th + 1/20th, or 10% + 5%. This particular application happens to be exact.</p>
<p>You can even determine a generalization for any affine method, such as temperature conversions, by also adding and subtracting rounded approximations.</p>
<h2>Feynman Vs. the Abacus</h2>
<p>The above is child&#8217;s play! Any kid who has learned division can figure out their own tricks. The <em>real</em> limits of human mental math are accomplished by mental lookup tables. Special numbers are the name of the game; the more special numbers you know, the easier it is to quickly solve a problem.</p>
<p>The best example I have found of this is a story in <a href="http://www.amazon.com/gp/product/0393316041?ie=UTF8&amp;tag=jakvoyshom-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0393316041">Surely You&#8217;re Joking, Mr. Feynman!</a><img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.com/e/ir?t=jakvoyshom-20&amp;l=as2&amp;o=1&amp;a=0393316041" border="0" alt="" width="1" height="1" />, where he is challenged by a Japanese abacus salesman while visiting Portugal. I highly recommend you read the <a href="http://www.ee.ryerson.ca/~elf/abacus/feynman.html">full text of the encounter</a>.</p>
<p>The first challenge is addition. Feynman doesn&#8217;t stand a chance against the abacus, even when the numbers are written down and shown to both parties at the same time.</p>
<p>Next comes multiplication. Feynman still loses, but he has started to close the gap.</p>
<p>The next challenge is long division. It is a tie. This bothered the abacus salesman, so he challenges Feynman to cube roots. He writes the number &#8220;1729.03&#8243; on a piece of paper and starts working the abacus. Feynman quickly figures out that the first few digits are &#8220;12.002&#8243; while the abacus salesman struggles to even determine &#8220;12&#8243;.</p>
<p>As the book puts it:</p>
<blockquote><p>How did the customer beat the abacus?</p>
<p>The number was 1729.03. I happened to know that a cubic foot contains 1728 cubic inches, so the answer is a tiny bit more than 12. The excess, 1.03 is only one part in nearly 2000, and I had learned in calculus that for small fractions, the cube root&#8217;s excess is one-third of the number&#8217;s excess. So all I had to do is find the fraction 1/1728, and multiply by 4 (divide by 3 and multiply by 12). So I was able to pull out a whole lot of digits that way.</p></blockquote>
<h2>Hooray Math!</h2>
<p>The Feynman abacus story demonstrates one of the great things about math: every little fact eventually counts for something.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=175&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/10/20/human-numerical-methods/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>OpenID is Hard? So is Changing Your Password Every 3 Months.</title>
		<link>http://www.jakevoytko.com/blog/2008/09/09/openid-is-hard-so-is-changing-your-password-every-3-months/</link>
		<comments>http://www.jakevoytko.com/blog/2008/09/09/openid-is-hard-so-is-changing-your-password-every-3-months/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 04:00:05 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[changing passwords]]></category>
		<category><![CDATA[OpenID is hard]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=148</guid>
		<description><![CDATA[I&#8217;ve had the great fortune of working at two consecutive companies that force you to change your password every 3 months. Whenever the rollover date hits, I change EVERY password that I use. Today happens to be that day. Much to my amusement, I also happened to run across an article that states that OpenID [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had the great fortune of working at two consecutive companies that force you to change your password every 3 months. Whenever the rollover date hits, I change <strong><em><span style="text-decoration: underline;">EVERY</span></em></strong> password that I use.</p>
<p>Today happens to be that day.</p>
<p>Much to my amusement, I also happened to <a href="http://nedbatchelder.com/blog/200809/openid_is_too_hard.html">run across an article</a> that states that <a href="http://openid.net/">OpenID</a> is too hard for everyday use.</p>
<p>Absolutely! I couldn&#8217;t agree more. They still need to jump a gigantic new user hurdle. However, the alternative also sucks: changing your password for every service you use. So far today, I have changed the following passwords:</p>
<p><strong>At Work</strong>:</p>
<ul>
<li>Two local computer passwords</li>
<li>Two network passwords (one Unix, one NT).</li>
</ul>
<p><strong>At Home:</strong></p>
<ul>
<li>One Vista machine.</li>
<li>One Ubuntu laptop.</li>
<li>One server-edition Ubuntu machine.</li>
</ul>
<p><strong>On the Web:</strong></p>
<ul>
<li>Google</li>
<li>Reddit</li>
<li>jakevoytko.com x2</li>
<li>Dreamhost</li>
<li>Dreamhost MySQL (different password than the rest, naturally.)</li>
<li>Facebook</li>
<li>AOL Instant Messenger</li>
<li>Amazon</li>
<li>Windows Live (once I remembered which domain I used to register. This service plunges further onto my shit-list every time I use it).</li>
<li>Internet provider</li>
<li>Insurance provider</li>
</ul>
<p><strong>Special Passwords: </strong>(<em>I.E. Don&#8217;t allow symbols</em>)</p>
<ul>
<li>Verizon</li>
<li>Digg</li>
</ul>
<p>And I probably still have more to go! The good news is that a lot of sites seem to be converging on standards for passwords. Probaby 65% of the web-based passwords were in a section marked &#8220;Account Information&#8221; or &#8220;Profile.&#8221; Some were hopelessly buried.</p>
<p>OpenID may be hard, but they are taking a big step in the right direction. This is the web usability area that impacts users most</p>
<p>Ironically, one of the passwords I won&#8217;t be changing is OpenID, since the only time I used it, I used a throwaway password on a throwaway account that I don&#8217;t remember anymore <img src='http://www.jakevoytko.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> . Doing this for the 5th time in a row is certainly encouraging me to sign up with OpenID and get another password to add to the list!</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=148&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/09/09/openid-is-hard-so-is-changing-your-password-every-3-months/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Explaining Lisp to my Father</title>
		<link>http://www.jakevoytko.com/blog/2008/07/21/explaining-lisp-to-my-father/</link>
		<comments>http://www.jakevoytko.com/blog/2008/07/21/explaining-lisp-to-my-father/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 04:00:55 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming Languages]]></category>
		<category><![CDATA[Quote]]></category>
		<category><![CDATA[Brevity]]></category>
		<category><![CDATA[Explaining Lisp]]></category>
		<category><![CDATA[Lambdas]]></category>
		<category><![CDATA[Lisp]]></category>
		<category><![CDATA[Lisp Macros]]></category>
		<category><![CDATA[Self-Modifying code]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=102</guid>
		<description><![CDATA[Anyone who read my post last week knows that I&#8217;ve been trying to learn Lisp in my free time. My Dad has also noticed, and he occasionally checks on my progress. A week or two ago, he threw me a curveball: &#8220;How&#8217;s it going? Do you understand it all yet?&#8221; &#8220;No. I&#8217;m making progress, though. [...]]]></description>
			<content:encoded><![CDATA[<p>Anyone who read my post last week knows that I&#8217;ve been trying to learn Lisp in my free time. My Dad has also noticed, and he occasionally checks on my progress.</p>
<p>A week or two ago, he threw me a curveball:</p>
<blockquote><p>&#8220;How&#8217;s it going? Do you understand it all yet?&#8221;</p>
<p>&#8220;No. I&#8217;m making progress, though. I&#8217;m probably not going to have this down for a while. It&#8217;s a completely different way of thinking from the programming I normally do.&#8221;</p>
<p>&#8220;How is it different?&#8221;</p></blockquote>
<p>I froze. He&#8217;s &#8220;Mr.-Fix-It,&#8221; and understands the rock quarry/asphault business inside and out. He&#8217;s very analytical, and it&#8217;s almost impossible to stump him with my favorite &#8220;Devil&#8217;s advocate&#8221; questions. However, aside from what I&#8217;ve told him, he just doesn&#8217;t know much about programming.</p>
<p>&#8220;Metaprogramming&#8221; and &#8220;first-class functions&#8221; wouldn&#8217;t have meant anything. &#8220;It lets you write programs faster&#8221; is a cop-out; he&#8217;s given me detailed explanations of his business. I wanted him to understand.</p>
<p>I was able to stammer out the fact that the language encourages breaking problems into smaller versions of the same problem (recursion), but that other programming languages also supported it.</p>
<p>I eventually told him that I hadn&#8217;t even thought about explaining the difference to a non-programmer.</p>
<p>&#8220;Well, if you&#8217;re ever able to come up with it, let me know.&#8221;</p>
<p>In college, I was a Computer Science tutor. I could explain most CS concepts that students saw in early C++ and Java courses to the layman on the street. However, I had <strong><span style="text-decoration: underline;"><em>nothing</em></span></strong> for explaining the difference between Lisp and C++ to him, which was a little scary. I spent some time dreaming up examples.</p>
<h2>Functions</h2>
<blockquote><p>All models are wrong, but some are useful.</p>
<p>~<a href="http://en.wikiquote.org/wiki/George_E._P._Box">George Box</a></p></blockquote>
<p>Abstract math notions are boring to most people, so I try to relate programming concepts to real-world items.</p>
<p>A fast-food restaurant is a great example of a function: An order and some money is input, and you get cheeseburgers, fries, a soda, and your change. Whether a person likes math or not, they know what a function is: you put something in, you get something out.</p>
<p>The idea is easily extensible to Object Oriented programming: all Burger Kings have orders, and you can place a specific order at an instance of a Burger King. A Burger King &#8220;is-a&#8221; fast food restaraunt.</p>
<p>I will use this metaphor to explain why Lisp is different from the programming I usually do (C++/Java/C#/Python).</p>
<h2>Lambdas</h2>
<p>Any restaraunt probably has a few different ways to order food: over the phone, at a drive-through window, at a counter, through a waiter, etc. However, there might be unofficial ways to order food: Bill Gates might write a letter requesting a buffet with a few hundreds slipped in as proof. Someone might tell the owner on his way to work that he&#8217;d like him to come back with a pizza.</p>
<p>The owner can easily define new ways to order food through a restaraunt.</p>
<p>Lisp, through &#8220;lambdas&#8221;, lets a programmer define new functions as easily as a restaraunt owner can devise new ways to order. The inputs and outputs are the same, but making new functions can have very low overhead compared to other programming languages.</p>
<h2>Brevity</h2>
<p>&#8220;Wiz Wit&#8221;.</p>
<p>This is my usual order at <a href="http://en.wikipedia.org/wiki/Pat%27s_King_of_Steaks">Pat&#8217;s</a> in Philly. With just two words, I get a cheesesteak with Cheez-Wiz and fried onions in less than 5 seconds. The system is designed to maximize the number of cheesesteaks output per hour: orders are short, and you usually get your cheesesteak before you&#8217;re done paying [and sometimes, before you're done speaking!]</p>
<p>This lesson can be applied to writing: It&#8217;s easier to convey a short thought. Unless you are Charles Dickens or Neal Stephenson, economy of language should be a goal.</p>
<p>Lisp&#8217;s syntax is very simple and short, so you can usually convey a thought in Lisp much quicker than you can convey a thought in most other programming languages.</p>
<h2>Macros</h2>
<p>An order can come in several different forms: it can be written, it can be gestured, it can be be spoken, and it can be implicit.</p>
<p>A lot of programming languages let you generalize the details of what an order can receive. Most orders are the same, so you can handle the contents the same even though the orders are different. In C++, you could even use &#8220;templates&#8221; to write code that generates code that handles this idea.</p>
<p>Lisp takes this idea all the way to its logical conclusion through &#8220;macros.&#8221; You can easily write functions that define orders. The difference is that you can easily do this at any scope!</p>
<p>If you notice that all fast food restaraunts are the same except for color scheme, specials, and slogans, it is easy to write functions that define new fast food chains. If you notice that your functions for defining fast food chains are similar to your functions for defining hardware chains, you can write functions that generate these producers.</p>
<p>Lisp lets you easily do this manufacturing on a level that is unimaginable with any other language. It may be possible, but nothing beats Lisp&#8217;s ease-of-use.</p>
<h2>Self-Modifying Code</h2>
<p>The metaphor breaks down here, and I won&#8217;t force it. However, the idea is simple when it is explained.</p>
<p>Most programming languages are designed to modify memory. They all store their information in memory, retrieve it, modify it, and write it to memory again.</p>
<p>Some programming languages try to hide the fact that they&#8217;re based on a memory-modification model, but they are extremely similar to languages that don&#8217;t hide it.</p>
<p>Lisp, however, is written to modify lists. Lisp is also written using lists, so a Lisp program can be programmed to modify itself.</p>
<h2>Conclusion</h2>
<p>This is just the tip of the iceberg! There are a lot more ideas that lay beneath the surface here, and you can bet that I&#8217;ll think about how to explain them to an educated adult. However, this should get someone with passing familiarity to programming to understand what makes Lisp stand out: ease-of-use and brevity.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=102&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/07/21/explaining-lisp-to-my-father/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>ICANN and Ctrl-Alt-Shift-Tilde-Backflip</title>
		<link>http://www.jakevoytko.com/blog/2008/07/07/icann-and-ctrl-alt-shift-tilde-backflip/</link>
		<comments>http://www.jakevoytko.com/blog/2008/07/07/icann-and-ctrl-alt-shift-tilde-backflip/#comments</comments>
		<pubDate>Mon, 07 Jul 2008 04:00:55 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[ICANN]]></category>
		<category><![CDATA[keyboard shortcuts]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Top-level domains]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=94</guid>
		<description><![CDATA[The Background On June 26th, ICANN decided that the world needs more top-level domain names. Instead of the big three: .com, .org, and .net, we can now look forward to top-level domains such as .pepsi, .nyc, and .travel. This plan wasn&#8217;t forged from malice. There are quite a few benefits to the proposal. For example, [...]]]></description>
			<content:encoded><![CDATA[<h2>The Background</h2>
<p>On June 26th, ICANN <a href="http://www.icann.org/en/announcements/announcement-4-26jun08-en.htm">decided that the world needs more top-level domain names</a>. Instead of the big three: .com, .org, and .net, we can now look forward to top-level domains such as .pepsi, .nyc, and .travel.</p>
<p>This plan wasn&#8217;t forged from malice. There are quite a few benefits to the proposal. For example, users of non-Roman alphabets will find new support for native-language domain names. However, I found my gut reaction strongly critical the idea, so I ended up putting a little bit of time into thinking through the (negative) consequences of the move.</p>
<h2>Expectations and Security</h2>
<p>A lot of my initial concerned boiled down to the following question:</p>
<p><strong>Is it wise to change one of the foundations of the internet this late in the game? </strong></p>
<p>I don&#8217;t mean this from a technical standpoint, but rather a human standpoint. Unlike most of the technical organization of the internet, people actually interact with top level domains directly in multiple ways.</p>
<p>First is the grouping idea behind the expansion: even though usage is currently very limited, there is a practical difference between <a href="http://www.google.com">google.com</a> and <a href="http://www.google.cn">google.cn</a>: without even looking at the sites, I know that I am far more likely to understand the content on the first domain than the second domain. After looking at the sites, I am 100% sure I can&#8217;t understand the content at <a href="http://www.google.cn">google.cn</a>, and am mystified about the goofy hover-animations at the bottom of the page. Obviously, the proposal aides this human interaction with the internet.</p>
<p>Second is the simple issue of memory: At the moment, I can&#8217;t think of a site that I regularly use that has a domain other than .com, .net, .edu, and .org. That really limits the amount that concerns me when I memorize a new location on the web. Is this a big deal? Not really. Is it a factor? Absolutely.</p>
<p>Last is the security of top-level domain names. We all know that we shouldn&#8217;t go to www.mybank.com.info. That&#8217;s not to say nobody ever goes to phishing sites, but it&#8217;s a simple and useful safeguard against the faceless evil on the internet.</p>
<p>The security aspect of the top-level domain switch had me worried for a while. Let&#8217;s say that the newly formed .travel domain allows anybody to nab a new travel account. After all, a lot of people like to travel. Why not let them create their own .travel blogs about travelling?</p>
<p>Unfortuantely, this opens up an unfortunate can of worms. Can you trust a visit to <a href="orbitz.travel">orbitz.travel</a>, a seemingly innocuous domain at the nascent .travel top-level domain? Was it <a href=" ">account.orbitz.com</a>, <a href=" ">account.orbitz.travel</a>, or <a href=" ">account.travel.orbitz</a>?</p>
<p>This is not to say that any new top-level domain registrar will actually implement any of these measures. However, this will force a shift for a new mental security model.</p>
<h2>What Actually Concerns Me</h2>
<p>Soon, I realized that my concern over the proposal was just a defense of my boundless love of keyboard shortcuts! In Firefox, I&#8217;ve been using the domain completion keyboard shortcuts for a few years now, so much so that they have grown to be a necessary part of my browsing experience.</p>
<p>As my girlfriend can attest, a normal browsing session is not complete without the following exclamation/keyboard interaction:</p>
<p>&#8220;I wonder how the crazies are doing!&#8221; <em>&lt;Ctrl&gt;-t, reddit, &lt;Ctrl&gt;-&lt;Enter&gt;.</em></p>
<p>It takes me literally less than a second to find out why Ron Paul thinks C++ is worse than Haskell&#8217;s type system (with benchmarks), and I will be crushed when I am forced to navigate to other websites without my precious keyboard completions. I will either have to &lt;god forbid&gt; type out the whole domain, or find a Firefox plugin that will let me use archaic shortcuts like <em>&lt;Ctrl&gt;-&lt;Alt&gt;-&lt;Shift&gt;-~-&lt;Backflip&gt;</em> in order to properly navigate to the .travel domain.</p>
<h2>Keyboard Shortcuts? Are You Serious?</h2>
<p>Absolutely not! The above section is triple-underlining my belief that the top-level domain switch will not be a technical issue, but will create extra people problems. Once the new top-level domains are activated, all internet users will have to go through a new adjustment (good and bad) on their conceptual models of organization and security of information on the internet.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=94&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/07/07/icann-and-ctrl-alt-shift-tilde-backflip/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Happy Fourth of July! Holiday Quote Edition</title>
		<link>http://www.jakevoytko.com/blog/2008/07/04/happy-fourth-of-july-holiday-quote-edition/</link>
		<comments>http://www.jakevoytko.com/blog/2008/07/04/happy-fourth-of-july-holiday-quote-edition/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 04:00:49 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[Quote]]></category>
		<category><![CDATA[Declaration of Independence]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=93</guid>
		<description><![CDATA[When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature&#8217;s God entitle them, a decent respect to the [...]]]></description>
			<content:encoded><![CDATA[<p>When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature&#8217;s God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.</p>
<p>We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness. — That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, — That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn that mankind are more disposed to suffer, while evils are sufferable than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security. — Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.</p>
<p>He has refused his Assent to Laws, the most wholesome and necessary for the public good.</p>
<p>He has forbidden his Governors to pass Laws of immediate and pressing importance, unless suspended in their operation till his Assent should be obtained; and when so suspended, he has utterly neglected to attend to them.</p>
<p>He has refused to pass other Laws for the accommodation of large districts of people, unless those people would relinquish the right of Representation in the Legislature, a right inestimable to them and formidable to tyrants only.</p>
<p>He has called together legislative bodies at places unusual, uncomfortable, and distant from the depository of their Public Records, for the sole purpose of fatiguing them into compliance with his measures.</p>
<p>He has dissolved Representative Houses repeatedly, for opposing with manly firmness his invasions on the rights of the people.</p>
<p>He has refused for a long time, after such dissolutions, to cause others to be elected, whereby the Legislative Powers, incapable of Annihilation, have returned to the People at large for their exercise; the State remaining in the mean time exposed to all the dangers of invasion from without, and convulsions within.</p>
<p>He has endeavoured to prevent the population of these States; for that purpose obstructing the Laws for Naturalization of Foreigners; refusing to pass others to encourage their migrations hither, and raising the conditions of new Appropriations of Lands.</p>
<p>He has obstructed the Administration of Justice by refusing his Assent to Laws for establishing Judiciary Powers.</p>
<p>He has made Judges dependent on his Will alone for the tenure of their offices, and the amount and payment of their salaries.</p>
<p>He has erected a multitude of New Offices, and sent hither swarms of Officers to harass our people and eat out their substance.</p>
<p>He has kept among us, in times of peace, Standing Armies without the Consent of our legislatures.</p>
<p>He has affected to render the Military independent of and superior to the Civil Power.</p>
<p>He has combined with others to subject us to a jurisdiction foreign to our constitution, and unacknowledged by our laws; giving his Assent to their Acts of pretended Legislation:</p>
<p>For quartering large bodies of armed troops among us:</p>
<p>For protecting them, by a mock Trial from punishment for any Murders which they should commit on the Inhabitants of these States:</p>
<p>For cutting off our Trade with all parts of the world:</p>
<p>For imposing Taxes on us without our Consent:</p>
<p>For depriving us in many cases, of the benefit of Trial by Jury:</p>
<p>For transporting us beyond Seas to be tried for pretended offences:</p>
<p>For abolishing the free System of English Laws in a neighbouring Province, establishing therein an Arbitrary government, and enlarging its Boundaries so as to render it at once an example and fit instrument for introducing the same absolute rule into these Colonies</p>
<p>For taking away our Charters, abolishing our most valuable Laws and altering fundamentally the Forms of our Governments:</p>
<p>For suspending our own Legislatures, and declaring themselves invested with power to legislate for us in all cases whatsoever.</p>
<p>He has abdicated Government here, by declaring us out of his Protection and waging War against us.</p>
<p>He has plundered our seas, ravaged our coasts, burnt our towns, and destroyed the lives of our people.</p>
<p>He is at this time transporting large Armies of foreign Mercenaries to compleat the works of death, desolation, and tyranny, already begun with circumstances of Cruelty &amp; Perfidy scarcely paralleled in the most barbarous ages, and totally unworthy the Head of a civilized nation.</p>
<p>He has constrained our fellow Citizens taken Captive on the high Seas to bear Arms against their Country, to become the executioners of their friends and Brethren, or to fall themselves by their Hands.</p>
<p>He has excited domestic insurrections amongst us, and has endeavoured to bring on the inhabitants of our frontiers, the merciless Indian Savages whose known rule of warfare, is an undistinguished destruction of all ages, sexes and conditions.</p>
<p>In every stage of these Oppressions We have Petitioned for Redress in the most humble terms: Our repeated Petitions have been answered only by repeated injury. A Prince, whose character is thus marked by every act which may define a Tyrant, is unfit to be the ruler of a free people.</p>
<p>Nor have We been wanting in attentions to our British brethren. We have warned them from time to time of attempts by their legislature to extend an unwarrantable jurisdiction over us. We have reminded them of the circumstances of our emigration and settlement here. We have appealed to their native justice and magnanimity, and we have conjured them by the ties of our common kindred to disavow these usurpations, which would inevitably interrupt our connections and correspondence. They too have been deaf to the voice of justice and of consanguinity. We must, therefore, acquiesce in the necessity, which denounces our Separation, and hold them, as we hold the rest of mankind, Enemies in War, in Peace Friends.</p>
<p>We, therefore, the Representatives of the united States of America, in General Congress, Assembled, appealing to the Supreme Judge of the world for the rectitude of our intentions, do, in the Name, and by Authority of the good People of these Colonies, solemnly publish and declare, That these united Colonies are, and of Right ought to be Free and Independent States, that they are Absolved from all Allegiance to the British Crown, and that all political connection between them and the State of Great Britain, is and ought to be totally dissolved; and that as Free and Independent States, they have full Power to levy War, conclude Peace, contract Alliances, establish Commerce, and to do all other Acts and Things which Independent States may of right do. — And for the support of this Declaration, with a firm reliance on the protection of Divine Providence, we mutually pledge to each other our Lives, our Fortunes, and our sacred Honor.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=93&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/07/04/happy-fourth-of-july-holiday-quote-edition/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What Do You Trust Less?</title>
		<link>http://www.jakevoytko.com/blog/2008/06/02/what-do-you-trust-less/</link>
		<comments>http://www.jakevoytko.com/blog/2008/06/02/what-do-you-trust-less/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 04:00:23 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Algorithms vs. People]]></category>
		<category><![CDATA[Askimet]]></category>
		<category><![CDATA[Germany]]></category>
		<category><![CDATA[Murphy's Law]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/2008/06/02/what-do-you-trust-less/</guid>
		<description><![CDATA[Algorithms or People? The reason I ask this is that I am currently knee-deep in brötchen in Germany, but my blog posts are updating on schedule. Before I left, I wrote out all of the scheduled posts so that there is no hiccup for my readers. Lucky you. However, one of my favorite parts of [...]]]></description>
			<content:encoded><![CDATA[<h2>Algorithms or People?</h2>
<p>The reason I ask this is that I am currently knee-deep in <em>brötchen</em> in Germany, but my blog posts are updating on schedule. Before I left, I wrote out all of the scheduled posts so that there is no hiccup for my readers. Lucky you.</p>
<p>However, one of my favorite parts of blogging has to fall by the wayside: the comments. You can still write them, but they won&#8217;t be approved until I return. I may get some computer time, but I have no desire to plan my trip around my blog.</p>
<p>My blog gets about 35-40 spam comments a day, and that&#8217;s what gets through my spam filter. I don&#8217;t give a damn about advertising, and I only really hope to pull in enough dough each year to meet my hosting costs. The <em>real </em> value to me is the comments. Don&#8217;t get me wrong, you can still write them, and I encourage it! I just don&#8217;t see the incentive when I won&#8217;t see them for two weeks.</p>
<p>I thought about signing up for a comment filtering service or trying Akismet, but Murphy started to whisper in my ear:</p>
<p><em>What if it is broken when you are gone?</em> Well, that&#8217;s probably not likely to happen. These services have been working for a while, and they probably have a pretty high success rate if people use them.</p>
<p><em>You&#8217;ll be gone for over two weeks. By the time you get back, who knows how many spam comments slipped through the cracks?</em> OK, you got me there Murphy.</p>
<p>Basically, the fact that I could go so long without being able to repair any damage is a deterrent for me. This obviously discourages discussion, because commentors want to tell me how much I suck NOW, not in 2 weeks. However, I feel that the potential risk (posts with a hundred spam comments each) outweighs the reward. It doesn&#8217;t sound so bad, but it personally bothers me.</p>
<p>This comes down to a fundamental issue: <strong>I don&#8217;t trust the accuracy of algorithms that predict the behavior of people.</strong> <strong> Yet. </strong> Even the best service that I have, GMail, still throws some of my valid email into the spam folder! If even the best service can&#8217;t do the work 100% right, I don&#8217;t see why I should trust one I&#8217;ve never used. When I am deciding between the evil and stupidity of the world versus the performance of an algorithm, I still have to give the upper hand to the evil.</p>
<p>I&#8217;d ask you what you think, but you have no incentive to comment! Enjoy your day.</p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=87&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/06/02/what-do-you-trust-less/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bill Gates Predicts Web 2.0 in 1994</title>
		<link>http://www.jakevoytko.com/blog/2008/05/30/bill-gates-predicts-web-20-in-1994/</link>
		<comments>http://www.jakevoytko.com/blog/2008/05/30/bill-gates-predicts-web-20-in-1994/#comments</comments>
		<pubDate>Fri, 30 May 2008 04:00:57 +0000</pubDate>
		<dc:creator>Jake</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Quote]]></category>
		<category><![CDATA[1994]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Bill Gates Playboy]]></category>
		<category><![CDATA[Predictions are hard]]></category>
		<category><![CDATA[Web 2.0]]></category>

		<guid isPermaLink="false">http://www.jakevoytko.com/blog/?p=83</guid>
		<description><![CDATA[&#8230; and fails to capitalize on it! &#8220;Say you want to watch a movie. To choose, you&#8217;ll want to know what movies others liked and, based on what you thought of other movies you&#8217;ve seen, if this is a movie you&#8217;d like. You&#8217;ll be able to browse that information. Then you select and get video [...]]]></description>
			<content:encoded><![CDATA[<p><em>&#8230; and fails to capitalize on it!</em></p>
<blockquote><p><strong>&#8220;</strong>Say you want to watch a movie. To choose, you&#8217;ll want to know  what movies others liked and, based on what you thought of other movies you&#8217;ve  seen, if this is a movie you&#8217;d like. You&#8217;ll be able to browse that information.  Then you select and get video on demand. Afterward, you can even share what you  thought of the movie.</p>
<p>But thinking of it only in terms of movies on demand  trivializes the ultimate impact. The way we find information and make decisions  will be changed. Think about how you find people with common interests, how you  pick a doctor, how you decide what book to read. Right now, its hard to reach  out to a broad range of people. You are tied into the physical community near  you. But in the new environment, because of how information is stored and  accessed, that community will expand. This tool will be empowering, the  infrastructure will be built quickly and the impact will be broad.&#8221;</p>
<p>~Bill Gates, <a href="http://beginnersinvest.about.com/library/titans/bl-billgatesinterview2.htm">Playboy 1994</a></p></blockquote>
<p>I love reading old predictions and seeing where people went right, and where people went wrong. Interestingly, we have a dead-on prediction that Microsoft has failed to profit from. The community-driven Web 2.0 phase has come, and Microsoft still has not figured out a great way to make money from the web community, even though they had a 10 year ideological head start on everyone else.</p>
<p>To use his movie example, <a href="http://www.imdb.com/">IMDB</a>, <a href="http://www.rottentomatoes.com/">RottenTomatoes</a>, and <a href="http://www.amazon.com/dvds-used-hd-action-comedy-oscar/b/ref=sa_menu_mov1?ie=UTF8&amp;node=130&amp;pf_rd_p=328655101&amp;pf_rd_s=left-nav-1&amp;pf_rd_t=101&amp;pf_rd_i=507846&amp;pf_rd_m=ATVPDKIKX0DER&amp;pf_rd_r=1VV3XFBCNFS2DMMP5J63">Amazon</a> pretty much run the market on movie reviews.</p>
<p>Microsoft even had all of the pieces to do AJAX in place <a href="http://garrettsmith.net/blog/archives/2006/01/microsoft_inven_1.html">six years before anyone else</a>, but nothing came together until it was too late.</p>
<p>The lesson? <strong>Predicting the future is hard, even when you get it right.</strong></p>
<img src="http://www.jakevoytko.com/blog/?ak_action=api_record_view&id=83&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.jakevoytko.com/blog/2008/05/30/bill-gates-predicts-web-20-in-1994/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
