<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1511105172892878010</id><updated>2011-12-07T23:32:45.680-05:00</updated><category term='big-o'/><category term='3D Desktop'/><category term='javascript'/><category term='algorithms'/><category term='discrete mathematics'/><category term='OS X'/><category term='random'/><title type='text'>When no one is looking...</title><subtitle type='html'>I eat thunderclouds and chew on mountain tops.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://wollardj.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://wollardj.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Joe Wollard</name><uri>http://www.blogger.com/profile/08050020309888365234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1511105172892878010.post-8846064600472215367</id><published>2011-09-09T15:49:00.000-04:00</published><updated>2011-09-09T15:53:13.229-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><title type='text'>Caching Calculations in Javascript</title><content type='html'>I've been asked to demonstrate a solution to a small problem using JavaScript. The problem is basically one of scope and calculation caching, and is defined thusly:&lt;br /&gt;&lt;blockquote&gt;I have two functions that perform calculations. Function A is always called before function B, and function B always calls function A. How can I make this more efficient?&lt;/blockquote&gt;Of course there's probably a way to solve this problem through refactoring the code, but let's pretend there isn't in our scenario. Javascript is a prototypal language, not a class based one. Fortunately for us, this means we can create a function and then attach properties to it that make it behave somewhere between a true function and an object. On to the code...&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Internally Managed Data Caching&lt;/span&gt;&lt;br /&gt;If a function performs heavy calculations, you really don't want it to perform the calculations over and over again, especially not while the parameters are the same. The following function employs caching to make its execution more efficient:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;function A()&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;if (A.cache === false)&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Our super complex calculation&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; A.cache = 1 + 2 + 3 + 4;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return A.cache;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// Define a static variable that is local to the A function that&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// will store the result of the super complex calculations.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;A.cache = false;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;In the above example, we've made a function and a property attached to that function that is used to&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;store the result of a calculation. The first time the function is executed, the cache container "&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A.cache&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;" property is set to 'false' which triggers the calculation to be performed. But notice that instead of simply returning the value of the calculation, we cache it. Since the function is always returning the cached calculation, it can be called as many times as you want, but it will only perform the calculation once. So with the problem stated above, you could call function &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;, then function &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;B&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; knowing full well that function &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;will get called a total of two times, but will only do any actual work once.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Externally Managed Data Caching&lt;/span&gt;&lt;/div&gt;&lt;div&gt;How can you force the function to refresh its cache if there's no way to tell it that the environment changed in such a way that the result of the calculation could be different? What you really need is a mechanism for informing the function that its cache is dirty and needs to be refreshed. This could technically be done by setting &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A.cache = false&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;, but here's a slightly more robust example&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;function A()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;if (A.cache === false&lt;b&gt; || A.cacheIsDirty !== false&lt;/b&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Our super complex calculation&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; A.cache = 1 + 2 + 3 + 4;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;A.cacheIsDirty = false;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: Times;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return A.cache;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// Define a static variable that is local to the A function that&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// will store the result of the super complex calculations.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A.cache = false;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// Define a static variable that is local to the A function that&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// will be used to inform function A that its cache is not to be&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;// trusted.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;A.cacheIsDirty = true;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Times; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;And done! We've now got a way for outside code to warn a function that its internal cache may no longer be safe to use. A simple use case for this might be a form wherein a user can input multiple parameters and then view the calculations. Well, if the user doesn't modify any of the parameters that function A might need to look at, then it should be allowed to return the cached result. But if the user &lt;i&gt;does&lt;/i&gt;&amp;nbsp;change a parameter that function A cares about, then the piece of code that was listening for that change can call &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;A.cacheIsDirty = true;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;to make sure that function A will discard its cache and run its calculations again.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1511105172892878010-8846064600472215367?l=wollardj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wollardj.blogspot.com/feeds/8846064600472215367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1511105172892878010&amp;postID=8846064600472215367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/8846064600472215367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/8846064600472215367'/><link rel='alternate' type='text/html' href='http://wollardj.blogspot.com/2011/09/caching-calculations-in-javascript.html' title='Caching Calculations in Javascript'/><author><name>Joe Wollard</name><uri>http://www.blogger.com/profile/08050020309888365234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1511105172892878010.post-918270068103177690</id><published>2011-09-08T22:27:00.001-04:00</published><updated>2011-09-08T22:27:59.889-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='random'/><category scheme='http://www.blogger.com/atom/ns#' term='3D Desktop'/><title type='text'>Getting Back To Nature, On Our Computers</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;It's my humble opinion that Apple has been the clear victor in the battle to create an easy to use computer interface, however there are still elements that just don't make sense to everyone. Is it even possible to make a user interface that everyone can easily understand? Given that&amp;nbsp;&lt;/span&gt;"It is impossible to make anything foolproof, because fools are so ingenious.", I doubt it. But I believe you're only saying it's impossible because no one has ever done it before. (major geek points to anyone who gets both references)&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Let me start by admitting that I watched Discovery's "Curiosity:&amp;nbsp;&lt;a href="http://youtu.be/fpb7NMR-XOo"&gt;Did God Create The Universe&lt;/a&gt;" with &lt;a href="http://www.hawking.org.uk/"&gt;Stephen Hawking&lt;/a&gt;&amp;nbsp;last night. One of the things that Stephen drives home is that the laws of nature, or physics, are immutable and cannot be broken. They are also universally understood and obeyed. Keep that in your back pocket. I'm coming back to it.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Earlier today I logged into an OS X computer to assist a customer of mine and noticed something brief, but odd. The global menu bar at the top of the screen wasn't visible, yet its shadow was. Clearly this breaks a few fundamental laws of nature and would never happen in the physical world. So about 0.75 seconds later, I found that I had resolved that issue by tying Professor Hawking's cautionary notes about the laws of nature into a desktop environment. It was a desktop environment that embraced the laws of nature instead of poorly mimicking them or outright ignoring them.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The easiest way to define the desktop environment that I envisioned is to remind my imaginary development team that two objects having mass cannot occupy the same space at the same time. That and to force them into believing that computer graphics have mass. This is a law that even my fish understands; he knows that he can't go through the rocks at the bottom of his tank nor the glass that surrounds him. He might not understand exactly why, but it makes sense to him that he cannot pass through those things. He also understands how to move water around him, not through him, so that he can swim. Try to apply this rule to any part of the current desktop/windowing systems out there and I think you'll find that they break that law in almost every instance. Icons overlap each other on the desktop and neither one is clearly on top of another; two inactive windows are positioned behind a third window in such a way that it is unclear which one is in the middle and which one is behind the other two. Why have we complacantly put up with this for so long, realizing that our interactions with computers have no analog in the physical world.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit; font-size: large;"&gt;The Missing Z Axis&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Every windowing system attempts a half-hearted implementation of the &lt;a href="http://en.wikipedia.org/wiki/Z-axis#Cartesian_coordinates_in_three_dimensions"&gt;z axis&lt;/a&gt;, as do some applications such as the browser your using right now (think&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Z-index"&gt;z-index&lt;/a&gt;). The problem with the current system is that it doesn't provide a truly 3 dimensional experience for the user. Instead, it allows objects to be stacked in a particular order in 2 dimensions. But what if we introduced three extra attributes to those objects?&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Space&lt;/b&gt;: Everything we interact with is surrounded by space. We reach for things through space, we pry things apart by inserting a tool into a space too small for our fingers, we expect and understand space.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Perspective Scaling&lt;/b&gt;: When things get further away from us, they appear to shrink. When they are getting closer, they appear to grow. Virtual objects should therefore also shrink and grow as is appropriate for their distance from us.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Visual Clarity&lt;/b&gt;: This is one area where modern windowing systems are getting close, but still don't quite have it down. The blur effect is somewhat annoying in its current state, but that's because most implementations are boolean; blur on vs. blur off. But if we have 20/20 vision and something is 21 feet away from us, it starts to appear a little fuzzy. Objects that are 50 feet away are increasingly fuzzy. So let's take the blur effect and make it a little more intelligent. For a spiffier desktop environment, we could even introduce a lightweight particle system to simulate the particles that make things appear lighter (assuming a sunny day) the more distant they are.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;But 3D Desktops Suck&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Yep, they do and yes I realize that I'm describing one. I strongly believe the reason that they suck is the same reason 2D desktops suck: They are attempting to look interesting but don't actually remind us of anything in the physical world. Developers and engineers aren't to blame here. We simply don't have a holodeck yet, and until we do 3D is going to be a pretty tough sell for our senses.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Okay, so why am I proposing a 3D desktop if I think they suck? The answer is simply that I don't want a 3D desktop. What I want is an experience akin to a surgeon using a camera inside a patient to see where to cut. In other words, I want a 2 dimensional interface to a place that my mind can believe is 3 dimensional. No, it's not ideal, but it's a better use of current technology than what we're doing with it right now.&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Interacting With a 3D World with a 2D Interface&lt;/span&gt;&lt;br /&gt;We already know how to get from point A to point B on a cartesian plane; you just move your mouse and your cursor moves to that point. But how can we easily move along the z axis without special hardware? I'm sure there are plenty of ideas out there, but one of them might finally be a good use for "hot corners", or maybe even hot 'edges'. Say you want to zoom out to a window behind you, maybe you move the mouse to the bottom of the screen or to one of the bottom corners. Zooming in could be done by either moving your mouse to the top of the screen, or by simply clicking on a window that is in the distance. To make zooming a little more friendly, we can take a page from Apple's menu scrolling engine wherein scrolling starts slowly and immediately when the mouse enters the appropriate area of the menu, then increases in speed as the mouse is held in place.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Back to the Shadows&lt;/span&gt;&lt;br /&gt;Remember way back at the beginning of this post how the whole idea started because I saw a shadow with no object? Let's wrap this up by getting back to that. Current window shadowing techniques generally only have 3 possible states: A bold shadow for the active window, a not-so-bold shadow for all of the inactive windows, and no shadow at all for those utility windows. You may have noticed as you peel your eyes away from the computer screen that this is yet another area where there is no real world analog. But hey, we've just described a 3D space for those windows which means we should be able to fix this problem as well.&lt;br /&gt;&lt;br /&gt;The existence of a shadow implies three things; a light source, an object with mass in the foreground, and an object with mass in the background. Current shadowing techniques have, or at least imply, all three of these things. But where is that light source exactly? It's almost directly behind our heads. Every real-world scenario that I can come up with where any light source would be behind my head involves a face-plant, which I'm not terribly fond of.&lt;br /&gt;&lt;br /&gt;We've got a 3D space for windows &lt;i&gt;and&lt;/i&gt;&amp;nbsp;their shadows now, so let's move that light source to someplace a little more natural, someplace a little higher above us and maybe off to one side a bit. Heck, it could even move around a bit to correspond with the time of day. We can then project the shadows on the floor of our 3D space. In this instance, the window that is in focus wouldn't have a shadow at all while windows in the background would. Think of a scenario where you're reading a newspaper while waiting for the bus. The newspaper has no shadow that you care to acknowledge because its shadow is being cast outside of your field of vision. However, if you peer around your newspaper for just a moment and notice another person standing just like you, reading the same paper that you're reading, you &lt;i&gt;can&lt;/i&gt;&amp;nbsp;see the shadow that their paper casts on the ground or perhaps on the other person's legs because both the paper and its shadow fit within your field of vision.&lt;br /&gt;&lt;br /&gt;So let's move the shadows down to the ground where they belong, and lets let the things we're looking at feel like they are really right in front of us while everything else is far away. For a little per-widow depth, we could add subtle widget shadows. For example, I can see a shadow being cast in Safari right now that is meant to make the tabs appear to be beneath the address bar and slightly embedded. Let's keep that going, but make it adhere to the position of the light source so it makes sense.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Fin&lt;/span&gt;&lt;br /&gt;So there we have it. A poorly described, but fairly thorough thought experiment into a 3D desktop with a 2D interface. You know what would really make this idea cool? Using it on a tablet that supports multitouch. I'd imagine you could zip around quite nicely within 3 dimensions on one of those things. If anyone decides to implement such a concept, I'd love to know about it and help test it. I'd also gladly accept royalties or shares in your wildly successful company. ;-)&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1511105172892878010-918270068103177690?l=wollardj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wollardj.blogspot.com/feeds/918270068103177690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1511105172892878010&amp;postID=918270068103177690' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/918270068103177690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/918270068103177690'/><link rel='alternate' type='text/html' href='http://wollardj.blogspot.com/2011/09/getting-back-to-nature-on-our-computers.html' title='Getting Back To Nature, On Our Computers'/><author><name>Joe Wollard</name><uri>http://www.blogger.com/profile/08050020309888365234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1511105172892878010.post-1451193887231887027</id><published>2007-01-20T13:55:00.000-05:00</published><updated>2011-09-07T14:05:20.192-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='big-o'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='discrete mathematics'/><title type='text'>Big-O Example</title><content type='html'>If you're like me you've seen the term "Big-O" but didn't quite grasp it the first time. You've also probably looked all over the Internet trying to make heads or tails of this seemingly complex term. If you weren't confused by the first definition that you found, try checking out the &lt;a href="http://en.wikipedia.org/wiki/Big-O"&gt;Wikipedia&lt;/a&gt; entry - that should get you nice and confused.&lt;br /&gt;&lt;br /&gt;The purpose of Big-O notation is to provide a language that describes how efficient an algorithm is (or is not) without taking into consideration the exact speed of a particular computer that it might be running on. But how to calculate it?&lt;br /&gt;&lt;br /&gt;Eventually I found a short mention of this topic in "&lt;a href="http://www.amazon.com/Objects-Abstraction-Data-Structures-Design/dp/0471692646/sr=11-1/qid=1169319740/ref=sr_11_1/002-6331559-3993658"&gt;Objects, Abstraction, Data Structures and Design using Java Version 5.0&lt;/a&gt;" by Elliot B. Koffman and Paul A.T. Wolfgang that seemed to make sense to me, and hopefully will click for you as well. The following was taken from pg113 Example 2.19:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Given T(&lt;i&gt;n&lt;/i&gt;) = &lt;i&gt;n&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; + 5&lt;i&gt;n&lt;/i&gt; + 25, we want to show that this is indeed O(n&lt;sup&gt;2&lt;/sup&gt;). Thus we want to show that there are constants &lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt; and &lt;i&gt;c&lt;/i&gt; such that for all &lt;i&gt;n&lt;/i&gt; &amp;gt; &lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt;, &lt;i&gt;cn&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; &amp;gt; &lt;i&gt;n&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; + 5&lt;i&gt;n&lt;/i&gt; + 25. To solve this we need to find a point where&lt;br /&gt;&lt;code&gt;&lt;i&gt;cn&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; = &lt;i&gt;n&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; + 5&lt;i&gt;n&lt;/i&gt; + 25&lt;/code&gt;&lt;br /&gt;If we let &lt;i&gt;n&lt;/i&gt; be &lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt; and solve for &lt;i&gt;c&lt;/i&gt;, we get&lt;br /&gt;&lt;code&gt;&lt;i&gt;c&lt;/i&gt; = 1 + 5/&lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt; + 25/&lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/code&gt;&lt;br /&gt;For an &lt;i&gt;n&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt; of 5, this gives us a &lt;i&gt;c&lt;/i&gt; of 3. So 3&lt;i&gt;n&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; &amp;gt; &lt;i&gt;n&lt;/i&gt;&lt;sup&gt;2&lt;/sup&gt; + 5&lt;i&gt;n&lt;/i&gt; + 25 for all &lt;i&gt;n&lt;/i&gt; greater than 5&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1511105172892878010-1451193887231887027?l=wollardj.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wollardj.blogspot.com/feeds/1451193887231887027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1511105172892878010&amp;postID=1451193887231887027' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/1451193887231887027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1511105172892878010/posts/default/1451193887231887027'/><link rel='alternate' type='text/html' href='http://wollardj.blogspot.com/2007/01/big-o-example.html' title='Big-O Example'/><author><name>Joe Wollard</name><uri>http://www.blogger.com/profile/08050020309888365234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
