<?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>American in Spain &#187; Programming</title>
	<atom:link href="http://erikras.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://erikras.com</link>
	<description>Thoughts and photos from an American living in Spain.</description>
	<lastBuildDate>Fri, 03 Feb 2012 20:01:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Where are all the video emails?</title>
		<link>http://erikras.com/2010/12/30/where-are-all-the-video-emails/</link>
		<comments>http://erikras.com/2010/12/30/where-are-all-the-video-emails/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 16:47:57 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Damn, Nature!]]></category>
		<category><![CDATA[Marketing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[nora]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/?p=4791</guid>
		<description><![CDATA[With the release of the iPhone 4, and similar competitors, in 2010, video phone calls are just now starting to become more commonplace, although they are often less comfortable or convenient than regular voice calls. Webcam video chatting has been gaining in popularity over the last decade, but it has still been a bit cumbersome, [...]<h3>Related Photos</h3>
<ol>
										</ol>

]]></description>
			<content:encoded><![CDATA[<p><img class="post-thumb" alt="thumb" src="http://i3.ytimg.com/vi/fDYBa5vgl9U/default.jpg" width="100" height="75"/>With the release of the iPhone 4, and similar competitors, in 2010, video phone calls are just now starting to become more commonplace, although they are often less comfortable or convenient than regular voice calls. Webcam video chatting has been gaining in popularity over the last decade, but it has still been a bit cumbersome, usually requiring a lot of pre-communication communication to decide on a time for the call.</p>
<p>I had one of the very first computer webcams, the <a href="http://en.wikipedia.org/wiki/QuickCam">Connectix QuickCam</a>, back in 1995. I took it with me to college and actually video chatted with my parents a few times from my college dorm room. At the time, the webcam software and propaganda was very excited about the idea of &#8220;video email&#8221;, and that, in the very near future, we&#8217;d all be sending short video recordings to each other like on Star Trek. But then again, everyone thought we&#8217;d be surfing the web in 3D with <a href="http://en.wikipedia.org/wiki/Vrml">VRML</a> by the end of the millennium, too.<br />
<span id="more-4791"></span><br />
The iPhone 4, and other front-facing camera phones, have finally lowered the hassle level of sending a video email, a requisite for any technology taking off. Bandwidth speeds and video compression algorithms are now good enough that a 30 second video clip can be downloaded in less than 20 seconds.</p>
<p>Even with all this level of ease, I still don&#8217;t think video emails will become standard any time soon.  Google&#8217;s increasingly popular <a href="http://en.wikipedia.org/wiki/Vrml">Google Voice</a> service is handy specifically because it is moving in the <em>opposite</em> direction, translating spoken voice messages into text. Text is the most efficient way we receive communication, since most people can read faster than they can talk. It&#8217;s also much easier to edit and perfect just what you want to say in text than with video (e.g. &#8220;Darn, that&#8217;s not what I meant. Let&#8217;s record another take!&#8221;) </p>
<p>One might think that if the literacy rate continues to drop, voice and video emails might become more popular, but one look at social networking sites like MySpace and Facebook confirms that a lack of literacy doesn&#8217;t seem to be stopping anyone.</p>
<h3>A Case Study</h3>
<p>For a couple weeks now, I&#8217;ve been working on getting Nora to say &#8220;Good morning&#8221;. She doesn&#8217;t yet say it perfectly and requires some prodding in the morning to say it, but she&#8217;s made some progress. Earlier in the week, I thought that if I could pair &#8220;good morning&#8221; with &#8220;grandma&#8221;, a word she knows well (she says &#8220;meh-mah&#8221;), it might be nice to record a little video to send to my mother for her to see when she woke up. It only took about four takes, and then another thirty minutes for her to stop saying &#8220;Good morning, Grandma!&#8221;  Not surprisingly, we had a video response in our inbox the next morning. This time in our response, we tried saying &#8220;Good morning, grandpa!&#8221; as well, but to limited success. It was a fun experiment this week, but our vocabulary has run out, I think.</p>
<p><object width="505" height="309"><param name="movie" value="http://www.youtube.com/v/fDYBa5vgl9U?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/fDYBa5vgl9U?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="505" height="309"></embed></object></p>
<p>Perhaps one day we will be recording messages back and forth all day long, but I suspect that people will still be typing with their fingers and scrolling through text on screens at the end of the twenty-first century.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
										</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2010/12/30/where-are-all-the-video-emails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Parenting Taboos</title>
		<link>http://erikras.com/2010/12/22/parenting-taboos/</link>
		<comments>http://erikras.com/2010/12/22/parenting-taboos/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 12:26:47 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Colindres]]></category>
		<category><![CDATA[Damn, Nature!]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Parenting]]></category>
		<category><![CDATA[ted]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/?p=4781</guid>
		<description><![CDATA[Taboos are fascinating. My life has never been the same since August 8, 2006, when I read an article about examining what we don&#8217;t dare say aloud, and how the amount of trouble one can get in for saying certain things is positively correlated with the likelihood that they are true. Today I stumbled upon [...]<h3>Related Photos</h3>
<ol>
							</ol>

]]></description>
			<content:encoded><![CDATA[<p><img class="post-thumb" alt="thumb" src="http://i2.ytimg.com/vi/12OAr0lt4bk/default.jpg" width="100" height="75"/>Taboos are fascinating. My life has never been the same since <a href="http://erikras.com/2006/08/08/what-you-cant-say/">August 8, 2006</a>, when I read <a href="http://paulgraham.com/say.html">an article</a> about examining what we don&#8217;t dare say aloud, and how the amount of trouble one can get in for saying certain things is positively correlated with the likelihood that they are true. Today I stumbled upon a TED Talk by a married couple, Rufus Griscom and Alisa Volkman, who run a website about parenting. Their topic was parenting taboos, that is, what you can&#8217;t say about parenting.<br />
<span id="more-4781"></span><br />
My favorite part of their talk was when they took on the subject of happiness. I&#8217;m a <a href="http://erikras.com/2006/12/22/the-secret-to-happiness/">big</a> <a href="http://erikras.com/2008/12/18/dan-gilbert-makes-me-happy/">fan</a> <a href="http://erikras.com/2010/06/07/publishing/">of</a> Dan Gilbert, and his research and conclusions on how happiness declines when you have kids seem to me, intellectually, to be correct, but something about it just doesn&#8217;t <em>feel</em> right. I&#8217;ve been unable to pin down just what that problem was&#8230;until now. Griscom and Volkman absolutely nail it with a chart around minute thirteen of their talk.</p>
<p><object width="505" height="309"><param name="movie" value="http://www.youtube.com/v/12OAr0lt4bk?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/12OAr0lt4bk?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="505" height="309"></embed></object></p>
<p>I think that the internet and the optional anonymity it provides are having an excellent effect on social taboos. I applaud the hundreds of people valiantly blogging their way through emotionally difficult times of their life, whether it be divorce, miscarriage, closeted sexuality, cancer, or losing a spouse. By being publicly honest about these things, even anonymously, they are helping thousands of other people feel less alone in their problems. Parenting is less severe than those problems, but it still brings with it insecurities that, unless other people are sharing about them too, can easily make you feel alone. And if you can find a way to pay the rent by designing a website to help people share, then good for you, Griscom and Volkman.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
							</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2010/12/22/parenting-taboos/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How was this working?</title>
		<link>http://erikras.com/2010/07/29/how-was-this-working/</link>
		<comments>http://erikras.com/2010/07/29/how-was-this-working/#comments</comments>
		<pubDate>Thu, 29 Jul 2010 16:34:21 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Weird]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/?p=4388</guid>
		<description><![CDATA[An oversimplified description of my job as a computer programmer goes something like this. I get some requirements for a program from my boss or a client. I write the program as perfectly as I can. I test the program with all the cases that I think it will need to handle. The program is [...]<h3>Related Photos</h3>
<ol>
							</ol>

]]></description>
			<content:encoded><![CDATA[<p><a class="post-thumb" href="http://www.flickr.com/photos/gottcha78/545271203/" title="Friendly Bug! by gottcha78, on Flickr"><img src="http://farm2.static.flickr.com/1342/545271203_457e1a77d1_t.jpg" width="100" height="75" alt="Friendly Bug!" /></a>An oversimplified description of my job as a computer programmer goes something like this.</p>
<ol>
<li>I get some requirements for a program from my boss or a client.</li>
<li>I write the program as perfectly as I can.</li>
<li>I test the program with all the cases that I think it will need to handle.</li>
<li>The program is done and people start using it.</li>
<li>For whatever reason the requirements change (or a bug is found), and I have to go back and modify the code. Inevitably less testing is done on these changes than the original writing.</li>
<li><a href="http://en.wikipedia.org/wiki/Goto">Go to</a> #4.</li>
</ol>
<p>It&#8217;s pretty rare for the original writing of a program to have a significant bug in it after testing, although I&#8217;m not perfect. Almost all bugs are introduced in step #5. When you first write the program, the entire program and its relationship with other programs is in your mind. But when you go back to look at old code, it&#8217;s just not fresh in your memory, and it&#8217;s very easy to make a change without taking into consideration all the consequences that change will have.<br />
<span id="more-4388"></span><br />
Sometimes when I&#8217;m doing testing on change to a piece of code, I&#8217;ll find a problem in an unrelated common part of the system, like a line of code that is run several dozen times every time anyone goes to any page on any of my company&#8217;s websites. Looking at the code reveals that there is <strong><em>no way this could possibly be working</em></strong>, and yet millions of dollars of revenue have been earned specifically because that line worked.</p>
<p>The name in the industry for this type of phenomenon is <a href="http://en.wikipedia.org/wiki/Unusual_software_bug#Schroedinbug"><em>Schroedinbug</em></a>, because, like <a href="http://en.wikipedia.org/wiki/Schr%C3%B6dinger's_cat">Schrödinger&#8217;s cat</a>, everything is fine until you observe what&#8217;s inside the box.</p>
<p>What is really mind-blowing about <em>Schroedinbugs</em> is just how often they occur. I find bugs like this several times a year. Today was one of those days.</p>
<p>I have to wonder if other branches of engineering have similar phenomena. Do engineers sometimes find a rusted bolt and say, &#8220;Man, I can&#8217;t believe the bridge is still standing!&#8221; Do doctors often tell patients, &#8220;According to medical science, that really should have killed you.&#8221; I certainly hope not, but my intuition tells me it happens <em>all the time</em>.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
							</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2010/07/29/how-was-this-working/feed/</wfw:commentRss>
		<slash:comments>212</slash:comments>
		</item>
		<item>
		<title>XML Renderer in Clojure</title>
		<link>http://erikras.com/2009/09/08/xml-renderer-in-clojure/</link>
		<comments>http://erikras.com/2009/09/08/xml-renderer-in-clojure/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 20:59:10 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/?p=2980</guid>
		<description><![CDATA[I&#8217;ve spent the past few days playing around with Clojure. Clojure is an implementation of Lisp, the most powerful programming language, that compiles to byte code that runs on the Java Virtual Machine. I won&#8217;t go into just how awesome that is, but there are many technical reasons why this platform decision is equivalent to [...]<h3>Related Photos</h3>
<ol>
				</ol>

]]></description>
			<content:encoded><![CDATA[<p><img src="http://clojure.org/file/view/clojure-icon.gif" class="post-thumb" alt="clojure logo" width="100" height="100"/>I&#8217;ve spent the past few days playing around with <a href="http://clojure.org/">Clojure</a>.  Clojure is an implementation of Lisp, the <a href="http://erikras.com/2007/07/06/lisp-enlightenment-and-emacs-frustration/">most powerful programming language</a>, that compiles to byte code that runs on the Java Virtual Machine.  I won&#8217;t go into just how awesome that is, but there are many technical reasons why this platform decision is equivalent to standing on the shoulders of giants.</p>
<p>Clojure comes with a built-in library for parsing XML files into Clojure data structures, but, for the life of me, I could absolutely not find any implementations that went the other way, to render XML from the Clojure structure that the default parser creates.  So I wrote one&#8230;in 25 lines of code.<br />
<span id="more-2980"></span><br />
<em>Update: I did find a function in the clojure contrib <a href="http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/lazy_xml.clj">lazy-xml.clj</a> that will emit XML nodes to a stream, but it&#8217;s (gasp!) not remotely functional.</em></p>
<p><code>(def *always-open* #{:div :script :textarea})<br />
<br />
(defn render-attributes [attributes]<br />
&nbsp;&nbsp;(when attributes<br />
&nbsp;&nbsp;&nbsp;&nbsp;(apply str<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(for [[key value] attributes]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str \space (name key) "=\"" value \")))))<br />
<br />
(defn render [node]<br />
&nbsp;&nbsp;&nbsp;&nbsp;(if (string? node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.trim node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [tag (:tag node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;children (:content node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;has-children? (not-empty children)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open? (or has-children? (contains? *always-open* tag))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open-tag (str \&lt; (name tag)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(render-attributes (:attrs node))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if open? \&gt; "/&gt;"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close-tag (when open? (str "&lt;/" (name tag) \&gt;))]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open-tag<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply str (when has-children?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(for [child children]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(render child))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close-tag))))</code><br />
There is a little extra HTML-specific logic in there to not close &lt;script&gt; or &lt;div&gt; or &lt;textarea&gt; tags, as some web browsers can&#8217;t handle those cases.</p>
<p>So if you have an HTML file that looks like this&#8230;<br />
<code>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;html&gt;<br />
&nbsp;&lt;head&gt;<br />
&nbsp;&nbsp;&lt;title&gt;Testing Title&lt;/title&gt;<br />
&nbsp;&nbsp;&lt;style type="text/css"&gt;<br />
&nbsp;&nbsp;&nbsp;.some-class { font-weight: bold; }<br />
&nbsp;&nbsp;&lt;/style&gt;<br />
&nbsp;&nbsp;&lt;script type="text/javascript" src="myjs.js"&gt;&lt;/script&gt;<br />
&nbsp;&lt;/head&gt;<br />
&nbsp;&lt;body&gt;<br />
&nbsp;&nbsp;&lt;p id="message" class="some-class"&gt;<br />
&nbsp;&nbsp;&nbsp;This is a totally awesome test!<br />
&nbsp;&nbsp;&lt;/p&gt;<br />
&nbsp;&lt;/body&gt;<br />
&lt;/html&gt;</code><br />
And you run the following command at the REPL&#8230;<br />
<code>(println (render (clojure.xml/parse "index.html")))</code><br />
&#8230;you should get this back:<br />
<code>&lt;html&gt;&lt;head&gt;&lt;title&gt;Testing Title&lt;/title&gt;&lt;style type="text/css"&gt;.some-class { font-weight: bold; }&lt;/style&gt;&lt;script type="text/javascript" src="myjs.js"&gt;&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;p id="message" class="some-class"&gt;This is a totally awesome test!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</code><br />
While valid XML, it&#8217;d be nice to have it prettily formatted.  To do this, we must add a little complexity to keep track of depth and indentation.</p>
<p><code>(def *always-open* #{:div :script})<br />
<br />
(defn render-attributes [attributes]<br />
&nbsp;&nbsp;(when attributes<br />
&nbsp;&nbsp;&nbsp;&nbsp;(apply str<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(for [[key value] attributes]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str \space (name key) "=\"" value \")))))<br />
<br />
(defn render<br />
&nbsp;&nbsp;([node] (render node 0 false))<br />
&nbsp;&nbsp;([node pretty?] (render node 0 pretty?))<br />
&nbsp;&nbsp;([node depth pretty?]<br />
&nbsp;&nbsp;&nbsp;(let [indent (when pretty? (apply str (repeat depth "&nbsp;&nbsp;")))]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if (string? node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str indent (.trim node) (when pretty? "\n"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let [tag (:tag node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;children (:content node)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;has-children? (not-empty children)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;always-open? (contains? *always-open* tag)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open? (or has-children? (contains? *always-open* tag))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open-tag (str indent \&lt; (name tag)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(render-attributes (:attrs node))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if open? \&gt; "/&gt;"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close-tag (when open?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str (when (not always-open?) indent)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&lt;/" (name tag) \&gt;))]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(str<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open-tag<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (and pretty? (not always-open?)) "\n")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(apply str (when has-children?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(for [child children]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(render child (inc depth) pretty?))))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close-tag<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(when (and pretty? (&gt; depth 0)) "\n")))))))</code><br />
This has bumped us up to 34 lines of code with proper formatting.  Now if we call:<br />
<code>(println (render (clojure.xml/parse "index.html")))</code><br />
We still get the same unformatted html back because it defaults to non-pretty formatting.  But if we request pretty formatting&#8230;<br />
<code>(println (render (clojure.xml/parse "index.html") true))</code><br />
We get back this:<br />
<code>&lt;html&gt;<br />
&nbsp;&nbsp;&lt;head&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Testing Title<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/title&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;style type="text/css"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.some-class { font-weight: bold; text-align:inherit; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/style&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;script type="text/javascript" src="myjs.js"&gt;&lt;/script&gt;<br />
&nbsp;&nbsp;&lt;/head&gt;<br />
&nbsp;&nbsp;&lt;body&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;p id="message" class="some-class"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This is a totally awesome test!<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/p&gt;<br />
&nbsp;&nbsp;&lt;/body&gt;<br />
&lt;/html&gt;</code><br />
Perfect!</p>
<p>What&#8217;s amazing is that, after a few days of working with Clojure, and <a href="http://erikras.com/2007/07/06/lisp-enlightenment-and-emacs-frustration/">a very small background in Lisp</a>, this code is perfectly readable.  I could not figure out a way to go through the tree with Clojure&#8217;s tail recursion idiom, so I had to use stack recursion.  For most XML files, stack recursion is going to be just fine.</p>
<p>I am still not convinced that Clojure deserves a place in any of my business applications, but it definitely has the best shot of any Lisp dialect I&#8217;ve seen, mainly because of its trivial <a href="http://clojure.org/java_interop">interoperation with Java</a>.</p>
<p>If any Clojure ninjas out there would like to suggest improvements to my algorithm, I&#8217;m all ears.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
				</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2009/09/08/xml-renderer-in-clojure/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Bug in java.util.EnumMap.clone()</title>
		<link>http://erikras.com/2009/05/08/bug-in-javautilenummapclone/</link>
		<comments>http://erikras.com/2009/05/08/bug-in-javautilenummapclone/#comments</comments>
		<pubDate>Fri, 08 May 2009 16:58:56 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Complaining]]></category>
		<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/?p=2227</guid>
		<description><![CDATA[At work today we found ourselves totally confused by the behavior of one of our EnumMap instances. No matter what we did to it (setting new values, clearing, etc.), when we iterated through the entry set, the values were the same. After investigating the source code for java.util.EnumMap, it became clear that the problem was [...]<h3>Related Photos</h3>
<ol>
										</ol>

]]></description>
			<content:encoded><![CDATA[<p>At work today we found ourselves totally confused by the behavior of one of our EnumMap instances.  No matter what we did to it (setting new values, clearing, etc.), when we iterated through the entry set, the values were the same.  After investigating the source code for java.util.EnumMap, it became clear that the problem was based on the fact that the EnumMap instance we were working with had been generated by calling EnumMap.clone() rather than using the constructor.  I&#8217;ve written a test program to demonstrate this bug.  It should <em>NOT</em> behave like this!<br />
<span id="more-2227"></span></p>
<style type="text/css">
code span.keyword {
  font-weight:bold;
  color: #000080;
}
code span.member {
  font-weight:bold;
  color: #660e7a;
}
code span.static {
  font-style:italic;
  font-weight:bold;
  color: #660e7a;
}
code span.comment {
  font-style:italic;
  color: #006600;
}
</style>
<h3>The Code</h3>
<p><code><br />
<span class="keyword">public</span> <span class="keyword">class</span> EnumMapBug<br />
{<br />
&nbsp;&nbsp;<span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">enum</span> E { <span class="static">A</span>,<span class="static">B</span>,<span class="static">C</span> }<br />
<br />
&nbsp;&nbsp;<span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> main(<span class="keyword">final</span> String[] args)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span> EnumMap&lt;E ,String> map =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">new</span> EnumMap&lt;E, String&gt;(E.<span class="keyword">class</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put(E.<span class="static">A</span>, "apple");<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put(E.<span class="static">B</span>, "ball");<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put(E.<span class="static">C</span>, "cat");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// call entrySet() to generate internal entrySet</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;map.entrySet();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// print original values</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nOriginal values:");<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nA is for " + map.get(E.<span class="static">A</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("Entries: " + map.entrySet());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// clone the map.</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("\nCloning...now using clone.");<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span> EnumMap&lt;E, String&gt; clone = map.clone();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// from now on, any time we access the clone's entry set,</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// it will WRONGLY give us the original map's entry set.</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nA is for " + clone.get(E.<span class="static">A</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("Entries: " + clone.entrySet());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// no matter what we do to the clone's values,</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// the clone's entry set never changes.</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nSetting new A value...");<br />
&nbsp;&nbsp;&nbsp;&nbsp;clone.put(E.<span class="static">A</span>, "aardvark");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// but get() still works</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nA is for " + clone.get(E.<span class="static">A</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("Entries: " + clone.entrySet());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// clear the clone</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nClearing...");<br />
&nbsp;&nbsp;&nbsp;&nbsp;clone.clear();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// get() properly returns null</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nA is for " + clone.get(E.<span class="static">A</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// but the entry set still contains our original entries</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("Entries: " + clone.entrySet());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// rather amazingly, when we modify the original</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// map's contents, the entry set for the clone changes</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nSetting new A value...");<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put(E.<span class="static">A</span>, "algorithm");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("\nA is for " + clone.get(E.<span class="static">A</span>));<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="static">out</span>.println("Entries: " + clone.entrySet());<br />
&nbsp;&nbsp;}<br />
}</code><br />
There is a more easily copied and pasted version of this code <a href="http://pastebay.com/14461">here</a>.</p>
<h3>The Output</h3>
<p>The code above results in the following output:</p>
<p><code>Original values:<br />
<br />
A is for apple<br />
Entries: [A=apple, B=ball, C=cat]<br />
<br />
Cloning...now using clone.<br />
<br />
A is for apple<br />
Entries: [A=apple, B=ball, C=cat]<br />
<br />
Setting new A value...<br />
<br />
A is for aardvark<br />
Entries: [A=apple, B=ball, C=cat]<br />
<br />
Clearing...<br />
<br />
A is for null<br />
Entries: [A=apple, B=ball, C=cat]<br />
<br />
Updating original map...<br />
<br />
A is for null<br />
Entries: [A=algorithm, B=ball, C=cat]</code></p>
<h3>Explanation</h3>
<p>When I said &#8220;rather amazingly&#8221; in the comment, it&#8217;s only really amazing when you don&#8217;t understand what is going on.  When you clone an EnumMap, because of the entry set caching and the bug in clone(), the cloned instance&#8217;s entrySet() method will always give you a reference to the original map&#8217;s entry set, never to its own.  The <a href="http://www.jdocs.com/javase/7.b12/java/util/EnumMap.html">version of EnumMap that I&#8217;m using</a> contains the javadoc info &#8220;@version 1.22, 05/05/07&#8243;.  It&#8217;s clear enough to see the bug in clone().  The EnumMap clone() method is:</p>
<p><code><span class="keyword">public</span> EnumMap&lt;K, V&gt; clone() {<br />
&nbsp;&nbsp;EnumMap&lt;K, V&gt; result = <span class="keyword">null</span>;<br />
&nbsp;&nbsp;<span class="keyword">try</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;result = (EnumMap&lt;K, V&gt;) <span class="keyword">super</span>.clone();<br />
&nbsp;&nbsp;} <span class="keyword">catch</span>(CloneNotSupportedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">throw</span> <span class="keyword">new</span> AssertionError();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;result.<span class="member">vals</span> = (Object[]) result.<span class="member">vals</span>.clone();<br />
&nbsp;&nbsp;<span class="keyword">return</span> result;<br />
}</code><br />
But it needs one more line:</p>
<p><code><span class="keyword">public</span> EnumMap&lt;K, V&gt; clone() {<br />
&nbsp;&nbsp;EnumMap&lt;K, V&gt; result = <span class="keyword">null</span>;<br />
&nbsp;&nbsp;<span class="keyword">try</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;result = (EnumMap&lt;K, V&gt;) <span class="keyword">super</span>.clone();<br />
&nbsp;&nbsp;} <span class="keyword">catch</span>(CloneNotSupportedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">throw</span> <span class="keyword">new</span> AssertionError();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;result.<span class="member">vals</span> = (Object[]) result.<span class="member">vals</span>.clone();<br />
&nbsp;&nbsp;<span style="background-color:#FFFF00;border:1px solid black;padding:2px;">result.<span class="member">entrySet</span> = <span class="keyword">null</span>;</span><br />
&nbsp;&nbsp;<span class="keyword">return</span> result;<br />
}</code><br />
This will force regeneration and caching of the entry set in the clone.</p>
<p>I&#8217;m rather surprised that I cannot find any reference to this bug on the internet.  It&#8217;s such an easy fix!  The workaround is to never use EnumMap.clone(), but to construct a new one with its copy constructor.  Like so, with the key and value in my example code:</p>
<p><code><span class="keyword">final</span> EnumMap&lt;E, String&gt; clone = <span class="keyword">new</span> EnumMap&lt;E, String&gt;(map);</code></p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
										</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2009/05/08/bug-in-javautilenummapclone/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Lisp Enlightenment and Emacs Frustration</title>
		<link>http://erikras.com/2007/07/06/lisp-enlightenment-and-emacs-frustration/</link>
		<comments>http://erikras.com/2007/07/06/lisp-enlightenment-and-emacs-frustration/#comments</comments>
		<pubDate>Fri, 06 Jul 2007 01:11:38 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Complaining]]></category>
		<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/2007/07/06/lisp-enlightenment-and-emacs-frustration/</guid>
		<description><![CDATA[I have recently had my interest piqued about Lisp. I learned a little Lisp back in college for some Artificial Intelligence classes that I took. It struck me as a rather awkward language. Several months ago, I found this article by Paul Graham about how he, in 1995, way before the dot-com boom, started a [...]<h3>Related Photos</h3>

No related photos.
]]></description>
			<content:encoded><![CDATA[<p>I have recently had my interest piqued about <a href="http://en.wikipedia.org/wiki/Lisp_programming_language">Lisp</a>.  I learned a little Lisp back in college for some Artificial Intelligence classes that I took.  It struck me as a rather awkward language.<br />
<span id="more-310"></span><br />
Several months ago, I found <a href="http://www.paulgraham.com/avg.html">this article</a> by Paul Graham about how he, in 1995, <em>way</em> before the dot-com boom, started a company, called Viaweb, to make customizable online stores, exactly five years before I, too, started a company to make customizable online stores.  The only difference is that he sold his to Yahoo! for millions of dollars.  In the article, he claims that the key factor that let his company beat out the competition at every turn was that they wrote their software in Lisp.  He quotes Eric Raymond:</p>
<blockquote><p>Lisp is worth learning for the profound enlightenment experience you will have when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use Lisp itself a lot.</p></blockquote>
<p>In my investigation, I&#8217;ve found that this moment of enlightenment is mentioned by many other Lisp users (aka. Lispers).  As a non-Lisper, I was reminded of the feeling I had when those <a href="http://www.magiceye.com/">Magic Eye</a> stereograms became popular.  I felt like everyone around me was staring at something that appeared uninteresting and saying, &#8220;Whoa!  Cooooool!!!&#8221;  I just didn&#8217;t get it.</p>
<p>Then, a few weeks ago, I found an article called <a href="http://www.defmacro.org/ramblings/lisp.html">The Nature of Lisp</a>, by Slava Akhmechet.  His stated goal of the article was to look back at his own path to Lisp enlightenment, and then reach out to the unenlightened and describe why Lisp is so cool in terms that non-Lispers understand, namely XML and <a href="http://ant.apache.org/">Ant</a>.  Compressing the article into one sentence, the main point that non-Lispers don&#8217;t get is that Lisp blurs the line between data and code much like Ant is code written in XML, a format used mostly for data, and this lets you manipulate your Lisp code with Lisp itself.  See how hard that is to understand?  There&#8217;s a reason Slava&#8217;s article is so long.</p>
<p>I was just beginning to see the light.  I had seen through the keyhole to a beautiful world out there, if I could just pry the door open a bit more&#8230;  The next step was reading <a href="http://www.gigamonkeys.com/book/">Practical Common Lisp</a>, a book by Peter Seibel, that he has released free on the web.  I am the exact audience that the book was written for, a pretty good programmer, well versed in one language, and interested in understanding why Lisp is so great.  In his introduction, he states,</p>
<blockquote><p>If you&#8217;re a hard-nosed pragmatist who wants to know what advantages Common Lisp has over languages such as Perl, Python, Java, C, or C#, this book should give you some ideas. Or maybe you don&#8217;t even care about using Lisp&#8211;maybe you&#8217;re already sure Lisp isn&#8217;t really any better than other languages you know but are annoyed by some Lisper telling you that&#8217;s because you just don&#8217;t &#8220;get it.&#8221; If so, this book will give you a straight-to-the-point introduction to Common Lisp. If, after reading this book, you still think Common Lisp is no better than your current favorite languages, you&#8217;ll be in an excellent position to explain exactly why.</p></blockquote>
<p>In the past few weeks, I&#8217;ve more or less read Practical Common Lisp from cover to cover.  I skipped over some of the stuff at the end about parsing MP3 files.  And the final conclusion is that: <em>Lisp is far better than any programming language I&#8217;ve ever learned, including Java</em>, which is more or less my &#8220;mother tongue&#8221; these days.  Even if you tie macros (Lisp&#8217;s true source of power) behind its back, its object inheritance, error handling, and variable scoping are far more robust and flexible than Java&#8217;s.</p>
<p>My programming language path went from BASIC to C++ to Java, with slight dabbling in C and Pascal along the way.  As such, I thought that concepts like &#8220;<acronym title="Almost true in Java">everything is an object</acronym>&#8220;, &#8220;every variable is really pointer to an object&#8221;, garbage collection, and running on a virtual machine were all brand new concepts in Java.  And just recently I&#8217;ve been amazed at the power of concepts like <a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29">closures</a> and <a href="http://en.wikipedia.org/wiki/First-class_function">first-class functions</a> in Javascript.  And now I learn that Lisp was doing all this and <em>more a decade before I was born</em>??  Mind.  Blown.</p>
<p>So here I am.  I&#8217;ve seen the light, and it&#8217;s absolutely beautiful.  I&#8217;ve pried open the door and am gazing, slack-jawed, at the blissful sunny meadows of efficient, elegant Lisp programming.  As I&#8217;m preparing to leave behind my dank dark prison cell of Java, vowing never to return, a little voice in the back of my head says what I was trying all along not to think about.</p>
<blockquote><p>If it&#8217;s so nice and perfect out there, why is there no one out there?  You think you&#8217;re so smart that, in only two months, you&#8217;ve figured something out that <em>none</em> of the other poor schmucks in the neighboring cells haven&#8217;t?</p></blockquote>
<p>&#8220;Shut up,&#8221; I murmured, and sprinted for the open door.  And that was when I slammed, face first, into the invisible pane of glass called <a href="http://en.wikipedia.org/wiki/Emacs">Emacs</a>.</p>
<p>At work, I spend almost all of my time using an application called <a href="http://www.jetbrains.com/idea/">IntelliJ IDEA</a>, an integrated development environment (IDE) for Java.  IntelliJ makes Java programming as easy as it can possibly be.  It more or less compiles your code as you type it, points out most bugs as they occur, intelligently suggests code completion to finish your words for you.  I generates all the annoying repetitive code, like getters and setters and equals() methods for you.  Without it, Java would be much more laborious to program in (but still not as bad as other languages in the C family tree).  Java has many other IDE alternatives, but none truly stack up to IntelliJ.</p>
<p>A couple years ago, I began using a plugin for IntelliJ, called <a href="http://ideavim.sourceforge.net/">IdeaVIM</a>, that allows me to use Vim key mappings in IntelliJ.  <a href="http://en.wikipedia.org/wiki/Vim_(text_editor)">Vim</a> is a successor to <a href="http://en.wikipedia.org/wiki/Vi">Vi</a>, which is an ancient UNIX text editor.  The main value that it provides is allowing you to move your cursor around a text file without moving your fingers from the home row, thus greatly reducing <a href="http://en.wikipedia.org/wiki/Repetitive_strain_injury" title="Repetitive Strain Injury">RSI</a>.</p>
<p>Lisp, on the other hand, has only one IDE.  That IDE consists of Emacs, another ancient, extensible text editor, and <a href="http://common-lisp.net/project/slime/" title="The Superior Lisp Interaction Mode for Emacs">SLIME</a>.  There are some commercial IDEs, but they all use Emacs key mappings and don&#8217;t improve the interface that much, so what&#8217;s the point?  <a href="http://video.google.com/videoplay?docid=-2140275496971874400">This 55 minute video</a> (<a href="http://common-lisp.net/movies/slime.mov">mov</a>) (<a href="http://common-lisp.net/movies/slime.torrent">torrent</a>) demonstration of Emacs and SLIME, by Marco Baringer (one of Lisp&#8217;s leading developers, it seems), is pretty impressive and demonstrates an efficiency of development comparable to that of IntelliJ.  You can even do some things that IntelliJ (and Java) can&#8217;t do, such as compile code directly into a running remote server.</p>
<p>Vi and Emacs are long time rivals, and the internet is full of bitter arguments about which is superior.  The fact is that they both provide ways of moving quickly around a text file and modifying entire blocks of text.  And, most importantly, both of them have <em>incredibly</em> steep learning curves.</p>
<p>I just spent all this brain energy comprehending the infinite power of Lisp, and now I&#8217;m stuck at the bottom of a learning cliff that prevents me from going any further before learning an awkward set of key combinations to edit a text file.  Coming from a Vim background, what I can&#8217;t stand about Emacs is that you have to hold down the Ctrl or Alt key practically the entire time you&#8217;re using it.  This is enough to make a Vim user scream!  Emacs seems like a sure way to <acronym title="Repetitive Strain Injury">RSI</acronym>.  This is a huge stumbling block for me at the moment, and it&#8217;s particularly frustrating because of my desire to flex my newly formed Lisp muscles.</p>
<p>It seems 100% crystal clear that if you want to be a Lisp developer, you have to use Emacs.  This is just a fact that I&#8217;m going to have to accept and either give up or learn Emacs.  I suspect that this is the major reason that Lisp isn&#8217;t more popular.  There are other problems like how the lack of rigid structure makes managing large teams of programmers difficult, but I bet the main glass wall keeping people in their cells is the difficulty of learning a new and different language <em>and</em> a new and different text editor.</p>
<p>Hopefully it&#8217;s just a matter of time.  I clearly recall a time when I thought, &#8220;Vi is so hard to use!  Why would anyone want to learn such a difficult editor?&#8221;  And now I can&#8217;t imagine life without it.  I&#8217;ve mainly written this post as a diary entry, both to organize my thoughts on the matter, and hopefully to have something to look back down on after scaling the Emacs learning cliff.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<p>No related photos.</p>
]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2007/07/06/lisp-enlightenment-and-emacs-frustration/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
<enclosure url="http://common-lisp.net/movies/slime.mov" length="156295708" type="video/quicktime" />
		</item>
		<item>
		<title>Javascript Gunner</title>
		<link>http://erikras.com/2007/05/21/javascript-gunner/</link>
		<comments>http://erikras.com/2007/05/21/javascript-gunner/#comments</comments>
		<pubDate>Mon, 21 May 2007 00:04:08 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/2007/05/21/javascript-gunner/</guid>
		<description><![CDATA[Welcome to the Javascript Gunner page. This little script that I wrote is an example of the kind of thing that can be done with the javascript &#60;canvas&#62; tag and a little imagination. Why should your drawings be confined to the &#60;canvas&#62; tag when the &#60;canvas&#62; tags themselves can be moved around the page? This [...]<h3>Related Photos</h3>
<ol>
				</ol>

]]></description>
			<content:encoded><![CDATA[<p>Welcome to the Javascript Gunner page. This little script that I wrote is an example of the kind of thing that can be done with the javascript <a href="http://en.wikipedia.org/wiki/Canvas_%28HTML_element%29">&lt;canvas&gt; tag</a> and a little imagination. Why should your drawings be confined to the &lt;canvas&gt; tag when the &lt;canvas&gt; tags themselves can be moved around the page?<br />
<span id="more-268"></span><br />
<strong>This effect is not compatible with Internet Explorer!!</strong> Download <a href="http://www.mozilla.com/en-US/firefox/">a real browser</a> if you want to see it.  It&#8217;s been tested on Firefox and Safari.  It cannot work on IE because it depends on the &lt;canvas&gt; tag and fixed element positioning, which IE does not support.</p>
<h3>What&#8217;s happening?</h3>
<p>Each gunner moves around the perimeter of the web page and fires bullets towards your mouse pointer. That&#8217;s it. There&#8217;s no game to it. It&#8217;s just a demonstration.  But that doesn&#8217;t mean you can&#8217;t have a little fun with it!  If you leave your mouse cursor perfectly still, every bullet will hit it.</p>
<h3>So let&#8217;s play!</h3>
<div>
<input type="button" onclick="new Gunner(100);" value="Add Gunner"/>
</div>
<div>
<input type="button" onclick="new Gunner(200);" value="Add Big Gunner"/>
</div>
<div>
<input type="button" onclick="new Gunner(50);" value="Add Small Gunner"/>
</div>
<div>
<input type="button" onclick="new Gunner(100, '#0000FF');" value="Add Blue Gunner"/>
</div>
<div>
<input type="button" onclick="new Gunner(100, '#FF0000');" value="Add Red Gunner"/>
</div>
<p>Be careful.  It&#8217;s very easy to overload your browser with too many gunners.</p>
<h3>The Code</h3>
<p>You are more than welcome to take a look at <a href="http://erikras.com/downloads/268/gunner.js">gunner.js</a> (12 KiB), download it, and use it on your own website.</p>
<p><script type="text/javascript" src="http://erikras.com/downloads/268/gunner.js"></script><br />
<script type="text/javascript">new Gunner(100);</script></p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<ol>
				</ol>

]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2007/05/21/javascript-gunner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Shadower &#8211; Realistic Drop Shadows in Javascript</title>
		<link>http://erikras.com/2006/12/04/the-shadower-realistic-drop-shadows-in-javascript/</link>
		<comments>http://erikras.com/2006/12/04/the-shadower-realistic-drop-shadows-in-javascript/#comments</comments>
		<pubDate>Mon, 04 Dec 2006 00:31:53 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/2006/12/04/the-shadower-realistic-drop-shadows-in-javascript/</guid>
		<description><![CDATA[This has been done before, but not in such a simple and elegant way, in my opinion. This implementation has four important features that separate it from the rest: no images, no messy nested divs in your html code, no CSS, and realistic fading shadows! It is based on the Prototype Javascript Framework, and requires [...]<h3>Related Photos</h3>

No related photos.
]]></description>
			<content:encoded><![CDATA[<p>This has been done before, but not in such a simple and elegant way, in my opinion.  This implementation has four important features that separate it from the rest: no images, no messy nested divs in your html code, no CSS, and realistic fading shadows!<br />
<span id="more-143"></span><br />
It is based on the <a href="http://prototype.conio.net/">Prototype Javascript Framework</a>, and requires version 1.5, which you can get <a href="http://erikras.com/downloads/143/prototype.js">here</a>.<br />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.2/effects.js"></script><br />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.2/dragdrop.js"></script><br />
<script type="text/javascript" src="/blog/shadower.js"></script></p>
<h3>Some Examples</h3>
<p>Other drop shadow libraries that eschew images, provide their shadow by adding an absolutely positioned div just behind the object.  Like so&#8230;</p>
<div id="example1" style="width:150px;z-index:10;background-color:#ff9999;text-align:center;padding:2px;cursor:move;"><strong>Example 1</strong><br /><small>(Drag Me Around)</small></div>
<p><script type="text/javascript">
var example1 = function() { Shadower.shadow('example1', {opacity:1.0,nestedShadows:1}); }
setTimeout(example1, 1); // IE doesn't like shadowing mid-flow
new Draggable('example1', { change: example1, starteffect: Prototype.emptyFunction, reverteffect: Prototype.emptyFunction, endeffect: Prototype.emptyFunction});</script><br />
I think you&#8217;ll agree that that looks pretty bad.  But it&#8217;s a lot better with a little opacity tweak&#8230;</p>
<div id="example2" style="width:150px;z-index:20;background-color:#99ff99;text-align:center;padding:2px;cursor:move;"><strong>Example 2</strong><br /><small>(Drag Me Around)</small></div>
<p><script type="text/javascript">
var example2 = function() { Shadower.shadow('example2', {opacity:0.7,nestedShadows:1}); }
setTimeout(example2, 1); // IE doesn't like shadowing mid-flow
new Draggable('example2', { change: example2, starteffect: Prototype.emptyFunction, reverteffect: Prototype.emptyFunction, endeffect: Prototype.emptyFunction});</script></p>
<p>But it still just looks like a gray box under there, doesn&#8217;t it?  That&#8217;s where the magic of The Shadower comes in.  Rather than just one gray box, it uses several successively smaller boxes stacked on top of each other to create a realistic drop shadow that really fades into the background.</p>
<div id="example3" style="width:150px;z-index:30;background-color:#9999ff;text-align:center;padding:2px;cursor:move;"><strong>Example 3</strong><br /><small>(Drag Me Around)</small></div>
<p><script type="text/javascript">
var example3 = function() { Shadower.shadow('example3', {opacity:0.7,nestedShadows:4}); }
setTimeout(example3, 1); // IE doesn't like shadowing mid-flow
new Draggable('example3', { change: example3, starteffect: Prototype.emptyFunction, reverteffect: Prototype.emptyFunction, endeffect: Prototype.emptyFunction});</script><br />
Now, doesn&#8217;t that look better?  Drag it up next to the others if you aren&#8217;t convinced.</p>
<h3>So how do I use it?</h3>
<p>There are five parameters to play with in getting your drop shadow just right.</p>
<dl>
<dt><strong>distance</strong> [default: 8]</dt>
<dd>The distance away from the shadowed element to draw the shadow.  This can also be thought of as the height &#8220;above the page&#8221; of the shadowed object</dd>
<dt><strong>angle</strong> [default: 130]</dt>
<dd>The direction away from the shadowed element to draw the shadow.  It is measured in degrees from the vertical.  If you think of it like the numbers on a clock, 12 is at 0&deg;, 3 is at 90&deg;, 6 is at 180&deg;, 9 is at 270&deg;, etc.  The default angle of 130 would be between 3 and 4 on the clock face.</dd>
<dt><strong>opacity</strong> [default: 0.7]</dt>
<dd>The opacity of the shadow, measured between 0.0 and 1.0.</dd>
<dt><strong>nestedShadows</strong> [default: 4]</dt>
<dd>This is the number of gradually darker shadows to draw under the shadowed element.</dd>
<dt><strong>color</strong> [default: #000000]</dt>
<dd>This is the color of the shadow.  The default black color is good enough for most uses, but you can change it if you want.</dd>
</dl>
<h3>Go ahead!  Play with it!</h3>
<p><script type="text/javascript">
function runShadower() {
try {
  $('shadower_error').innerHTML = '';
  var options = { distance: $('shadower_distance').value, angle: $('shadower_angle').value, opacity: $('shadower_opacity').value, nestedShadows: $('shadower_nestedShadows').value, color: '#' + $('shadower_color').value};
  if(isNaN(options.distance)) throw 'Invalid distance parameter';
  if(isNaN(options.angle)) throw 'Invalid angle parameter';
  if(isNaN(options.opacity)) throw 'Invalid opacity parameter';
  if(isNaN(options.nestedShadows)) throw 'Invalid nestedShadows parameter';
  $('shadower_code').innerHTML = 'Shadower.shadow(\'testExample\',<br />{<br />&nbsp;&nbsp;distance: '+options.distance+',<br />&nbsp;&nbsp;angle: '+options.angle+',<br />&nbsp;&nbsp;opacity: '+options.opacity+',<br />&nbsp;&nbsp;nestedShadows: '+options.nestedShadows+',<br />&nbsp;&nbsp;color: \''+options.color+'\'<br />});';
  Shadower.shadow('testExample', options, true);
}
catch (e) {
  $('shadower_error').innerHTML = e;
}
}
function shadowerPresets()
{
  var options = Object.extend({distance:8,angle:130,opacity:0.7,nestedShadows:4},arguments[0]);
  $('shadower_distance').value = options.distance;
  $('shadower_angle').value = options.angle;
  $('shadower_opacity').value = options.opacity;
  $('shadower_nestedShadows').value = options.nestedShadows;
  $('shadower_color').value = '000000';
  runShadower();
}
</script></p>
<div id="testExample" style="width:150px;z-index:40;background-color:#ff99ff;text-align:center;padding:2px;cursor:move;"><strong>Test Example</strong><br /><small>(Drag Me Around)</small></div>
<p><script type="text/javascript">new Draggable('testExample', { change: runShadower, starteffect: Prototype.emptyFunction, reverteffect: Prototype.emptyFunction, endeffect: Prototype.emptyFunction});</script></p>
<div style="text-align:center;width:100%">
<div id="shadower_error" style="width:100%;height:20px;font-weight:bold;color:#ff0000"> </div>
<table style="margin-left:40px;margin-bottom:15px;">
<tr>
<th style="text-align:right">distance:</th>
<td>
<input id="shadower_distance" onkeyup="runShadower()" type="text" style="width:40px;padding:2px;text-align:right;" value="8"/></td>
<th style="text-align:right">angle:</th>
<td>
<input id="shadower_angle" onkeyup="runShadower()" type="text" style="width:40px;padding:2px;text-align:right;" value="130"/></td>
</tr>
<tr>
<th style="text-align:right">opacity:</th>
<td>
<input id="shadower_opacity" type="text" onkeyup="runShadower()" style="width:40px;padding:2px;text-align:right;" value="0.7"/></td>
<th style="text-align:right">nestedShadows:</th>
<td>
<input id="shadower_nestedShadows" type="text" onkeyup="runShadower()" style="width:40px;padding:2px;text-align:right;" value="4"/></td>
</tr>
<tr>
<th style="text-align:right">color:</th>
<td>
<input id="shadower_color" type="text" style="padding:2px;width:55px;" onkeyup="runShadower()" value="000000"/></td>
</tr>
</table>
<p>Presets: <a href="javascript:shadowerPresets({opacity:1,nestedShadows:1});" style="margin-left:15px;">Example 1</a><a href="javascript:shadowerPresets({nestedShadows:1});" style="margin-left:15px;">Example 2</a><a href="javascript:shadowerPresets({});" style="margin-left:15px;">Example 3</a></p>
<p><code id="shadower_code" style="text-align:left;"> </code>
</div>
<p><script type="text/javascript">setTimeout(runShadower, 1); // IE doesn't like shadowing mid-flow</script></p>
<h3>Recommended Usage</h3>
<p>Ideally, you should set a CSS class on any elements that you want shadowed, and then call Shadower.shadowWithClass() on page load.  Like so&#8230;</p>
<p><code>&lt;html&gt;<br />
&nbsp;&nbsp;&lt;head&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;script type="text/javascript" src="shadower.js"&gt;&lt;/script&gt;<br />
&nbsp;&nbsp;&lt;/head&gt;<br />
&nbsp;&nbsp;&lt;body onload="Shadower.shadowWithClass('shadowed');"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;div class="shadowed"&gt;This div is shadowed&lt;/div&gt;<br />
&nbsp;&nbsp;&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<h3>Download</h3>
<p>So what are you waiting for?  Download it and start using it!</p>
<p><a href="http://erikras.com/downloads/143/prototype.js" style="margin-left:30px;margin-bottom:20px;padding:10px;width:400px;float:left;border:2px outset #990000;text-align:center;font-weight:bold;background-color:#E5ECF7">prototype.js</a></p>
<p><a href="http://erikras.com/downloads/143/shadower.js" style="margin-left:30px;margin-bottom:20px;padding:10px;width:400px;float:left;border:2px outset #990000;text-align:center;font-weight:bold;background-color:#E5ECF7">shadower.js</a></p>
<h3>Feedback</h3>
<p>I have not yet tested this on all browsers.  If you have any problems, please either leave a comment on this blog entry or email me at erikwordpressplugins -at- gmail.</p>
<p>Enjoy!</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<p>No related photos.</p>
]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2006/12/04/the-shadower-realistic-drop-shadows-in-javascript/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Multiple Inheritance in Java</title>
		<link>http://erikras.com/2006/10/23/multiple-inheritance-in-java/</link>
		<comments>http://erikras.com/2006/10/23/multiple-inheritance-in-java/#comments</comments>
		<pubDate>Mon, 23 Oct 2006 01:55:10 +0000</pubDate>
		<dc:creator>erik</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Musings]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.erik-rasmussen.com/blog/2006/10/23/multiple-inheritance-in-java/</guid>
		<description><![CDATA[I have come up with a way to accomplish multiple inheritance1 in Java using interfaces with static inner classes, which I will now present to you. First we need to define a problem that requires multiple inheritance. Let us suppose that I have a superclass, DbObject, that allows its subclasses to be loaded from and [...]<h3>Related Photos</h3>

No related photos.
]]></description>
			<content:encoded><![CDATA[<p>I have come up with a way to accomplish <a href="http://en.wikipedia.org/wiki/Multiple_inheritance">multiple inheritance</a><sup>1</sup> in <a href="http://java.sun.com/">Java</a> using interfaces with static inner classes, which I will now present to you.<br />
<span id="more-109"></span><br />
First we need to define a problem that requires multiple inheritance.  Let us suppose that I have a superclass, DbObject, that allows its subclasses to be loaded from and saved to the database.  We also have two abstract subclasses of DbObject, ProjectADbObject and ProjectBDbObject which provide project specific functionality to all the DbObjects of each project (<a href="#classdiagram">see class diagram</a>).  Now let&#8217;s assume that both projects need a DbObject that can represent a tree structure, say Folder and Category for Project A and Project B respectively.  This tree structure is represented by an interface that we will call SelfParenting.  Like so:</p>
<pre class="code"><span class="keyword">public interface</span> SelfParenting
{
  SelfParenting getParent(Database db) <span class="keyword">throws</span> DbException;
}</pre>
<p>Note that to fetch the actual instance, not just the foreign key reference, of our parent, we require the database.</p>
<p>So we have our two classes:</p>
<pre class="code"><span class="keyword">public class</span> Folder <span class="keyword">extends</span> ProjectADbObject
  <span class="keyword">implements</span> SelfParenting
{
  <span class="keyword">private</span> ForeignKey&lt;Folder&gt; <span class="member">parent</span>;
  ...
  <span class="keyword">public</span> Folder getParent(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> db.fetch(<span class="member">parent</span>);
  }
  ...
}</pre>
<p>and</p>
<pre class="code"><span class="keyword">public class</span> Category <span class="keyword">extends</span> ProjectBDbObject
  <span class="keyword">implements</span> SelfParenting
{
  <span class="keyword">private</span> ForeignKey&lt;Category&gt; <span class="member">parent</span>;
  ...
  <span class="keyword">public</span> Category getParent(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> db.fetch(<span class="member">parent</span>);
  }
  ...
}</pre>
<p>Obviously, we&#8217;re going to want more functionality than just getParent() if our interface is going to be useful.  What about methods for getting the children or the depth in the tree?  So we add these to our interface:</p>
<pre class="code"><span class="keyword">public interface</span> SelfParenting
{
  SelfParenting getParent(Database db) <span class="keyword">throws</span> DbException;
  SelfParenting[] getChildren(Database db) <span class="keyword">throws</span> DbException;
  <span class="keyword">int</span> getDepth(Database db) <span class="keyword">throws</span> DbException;
}</pre>
<p>And this is where we run into the multiple inheritance wall.  The implementation of getChildren() and getDepth() require more than one line, and the code will be exactly the same in both Folder and Category.  First, let&#8217;s look at what the code might look like for the Folder class:</p>
<pre class="code"><span class="keyword">public class</span> Folder <span class="keyword">extends</span> ProjectADbObject
  <span class="keyword">implements</span> SelfParenting
{
  <span class="keyword">private</span> ForeignKey&lt;Folder&gt; <span class="member">parent</span>;
  ...
  <span class="keyword">public</span> Folder getParent(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> db.fetch(<span class="member">parent</span>);
  }

  <span class="keyword">public</span> Folder[] getChildren(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">final</span> Collection&lt;Folder&gt; children =
      <span class="keyword">new</span> ArrayList&lt;Folder&gt;();
    <span class="keyword">for</span>(<span class="keyword">final</span> Folder folder : db.fetchAll(Folder.<span class="keyword">class</span>))
    {
      <span class="keyword">if</span>(folder.getParent(db).equals(<span class="keyword">this</span>))
        children.add(folder);
    }
    <span class="keyword">return</span> children.toArray(<span class="keyword">new</span> Folder[<span class="number">0</span>]);
  }

  <span class="keyword">public int</span> getDepth(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">int</span> depth = <span class="number">0</span>;
    Folder folder = <span class="keyword">this</span>;
    <span class="keyword">while</span>(folder.getParent() != <span class="keyword">null</span>)
    {
      depth++;
      folder = folder.getParent(db);
    }
    <span class="keyword">return</span> depth;
  }
  ...
}</pre>
<p>Obviously, the code will be identical in the Directory class.  Is there any way to avoid this code duplication?  What if we put the code into static methods of a static inner class of the interface?  Like so:</p>
<pre class="code"><span class="keyword">public interface</span> SelfParenting
{
  SelfParenting getParent(Database db) <span class="keyword">throws</span> DbException;
  SelfParenting[] getChildren(Database db) <span class="keyword">throws</span> DbException;
  int getDepth(Database db) <span class="keyword">throws</span> DbException;

  <span class="keyword">public static class</span> Impl
  {
    <span class="keyword">public static</span> &lt;T <span class="keyword">extends</span> SelfParenting&gt;
    T[] getChildren(<span class="keyword">final</span> Database db, <span class="keyword">final</span> T parent)
      <span class="keyword">throws</span> DbException
    {
      <span class="keyword">final</span> Collection&lt;T&gt; children = <span class="keyword">new</span> ArrayList&lt;T&gt;();
      <span class="keyword">final</span> T[] all = db.fetchAll(parent.getClass());
      <span class="keyword">for</span>(<span class="keyword">final</span> T possibleChild : all)
      {
        <span class="keyword">if</span>(possibleChild.getParent(db).equals(parent))
          children.add(possibleChild);
      }
      <span class="keyword">return</span> children.toArray(<span class="keyword">new</span> T[<span class="number">0</span>]);
    }

    <span class="keyword">public static int</span> getDepth(<span class="keyword">final</span> Database db,
                               SelfParenting node)
      <span class="keyword">throws</span> DbException
    {
      <span class="keyword">int</span> depth = <span class="number">0</span>;
      <span class="keyword">while</span>(node.getParent() != <span class="keyword">null</span>)
      {
        depth++;
        node = node.getParent(db);
      }
      <span class="keyword">return</span> depth;
    }
  }
}</pre>
<p>Then, the implementation of the new methods shrink down to one line:</p>
<pre class="code"><span class="keyword">public class</span> Folder <span class="keyword">extends</span> ProjectADbObject
  <span class="keyword">implements</span> SelfParenting
{
  <span class="keyword">private</span> ForeignKey&lt;Folder&gt; <span class="member">parent</span>;
  ...
  <span class="keyword">public</span> Folder getParent(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> db.fetch(parent);
  }

  <span class="keyword">public</span> Folder[] getChildren(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> Impl.<span class="static">getChildren</span>(db, <span class="keyword">this</span>);
  }

  <span class="keyword">public int</span> getDepth(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> Impl.<span class="static">getDepth</span>(db, <span class="keyword">this</span>);
  }
  ...
}</pre>
<p>And so the proper implementation of Category will be the same:</p>
<pre class="code"><span class="keyword">public class</span> Category <span class="keyword">extends</span> ProjectBDbObject
  <span class="keyword">implements</span> SelfParenting
{
  <span class="keyword">private</span> ForeignKey&lt;Category&gt; <span class="member">parent</span>;
  ...
  <span class="keyword">public</span> Category getParent(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> db.fetch(parent);
  }

  <span class="keyword">public</span> Category[] getChildren(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> Impl.<span class="static">getChildren</span>(db, <span class="keyword">this</span>);
  }

  <span class="keyword">public int</span> getDepth(<span class="keyword">final</span> Database db)
    <span class="keyword">throws</span> DbException
  {
    <span class="keyword">return</span> Impl.<span class="static">getDepth</span>(db, <span class="keyword">this</span>);
  }
  ...
}</pre>
<p>By moving the common implementation of the getChildren() and getDepth() methods into the interface (via a static inner class), we have eliminated the duplication of code, thereby enhancing the maintainability and enabling future implementations of SelfParenting to be trivial one-line methods.</p>
<p>The code above is obviously very inefficient<sup>2</sup>, but it was provided to demonstrate a point: that the advantages of multiple inheritance can be achieved in java via this &#8220;static methods in a static inner class in the interface&#8221; coding pattern.<br />
<a name="classdiagram"><br />
<h3>Class Diagram</h3>
<p></a><img src="http://farm2.static.flickr.com/1425/538540043_9b422165c1_o.jpg" width="442" height="502" alt="Multiple Inheritance Class Diagram"/></p>
<p class="footnote"><sup>1</sup>Note that this accomplishes the code reuse feature of multiple inheritance <em>only</em>.  In theory, you could get the effects of polymorphism by doing more than, or something other than, just call the static implementation in the interface.</p>
<p><sup>2</sup>A proper implementation of getChildren() would involve SQL where clauses.  There are also generics issues that would cause the code, as shown, to not compile.  The concept remains sound.</p>
<div class="promote"><div class="tweet-button"><a href="http://twitter.com/share" class="twitter-share-button" data-url="http://erikras.com?utm_source=Twitter&utm_medium=Social&utm_campaign=Tweet%2BButton" data-via="erikras" data-count="horizontal" data-related="noraras" data-text="American in Spain: Thoughts and photos from an American living in Spain.">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook-like"><iframe src="http://www.facebook.com/plugins/like.php?href=http://erikras.com%3Futm_source%3DFacebook%26utm_medium%3DSocial%26utm_campaign%3DLike%252BButton&amp;layout=button_count&amp;show_faces=false&amp;width=250&amp;action=recommend&amp;colorscheme=light&amp;height=35" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:35px;" allowTransparency="true"></iframe></div><div class="google-plus-one"><g:plusone></g:plusone><div class="flattr"><a class="FlattrButton" style="display:none;"title="American in Spain: Thoughts and photos from an American living in Spain."lang="en_US"rev="flattr;uid:erikras;category:rest;button:compact;"href="http://erikras.com">American in Spain: Thoughts and photos from an American living in Spain.</a></div><script type="text/javascript">(function() {var s=document.createElement("script"),t=document.getElementsByTagName("script")[0];s.type = "text/javascript";s.async = true;s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";t.parentNode.insertBefore(s, t);})();</script></div></div><span style="clear:both;">&nbsp;</span><h3>Related Photos</h3>
<p>No related photos.</p>
]]></content:encoded>
			<wfw:commentRss>http://erikras.com/2006/10/23/multiple-inheritance-in-java/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

