tag:blogger.com,1999:blog-71808922009-06-22T01:05:57.033-04:00a life of codingtrust your technolustynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.comBlogger61125tag:blogger.com,1999:blog-7180892.post-87474757572035596972009-06-12T10:54:00.005-04:002009-06-12T10:59:55.083-04:00Improving Common Tag : Worse is BetterCommon Tag is an "open tagging format developed to make content more connected, discoverable and engaging" [<a href="http://commontag.org">commontag.org</a>]. It mixes RDFa into XHTML to add metadata to specify metadata for a content block, most importantly a link to a common database entry that iconifies the topic like the one word tags used in many places. This is an improvement over word tags, which can be non-descript or ambiguous: does "apple" refer a fruit, a computer company, a record label, or someone's name? Tags that are acryonyms may have no meaning to the user. RDF is commonly referred to as the Semantic Web, because it helps computers link concepts together. Everyone wants the Semantic Web, but somehow it never happens... maybe its because RDFa looks like this:<br /><pre><br />&lt;body xmlns:ctag="http://commontag.org/ns#" rel="ctag:tagged"&gt;<br /> &lt;span typeof="ctag:Tag" rel="ctag:means" <br /> resource="http://rdf.freebase.com/ns/en.u2"/&gt;<br />&lt;/body&gt;<br /></pre><br />This is a very explicit piece of data. Much of its content is XML support structure. The semantic knowledge contained in there is:<ul><li>the tag for this span is "en.u2" in freebase</li></ul><br />The structure contained in there (removing any content) is:<br /><ul><li>xmlns:ctag="http://commontag.org/ns#"</li><li>rel="ctag:tagged"</li><li>typeof="ctag:Tag"</li><li>rel="ctag:means"</li><li>resource="http://rdf..com/ns/"</li></ul><br />There are a lot of things that can break without actually removing any semantic meaning. If there were a typo anywhere in the structure above, your tag would be hopelessly borked - all that work (and bandwidth) for naught. More importantly, this format says that if I want people to understand my tags I have to embrace XML, and there are few things that I dislike as much as XML. Look at all the structure required because of XML, and the complicated tools that are required to manipulate XML!<br /><br />Lets take that content and put in something sexier: simple HTML. Over at Hacker News, <a href="http://news.ycombinator.com/item?id=653391">someone suggested</a><br /><ul><li>&lt;p ctag="wikipedia/The_Beatles"&gt;We're talking about The Beatles here&lt;/p&gt;</li></ul><br />I like this direction, but its lacking in a gruesome way: ctag is not a valid HTML attribute. Browsers may not like it, and they certainly won't be able to read it, so it isn't as clean as the RDFa. How about this:<br /><ul><li>&lt;p class="-ctag-wikipedia-The_Beatles"&gt;We're talking about The Beatles here&lt;/p&gt;</li></ul><br />This <b>is</b> valid HTML, browsers can operate on this content, and you can even style it! This is much better than the previous suggestion (which was quite good, and spurred me to write this article), but is it better than RDFa?<br /><br />Content:<br /><ul><li>the tag for this span is "The_Beatles" at Wikipedia</li></ul><br />Structure:<br /><ul><li>class="-ctag-"</li></ul><br />It is by far more concise than RDFa, but it has limitations - the tag content has to be valid inside a CSS class, which means alphanumeric, dash, and underline. There is additional flexibility if you use backslash, but this is uncommon in CSS classes and may not play nice everywhere. Most significantly, it doesn't include a link to wikipedia, only the name, and Semanic Web people really dislike that. I suspect that most people will link to Wikipedia, and if not, a search engine can figure out the most likely host. I mean, how "smart" are your tools when they can't deduce the meaning of wikipedia? If you're using an internal host or very specific database, you can always fall back to RDFa.<br /><br />Worse is better. The CSS tag format I propose is not as specific as RDFa, but it is easier to implement, harder to mess up, works with non-XHTML, and easy for humans to verify. These generally overlooked and undervalued qualities make adoption easier for people, which is in the end all that really matters.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-8747475757203559697?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-38122414545092179052009-05-04T11:53:00.003-04:002009-05-04T12:04:06.978-04:00The NYTimes Doesn't Understand Social NetworksIn <a href="http://www.nytimes.com/2009/05/03/business/03stream.html">"Tinker Away, Facebook Says"</a>, the Times summarizes Facebook's recent API expansion announcement with a comparison to a grocery store that "props open the front door and invites everyone to come in, take the merchandise free of charge, and then give it away themselves". They call this "the counterintuitive business wisdom infecting Silicon Valley these days", and proceed to imply that Facebook is doing this from the kindness of their heart.<br /><br />Let me suggest that Facebook is not a charity but a profit driven company, seeing the consumer primarily as an unavoidable obligation. An API expansion attracts additional users and (more importantly) encourages current users to not leave. A permissive developer API allows more people to participate in innovating their platform for little expense to Facebook. These companies not affiliated with Facebook take risks in developing features that users might want. If users like these features Facebook can incorporate them into the product, otherwise they will wither and die without tarnishing the Facebook brand.<br /><br />Developers see this as a way to capitalize (however meagerly) on the success of a powerful brand. Consumers see it as a new channel to cater to their needs. What would be better for both developers and consumers is a federated system with non-centralized intellectual property ownership, and thats exactly what Facebook intends to prevent. The most important thing that you should know concerning any Facebook API is that one thing remains the same: Facebook owns its customer's data, and no one, not even the customer, is allowed to export that data from them.<br /><br />To an extent, this bothers customers. Facebook recently changed their terms of service to say that Facebook owned the property rights all user entered content. Since this would have been catastrophic to artists and writers, there was a substantial backlash that resulted in Facebook rescinding this clause. They additionally apologized and claimed that this was never the intent. It seems unlikely that they would attempt to own all user content in this way, and I believe that they were honest in saying that this was a mistake. What the terms should have said is that Facebook claims ownership of the format and<br />context of data as it appears in Facebook. You own your posts, but the only way to use them outside of Facebook is to retype them by hand. You own your photographs, but maybe only if you have the originals. And under no circumstances can you export Facebook's bread and butter: the relationships that you have established.<br /><br />And so Facebook's goal is to make you just happy enough that you won't jump ship. They will claim as much ownership of content that they can for the sole purpose of making it hard to leave. They will make it difficult or impossible to remove content. They will sell as much of your identity as advertisers will buy without the government getting involved. These are what the investors of social networks talk about, and the only way that they can survive as free services.<br /><br />I am sad to see the Times miss what is blatantly obvious to me. Is it not the age old motto of investigative journalism to follow the money? It may be that our journalists have lost their curiosity. Or possibly that people have generally become consumers, and consumers see themselves not as powerful individuals but as reflected in their relationship to companies. With Social Networks, the money is in owning customer data as much as possible, and selling that data (via keyword advertising, or outright) to advertisers.<br /><br />If I impress anything on you, let it be that Facebook needs you more than you need Facebook. They need you to buy products so that they can sell advertising, because Facebook is not really a free service. Years from now, the person who owns your past (photographs, notes, messages with friends) will be the one paying for it now, and if you are a Facebook user, that person is not you. The best thing that you can do for your future self is to get involved and start owning your present identity. Data in a product like Wordpress, Blogger (but not Blogspot), or simple HTML on a web server has been paid in full. There is no question about who owns the rights to your past, or what you are allowed to do with it - it is simply yours. Certainly, Facebook has extra features that you cannot get from these truly free products, but comparable features won't exist in other products (free or consumer paid) until there is a demand for them.<br /><br />So get out there and encourage people to think about the past of the future, which might be tomorrow. Maybe even use Facebook to spread the word - but don't be surprised if they shut you down. After all, they are the ones footing the bill.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-3812241454509217905?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-40629157503663629932009-01-07T13:47:00.002-05:002009-01-07T13:52:57.074-05:00Firefox: An Acceptable Cross Platform GUI ToolkitA recent <a href="http://news.ycombinator.com/item?id=423119">Hacker News submission</a> asked what an "acceptable" cross-platform GUI toolkit would be. It discusses common complaints about the existing toolkits GTK+, Qt, Tk, and wxWidgets. It suggests creating a new toolkit with the qualities of being written in C, keeping it simple, LGPL licensing, easily skinnable for different OS's, binding for scripting languages, and be "simple and easy to use".<br /><br />Good news! I know of an existing GUI toolkit that fits this bill. Its written and extensible in C/C++, has liberal licensing, is very skinnable, has bindings for JavaScript, Python, Java, Perl, and Ruby, and lots of existing open source code that you can learn from. It even has a large, mixed platform install base, so you know that the bugs are minimal. Its based on an object brokering system called XPCOM, and an application framework called Mozilla, but often goes by the name Firefox. Given the popularity of web applications in the startup community, Firefox seems like an obvious option for desktop apps. Yet it hasn't caught on, and I'm not sure why. <br /><br />I recently worked on a desktop application for my day job. Given their limited interface goals and a game-oriented 3d engine, they had decided to write the interface directly in OpenGL. It was difficult to design interfaces like that, so I did a prototype integration with wxPython. That worked well enough to start real product development, during which I realized that wxPython had many of the "cross-platform toolkit" woes like needless internal complexity, difficulty in writing new components, and general ugliness.<br /><br />I spent some time contemplating how people wrote successful cross platform desktop applications, and the two things that struck me were (a) there aren't many, (b) except Firefox, (c) and this might underly the popularity of web applications. So I did a new prototype using Firefox with a XUL user interface. What I found was that Firefox worked out great as a standalone application with modular code design, but it was difficult to write good interfaces in XUL. XUL seems to be well tested only as far as the functionality in Firefox is concerned. We switched to Ext-JS, started pretending to be web app devs, and got down to implementing features.<br /><br />Writing a desktop app based on XULRunner has some interesting side-effects. For one, it makes retargeting your code as a web application or Firefox plugin really easy. It also lets you develop using a variety of hacker friendly languages. Like programming in lisp, it changes your perspective on how applications should be developed, and makes questions like "which UI toolkit is the best?" seem fundamentally flawed. In an age when Apple is rewriting their apps to run in a browser (and still look and feel like desktop apps), isn't writing a code against a desktop UI toolkit fighting the tide?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-4062915750366362993?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com12tag:blogger.com,1999:blog-7180892.post-15482019646489522142008-12-10T13:48:00.007-05:002008-12-10T16:35:56.677-05:00JavaScript Performance<p>There are a lot of JavaScript performance benchmarks flying around out there. Some claim that Chrome shames the competition, others say that Firefox 3.1 is neck and neck with Chrome, others crown WebKit as the fastest of them all.</p><p>But what they never seem to do is compare them against other languages. One website, the <a href="http://shootout.alioth.debian.org">Computer Language Shootout</a> does, but it never seems to rate JavaScript particularly well. There are a few reasons for this. JavaScript has gotten a lot of attention recently and has thus been rapidly improving, and the CLS doesn't update very often. Tests are also written by different people, and folks who write JavaScript have never been the performance oriented crowd. Finally, the command line harness they use to execute JavaScript isn't representative of how users execute JavaScript.</p><p>So, what happens if we try to mitigate some of these? I picked a single test, rewrote it to run as a web page, and ran it using the latest version of browsers that can be considered stable. The results might surprise you.</p><br /><b>n = 10</b><table><tr><td>gcc</td><td>0.5s</td><td>1.0x</td></tr><tr><td>java6</td><td>0.7s</td><td>1.4x</td></tr><tr><td>java5</td><td>1.1s</td><td>2.2x</td></tr><tr><td>webkit</td><td>1.8s</td><td>3.6x</td></tr><tr><td>jsc</td><td>4.7s</td><td>9.4x</td></tr><tr><td>minefield</td><td>6.4s</td><td>12.8x</td></tr><tr><td>firefox</td><td>19.4s</td><td>38.8x</td></tr><tr><td>rhino</td><td>22.1s</td><td>44.2x</td></tr><tr><td>python</td><td>33.1s</td><td>66.2x</td></tr><tr><td>rhino</td><td>47.8s</td><td>95.6x</td></tr><br /><tr><td>ruby</td><td>58.3s</td><td>116.6x</td></tr><tr><td>webkit [parallels/xp]</td><td>1.0s</td><td></td></tr><tr><td>chrome [parallels/xp]</td><td>2.0s</td><td></td></tr></table><br /><b>n = 11</b><table><tr><td>gcc</td><td>5.1s</td><td>1.0x</td></tr><tr><td>java6</td><td>6.5s</td><td>1.3x</td></tr><tr><td>java5</td><td>12.6s</td><td>2.5x</td></tr><tr><td>webkit</td><td>23.4s</td><td>4.6x</td></tr><br /><tr><td>jsc</td><td>57.5s</td><td>11.3x</td></tr><tr><td>minefield</td><td>81.2s</td><td>15.9x</td></tr><tr><td>webkit[parallels/xp]</td><td>15.0s</td><td></td></tr><tr><td>chrome[parallels/xp]</td><td>29.0s</td><td></td></tr></table><br />Timings done on a Mac Book Pro 2.4 Gz Core 2 Duo / 4 GB RAM. Parallels/XP means running on Windows XP SP3 inside Parallels on the same computer.<br />WebKit is nightly build 39090.<br />WebKit [parallels/xp] is nightly build 39088.<br />jsc is built from svn rev 39090.<br />python is 2.5.1.<br />ruby is 1.8.6.<br /><br />So, interesting things:<ol><br /><li>The fastest JavaScript implementations are close to the speed of Java.</li><br /><li>The coming JavaScript implementations are substantially faster than Python or Ruby.</li><br /><li>WebKit is about twice as fast as jsc (the command line interpreter), so the Computer Language Shootout numbers will be inflated.</li><br /><li>Java 6 is substantially faster than Java 5.</li></ol><br />So, I expect to see more web services written in JavaScript. Why? The argument for Python or Ruby has been that they are much more productive than Java/C/C++/C# that the performance of these languages isn't important. I certainly agree with this. However, JavaScript has about the same level of language productivity, and now has an implementation thats 18 times as fast as python and 32 times as fast as ruby. And you can use the same language across the board for web apps.<br /><br />I also expect to start seeing desktop apps written in JavaScript. Why use a hacky python or ruby desktop app wrapper when you could use the best cross platform GUI kit there is? And, why bother with a local rails or django instance when you could do everything in a full MVC AJAX kit like <a href="http://www.sproutcore.com/">Sproutcore</a> or <a href="http://cappuccino.org/">Objective-J</a>?<br /><br />At the risk of giving away the secrets to my sauce, desktop JavaScript is going to change everything. There are already a couple of frameworks out there (<a href="http://www.aptana.com/jaxer">Jaxer</a>, <a href="http://titaniumapp.com/">Titanium</a>), but I think that there will be many more to come.<br /><br />(PS: Lisp FTW!)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-1548201964648952214?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com2tag:blogger.com,1999:blog-7180892.post-52956090313333917802008-08-04T16:01:00.005-04:002008-08-20T10:14:50.193-04:00Java Static Class Object Fields and Weak ReferencesIn browsing the Mozilla Rhino code, I stumbled upon a garbage collection problem that is truly bizarre. Rhino uses thread local storage for the current Context object. TLS uses a weak dictionary, so it is important that there is no strong circular reference to the key. Years ago (CVS r 1.234), the rhino class Context used to have a static reference to the thread local storage object. This was a problem because even when an array is empty, it has a reference to the class of objects it can hold. Thus, the TLS key (the ThreadLocal object itself) is referenced by the Context class, which is referenced by the (empty) Context[].class, which is a value in the TLS map! This circular dependency caused rhino to leak memory whenever a thread that used JavaScript completed. The solution to this was to change the value to an Object[]. When there are Context objects in the array, the reference still exists, however once the array is empty, there is no longer a reference and the TLS weakref dictionary will cut that key/value pair loose.<br /><br />The <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=281067#c5">comment</a>, <a href="http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/js/rhino/src/org/mozilla/javascript/Context.java&rev=1.234&root=/cvsroot">original</a>, and <a href="http://bonsai.mozilla.org/cvsview2.cgi?diff_mode=context&whitespace_mode=show&file=Context.java&branch=&root=/cvsroot&subdir=mozilla/js/rhino/src/org/mozilla/javascript&command=DIFF_FRAMESET&rev1=1.234&rev2=1.235">fix</a>.<br /><br />Wow, thats a lot of detail. Here's the summary: if you have static class fields, make sure they don't eventually point to the key of a weak dictionary. If find this unavoidable, you can break the loop by storing a value as an Object and casting any usage of it. You will still have to set this variable to null in order for GC to happen.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-5295609031333391780?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-38101136753753500452008-06-17T16:00:00.003-04:002008-06-17T16:08:53.440-04:00Firefox 3 is the Ugliest Browser YetIt's a bit trite for a blog post, but seriously, Firefox 2 looked way better than 3 on Windows. If you customize the toolbar (via right click) to use "small icons", its marginally better, but people actually spent time working on the design of this UI, so I shouldn't have to fix it for them. Everyone would have been much better off with the third party Firefox 1.x theme <a href="http://members.shaw.ca/lucx/">Charamel</a>. <br /><br />I haven't used the Mac version yet, but it appears to have the same heinous icon problems. Look at Safari and try again please.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-3810113675375350045?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com4tag:blogger.com,1999:blog-7180892.post-50425369198446919762008-05-29T17:39:00.003-04:002008-05-29T17:43:38.057-04:00XPCOM nsISupports Proxy Crashes<p>In building an application based on XULRunner, we've uncovered a number of bugs in the Mozilla codebase. One that really bothers me is the implementation of asynchronous object proxies. First, here's a brief overview of nsISupports proxies.</p><h3>XPCOM</h3><p>XPCOM is a generalized system for calling methods on objects. These objects can be implemented in C++, JavaScript, or Python (using a 3rd party library called PyXPCOM). XPCOM is the mechanism for defining Firefox extensions and writing applications that use XULRunner.</p><h3>Working With Threads</h3><p>One handy feature of XPCOM is the ability to have your method call execute in another thread. One example of this is a background thread that wants to do something to the UI, such as update a progress bar. Similarly to Java, Cocoa, and some Windows programming, UI access in Mozilla has to happen on the main thread. Another common situation is sending commands to a worker thread from the main thread. In both cases, we have a simple command to issue, but a direct method call is the wrong way to accomplish this.</p><p>So XPCOM has a mechanism for defining proxy objects that look identical to the original object, but executes your request in another thread. There are two flavors of this, synchronous (PROXY_SYNC) which will block your thread, and asynchronous (PROXY_ASYNC) which queues a request in the other thread and continues on. One implication of asynchronous dispatch is that there will be no return value, since you don't wait for the method to finish.</p><h3>The Async Warning</h3><p>The page <a href="http://developer.mozilla.org/en/docs/nsISupports_proxies">describing proxies</a> contains a very specific warning: if you pass variables by reference and those variables are on the stack, bad things will happen. It turns out that this is a bit understated, and doesn't convey some of the subtleties, so I will try to clarify.</p><h3>Asynchronous XPCOM Proxies Are Fundamentally Broken</h3><p>Using them will likely cause you nothing but pain. This pain will be in the form of totally random crashes, with meaningless (but seemingly useful) stack traces. You will ask people for help, and they will have no idea where to start. Unless you are intimately familiar with the XPCOM message dispatch and QueryInterface source code, PROXY_ASYNC should be a keyword which in your mind expands to Bad Bad Evil Crashing.</p><p>Why? Well, it turns out that return values are implemented as "out" parameters, which is a fancy way of saying references on the stack, which you may have recently learned is something that you should never mix with PROXY_ASYNC. So, if you were to call any method on an asynchronous proxy that <b>could</b> return a value, it will corrupt memory. There's actually no uncertainty here, XPCOM will write over some random memory address which is probably on some poor thread's stack.</p><h3>The Workaround</h3><p>"Ah!" you say, I can use PROXY_ASYNC and still sleep at night as long as I only call methods that return "void". Well, you might sleep a night or two, but soon you'll realize that bad things are still happening. The reality is, there is no workaround (sorry!). Even if you avoid methods with "out" or "in out" parameters, and ones that return values, Mozilla will still punish you by calling exactly these sorts of methods internally. If you're using a scripting language (generally JavaScript), things are even worse for you, because it makes a bunch more of these calls to set up your script object.</p><h3>The Documentation</h3><p>This bug is currently documented in <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=382631">buzilla</a>. Unfortunately, there seems to be no workable solution to the situation. On top of that, the people responsible for the code base don't know why anyone would even want to use asynchronous dispatch. So, that doesn't sound good. The only real fix is to find a way to remove any mention of PROXY_ASYNC from your code. Depending on your application, this may be an easy fix. So far for us, this has not been the case. (Mozilla was never intended to do what we're doing)</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-5042536919844691976?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-34722179585980733802008-01-04T12:44:00.000-05:002008-01-04T12:45:11.363-05:00FYI: JavaScript is LispJust a heads up in case anyone hasn't figured this out yet.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-3472217958598073380?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com2tag:blogger.com,1999:blog-7180892.post-23809360972004818482007-11-17T17:05:00.000-05:002007-11-17T18:15:57.131-05:00Some Things Never ChangeI just finished watching a <a href="http://video.google.com/videoplay?docid=8612534856516244040">half hour video on computer graphics</a>. It covers the basics of 2D and 3D graphics and basic animation in a way that the average person can understand, but with enough detail to provide basic understanding.<br /><br />The information itself isn't particularly blog-worthy; there are plenty of resources for learning about computer graphics. There are two reasons that this is interesting to me. First, television seems to have a dwindling amount of educational content. I remember watching <a href="http://en.wikipedia.org/wiki/3-2-1_Contact">3-2-1 Contact</a>, <a href="http://en.wikipedia.org/wiki/Mr_wizard">Mr. Wizard</a>, and <a href="http://en.wikipedia.org/wiki/NOVA">NOVA</a> as a kid. The programs <a href="http://en.wikipedia.org/wiki/List_of_programs_broadcast_by_Public_Broadcasting_Service#PBS_Kids">currently on PBS</a> don't seem to show the same interest in science, substituting fantasy, social interaction, and ironically, reading. This may be related to my perception that they are also oriented to a younger audience, but I can't help but feel that kids should be learning these things <i>instead</i> of watching TV, not <i>by</i> watching it.<br /><br />Second, this video is from a program called <a href="http://en.wikipedia.org/wiki/Sol_Garfunkel">For All Practical Purposes</a> and was filmed in the late '80s. The computer systems used are from <a href="http://en.wikipedia.org/wiki/Symbolics">Symbolics</a>, a company that made their own hardware and operating system written entirely in lisp. This idea is similar to the current <a href="http://en.wikipedia.org/wiki/Squeak">Squeak</a> project, which is written in smalltalk instead of lisp. The video is old, the computers are old, the technology is old, and yet, it isn't particularly different from the basic concepts that I learned at Georgia Tech a few years ago. The biggest changes have been in the hardware that allows us to animate using physical simulation, and have realtime rendering.<br /><br />Modern computing doesn't seem that different from 80's computing, except that everything is <a href="http://en.wikipedia.org/wiki/Image:Moore_Law_diagram_%282004%29.png">faster</a>, <a href="http://en.wikipedia.org/wiki/Image:Hard_drive_capacity_over_time.png">larger</a>, <a href="http://en.wikipedia.org/wiki/Wirth%27s_Law">less efficient</a>, <a href="http://en.wikipedia.org/wiki/Mac_OSX">prettier</a>, <a href="http://en.wikipedia.org/wiki/Broadband_access">more connected</a>, and cheaper (much, MUCH <a href="http://en.wikipedia.org/wiki/Macintosh_II">cheaper</a>). Just today I learned of a London startup that is writing games that would have run on a 1.2 MHZ <a href="http://en.wikipedia.org/wiki/Atari_2600">Atari 2600</a> in Macromedia Flash - which uses most of my 1,200 MHZ CPU. But ultimately, its all the same. In my eyes, this makes a stronger case for the idea of Computer Science, because if you ever really learned how computers work, you might understand them forever.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-2380936097200481848?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-2816094522561178182007-11-16T15:40:00.000-05:002007-11-17T18:32:13.808-05:00parent and __parent__ and __proto__, Oh My!Sometimes Javascript development can be rather scary. Unlike C or Java, which have well known standards, Javascript (like HTML) is often described by what works on one or more of the current implementations. On top of that, few people see Javascript as a legitimate language, and a vast number of novices are out there writing code that would make your skin crawl. <br /><br />In short, if you are a knowledgeable programmer, quickly picking up Javascript is much harder than it should be. The syntax is C-like (generally regarded as a plus), the functions are first class (almost universally positive), and the object system is prototype based (at least smalltalk people like this). Soon there will be a common <a href="http://www.mozilla.org/projects/tamarin/">just-in-time compiler</a>, and some people have suggested that it might <a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html">displace currently popular languages</a>. Personally, I wish that it ditched the prototype object system for a Python-like one, and had lisp-like macros, and just-in-time compilation can't come soon enough.<br /><br />When a question about a Javascript feature like "x.__proto__" arises, it can be difficult to answer. In my experience so far, the best places to look are <a href="http://developer.mozilla.org/en/docs/JavaScript">MDC</a> and the IRC channel listed on the page.<br /><br /><span style="font-weight:bold;">What is __proto__?</span><br /><br />When you make a Javascript "class" (ie constructing function), you can specify a prototype:<pre>function Example() {<br /> this.foo = 1;<br />}<br /><br />Example.prototype = {<br /> sample : function memberFunction() {},<br />}</pre>This attribute is copied onto constructed objects as <code>__proto__</code>, like so:<br /><pre>ex = new Example();<br />if (ex.__proto__ == Example.prototype) print("same!");</pre><code>__proto__</code> is a special attribute that is searched if an attribute is not found on the object, it is analogous to a parent class.<br /><br /><code>parent</code> and <code>__parent__</code> are substantially different. <code>parent</code> comes from the DOM, and is the tag that encloses the current tag. <code>__parent__</code> is a special variable that is a reference to the scope that created the object. Like <code>__proto__</code> is checked when a variable lookup fails. Where <code>__proto__</code> is checked when the failure looks like <code>this.missing_attribute</code>, <code>__parent__</code> is checked when the failure is in the form <code>missing_global</code>. According to <a href="http://www.mozilla.org/rhino/overview.html">Mozilla</a>, <code>__parent__</code> and <code>__proto__</code> have been deprecated, which is unfortunate since they can be quite useful.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-281609452256117818?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com3tag:blogger.com,1999:blog-7180892.post-1605405855890674852007-11-05T23:41:00.000-05:002007-11-06T17:08:23.881-05:00Debugging PythonAbove all else, my greatest annoyance with python is the lack of good documentation and defaults. I bet that there is a group somewhere that knows everything there is to know about python... I beg of them, write that knowledge down!<br /><br />Here's an example. I want to debug a faulty program:<br /><pre>x = [1,2,3]<br /><br />def foo():<br />sum = 0<br />for i in range(4):<br /> sum += x[i]<br /><br />import pdb<br />pdb.run("foo()")<br /></pre>I'm then prompted by pdb: (> replaced with ])<br /><pre>] [string](1)?()<br />(Pdb)<br /></pre>Good, now I'm in the debugger. To get things started, I type "c", return, and get:<br /><pre>Traceback (most recent call last):<br />File "[stdin]", line 1, in ?<br />File "c:\Python24\lib\pdb.py", line 996, in run<br />Pdb().run(statement, globals, locals)<br />File "c:\Python24\lib\bdb.py", line 366, in run<br />exec cmd in globals, locals<br />File "[string]", line 1, in ?<br />File "[stdin]", line 4, in foo<br />IndexError: list index out of range<br />]]]<br /></pre>You should notice that the last line is the standard python prompt (with the aforementioned character replacement to make blogger behave), not the debugger. I have finished my debugging session due to an error. Gee, it sure would have been nice to debug that, since my state is now lost! I was already using the debugger to run this code, why did it not catch this exception?<br /><br />It turns out that exception handling is done by sys.excepthook, and pdb.run doesn't set the excepthook. Some searching turned up two options. The first is simple but crude - add the following to site-packages/sitecustomize.py:<br /><br /><a href="http://mail.python.org/pipermail/python-list/2001-April/079168.html">Thomas Heller</a><br /><pre>import pdb, sys, traceback<br />def info(type, value, tb):<br /> traceback.print_exception(type, value, tb)<br /> pdb.pm()<br />sys.excepthook = info</pre>The second is more sophisticated, and checks for interactive mode:<br /><br /><a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65287">ActiveState Python Cookbook</a>.<br /><pre># code snippet, to be included in 'sitecustomize.py'<br />import sys<br /><br />def info(type, value, tb):<br /> if hasattr(sys, 'ps1') or not sys.stderr.isatty():<br /> # we are in interactive mode or we don't have a tty-like<br /> # device, so we call the default hook<br /> sys.__excepthook__(type, value, tb)<br /> else:<br /> import traceback, pdb<br /> # we are NOT in interactive mode, print the exception...<br /> traceback.print_exception(type, value, tb)<br /> print<br /> # ...then start the debugger in post-mortem mode.<br /> pdb.pm()<br /><br />sys.excepthook = info</pre>Here's what I'm currently running:<br /><pre># code snippet, to be included in 'sitecustomize.py'<br />import sys<br /><br />def info(type, value, tb):<br /> if (#hasattr(sys, "ps1") or<br /> not sys.stderr.isatty() or <br /> not sys.stdin.isatty()):<br /> # stdin or stderr is redirected, just do the normal thing<br /> original_hook(type, value, tb)<br /> else:<br /> # a terminal is attached and stderr is not redirected, debug <br /> import traceback, pdb<br /> traceback.print_exception(type, value, tb)<br /> print<br /> pdb.pm()<br /> #traceback.print_stack()<br /><br />original_hook = sys.excepthook<br />if sys.excepthook == sys.__excepthook__:<br /> # if someone already patched excepthook, let them win<br /> sys.excepthook = info</pre>The original ActiveState script doesn't debug if you are running in interactive mode. To me, this makes no sense at all - thats a case where I specifically want to debug. <br /><br />Alas, if the debugger shows an obvious error that could be fixed, python exceptions cannot be resumed. The code listed here will let you see the stack and move around in it, but your program is no longer running and can never finish where it left off. Allowing this requires call/cc, and as far as I can tell there is no plan to ever support that in python.<br /><br />If this was helpful, or should be changed, let me know. I've just started using it myself.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-160540585589067485?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com3tag:blogger.com,1999:blog-7180892.post-86888950726524618112007-08-12T09:37:00.001-04:002009-05-19T12:06:34.527-04:00Closures in PythonA closure is data attached to code (pretty simple, eh?). I use them for:<br /><ul><li>Replacing hard coded constants</li><li>Eleminating globals</li><li>Providing consistent function signatures</li><li>Implementing Object Orientation</li></ul>(Isn't it funny that people rarely tell you what closures are good for?)<br />Here is a closure in python:<br /><pre>def makeInc(x):<br /> def inc(y):<br /> # x is "closed" in the definition of inc<br /> return y + x<br /><br /> return inc<br /><br />inc5 = makeInc(5)<br />inc10 = makeInc(10)<br /><br />inc5 (5) # returns 10<br />inc10(5) # returns 15</pre>Closures in python are created by function calls. Here, the call to makeInc creates a binding for <b>x</b> that is referenced inside the function inc. Each call to makeInc creates a new instance of this function, but each instance has a link to a different binding of <b>x</b>. The example shows the closure of <b>x</b> being used to eliminate either a global or a constant, depending on the nature of <b>x</b>.<br /><pre>import time<br />keepRunning = True<br />updates = []<br />def runLoop():<br /> while (keepRunning):<br /> for u in updates:<br /> u()<br /><br />class foo:<br /> def __init__(self, x = 0):<br /> self.x = x<br /><br /> def update(self):<br /> print self.x<br /> self.x += 1<br /><br />f = foo()<br />g = foo(2)<br /><br />updates.extend([f.update, g.update])</pre>In python, all methods (but not functions) are closures ... sort of. The method definition <b>foo.update</b> closes the class foo. The value of <b>g.update</b> is a closure that stores the value of <b>g</b> and passes that as the first argument of <b>foo.self</b>, hence the first argument of a method in python is <i>self</i>. Details aside, it is important to note that the designers of python have gone out of their way so that you can pass <b>g.update</b> by itself to another function and have it continue to work correctly.<br /><br /><span style="font-size:140%;">Caveats</span><br /><br />In some languages, the variable bindings contained in a closure behave just like any other variables. Alas, in python they are read-only. This is similar to Java, and has the same solution: closing container objects. Closure of a dictionary or array won't let you assign a new dictionary or array, but will let you change the contents of the container. This is a common use pattern - every time you set a variable on <i>self</i>, you are changing the contents of a closed dictionary.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-8688895072652461811?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com3tag:blogger.com,1999:blog-7180892.post-12823269420445805042007-08-03T01:39:00.000-04:002007-08-03T01:40:21.705-04:00A Visualization of VisualizationsYou really need to see this one first hand, so <a href="http://www.smashingmagazine.com/2007/08/02/data-visualization-modern-approaches/">check it out</a>.<div><br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-1282326942044580504?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com3tag:blogger.com,1999:blog-7180892.post-6248067908338626362007-07-06T19:13:00.000-04:002007-07-06T21:38:30.642-04:00Working with Python/C<p>Some very short notes for working with python from C. I'm using Python 2.4.x, YMMV.</p><p><br />Getting the current error state inside your debugger:<br /></p><pre>_PyThreadState_Current->curexc_type</pre><p></p><p><br />Instantiating a "New Style" class (a subclass of "object"):</p><pre>PyObject* args = PyTuple_New(0);<br />PyObject* dict = PyDict_New();<br /><br />// works only with new style classes (subclasses of "object")<br />PyObject* result = PyObject_Call(classObject, args, dict);</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-624806790833862636?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-34785213457970108582007-06-15T12:54:00.000-04:002007-06-15T13:17:39.383-04:00Open Network Sockets on Mac OS X<p>This is one of those things that constantly annoys me. On Linux, <code>netstat</code> tells me the list of currently active network connections, including (often most importantly) listening connections. Just knowing that something is running on port 8080 tips me off that I probably have an Apache or Java EJB process running (or maybe a <a href="http://wiki.squeak.org/swiki/">swiki</a>) - a trip to localhost:8080 will answer my question. But what if this port isn't an HTTP server, and doesn't speak when connected to? Now you have a dilemma - there's no way of knowing what has this port open.<br /></p><p>Fortunately this is a solved problem on Linux. <code>netstat</code> has some options that tell you the PID of the process with the port open. From here you can use <code>ps</code> to find the name of the process, its path, the user who started it, etc. BTW, you need to run netstat as root to see other people's PID's and those of services.<br /></p><p>Well, you know what comes next - <code>netstat</code> on the Mac doesn't show PID's! WTF! Speaking of commands that Mac OS X doesn't have, <code>fuser</code> is missing as well. <code>fuser</code> on Linux tells you which processes have a specific file open - very useful if you're cleaning up files and one has is locked. Well, Mac OS X (BSD really) doesn't have <code>fuser</code>... but it does have a command called <code>lsof</code>. <code>lsof</code> isn't quite as user friendly as <code>fuser</code>. It only has one mode, which is to list every open file that is visible to you (this is a subtle hint that you should run it as root to see more files). This means that <code>fuser &lt;filename&gt;</code> roughly translates to <code>lsof | grep &lt;filename&gt;</code>. Very useful for finding that stray service that has outlived its welcome and is holding files hostage.</p><p>Still, the problem at hand is finding the PID of network sockets. It turns out that in POSIX, network sockets are pretty much the same as files. This means that they show up in <code>lsof</code> if you ask nicely. And since <code>lsof</code> shows PID's (it even gets fancy and shows the process name), it turns out to be the solution. So, here's the money shot:</p><p><code>sudo lsof -i -P</code></p><p>This produces something that looks like:</p><pre><br />COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME<br />launchd 1 root 9u IPv4 0x01d96e10 0t0 UDP *:137<br />launchd 1 root 10u IPv4 0x020dbe8c 0t0 TCP *:139 (LISTEN)<br />launchd 1 root 11u IPv4 0x020dbb38 0t0 TCP *:445 (LISTEN)<br />launchd 1 root 12u IPv6 0x01d99c50 0t0 TCP *:22 (LISTEN)<br />launchd 1 root 13u IPv4 0x020db7e4 0t0 TCP *:22 (LISTEN)<br />mDNSRespo 43 root 7u IPv4 0x01d96ad0 0t0 UDP *:5353<br />mDNSRespo 43 root 8u IPv6 0x01d96a00 0t0 UDP *:5353<br />mDNSRespo 43 root 9u IPv4 0x03379d40 0t0 UDP *:5353<br />mDNSRespo 43 root 13u IPv4 0x03379860 0t0 UDP 192.168.1.100:53891<br />mDNSRespo 43 root 14u IPv4 0x032f82a4 0t0 TCP *:* (CLOSED)<br />mDNSRespo 43 root 15u IPv4 0x02edb554 0t0 TCP 192.168.1.100:5000 (LISTEN)<br />mDNSRespo 43 root 16u IPv4 0x020da098 0t0 TCP *:* (CLOSED)<br /><br />... (lots more here)<br /></pre><p>If you don't have root access, you can still use <code>lsof</code>, but you won't see the plethora of system services and other users processes.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-3478521345797010858?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com5tag:blogger.com,1999:blog-7180892.post-1163742265026572662007-05-29T12:43:00.000-04:002007-05-29T14:42:51.762-04:00Python Techniques You've Been Googling ForI've been doing it, I bet you have too. Here's some topics that have come up lately, I'll be writing about each of them in time. Since you probably got here via Google, add a comment for the subject that got you here.<br /><br />Closures<br />Debugging<br />Creating functions<br />Metaclasses<br />Performance Optimization<br />Objects in depth<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-116374226502657266?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-52408948715265290622007-03-17T13:45:00.001-04:002007-03-17T13:45:16.776-04:00asdf-install on openMCLA Note: This has been sitting in my drafts folder for 10 months. I&#39;m<br>posting it unedited because its better out then in, right?<p>---<p>This should be pretty trivial... after all, its included with the<br>latest openMCL, right? (I&#39;m using the latest CVS)<p>Well, I&#39;ve been fighting to get it working for almost a week, most<br>likely because I tend to ignore files named README. Having some<br>experience with CPAN and rubygems, it should really be possible to get<br>packages from a package repository without even knowing the language<br>that you are using. Why? Because newbies want to see results before<br>they have to invest time in learning new things. In the worst case,<br>an end user doesn&#39;t know, or even want to know, how to program at all.<br> Package repositories should really just work.<p>Here are my notes so far:<p>You need to compile asdf-install. To do so, you should be in the<br>directory containing asdf-install.asd . Then run:<br>(asdf:operate &#39;asdf:compile-op :asdf-install)<br>(asdf:operate &#39;asdf:load-op :asdf-install)<br>Now, make your asdf registry:<p>mkdir /usr/local/share/ccl/asdf-registry<br>cp asdf-<p>You need to create ~/openmcl-init.lisp with:<br> (require &#39;asdf)<br>(setf asdf:*central-registry*<br> &#39;(*default-pathname-defaults*<br> #p&quot;/usr/local/asdf-install/site-systems/&quot; ; where<br>asdf-install puts things<br> #p&quot;/usr/local/share/ccl/asdf-registry/&quot; ; where i put<br>asdf-install.asd<br> ))<br>(asdf:operate &#39;asdf:load-op :asdf-install)<p>;;; its really best to install GPG<br>(setf asdf-install:*VERIFY-GPG-SIGNATURES* nil)<p>The central registry setup is important - maybe<br>asdf-install/site-systems should be the same folder as the asdf<br>registry... I dunno. What I do know is that they both need to be in<br>the asdf search path (ie asdf:*central-registry*) or you won&#39;t get<br>very far.<p>I hope that I&#39;m misguided, this is all a bad dream, and if I only<br>followed some magic instructions, this would be trivial. For now,<br>this works for me, and thats all that really matters.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-5240894871526529062?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-1165200351844756592006-12-03T21:37:00.000-05:002006-12-03T22:40:53.800-05:00Old And In The Way (stale fasl's)SBCL 1.0 has been released, and as expected, it breaks some things on my Powerbook. One specific problem is stale "fasl" files. Honestly, I don't even know what they are... I suspect them to be some kind of optimized bytecode used by ASDF to improve loading speed, but really (as long as they work) I don't care what they are.<br /><p>SBCL will stutter something like this:<br /><code><br />debugger invoked on a SB-FASL::INVALID-FASL-VERSION:<br /> #&lt;SB-SYS:FD-STREAM for "file /usr/local/lib/sbcl/site/rt-20040621/rt.fasl" {11A024F9}&gt;<br /> is in native code fasl file format version 70, but this version of SBCL uses<br /> format version 71.<br /></code><br />Searching cliki revealed that these are <a href="http://www.cliki.net/asdf">intermediate files</a> that can simply be deleted. They suggest that deleting files by hand is tedious and have a nice code snippit that should make things magically refresh in the future... I'm a little more pragmatic:<br /><code><br />find /usr/local/lib/sbcl -name '*.fasl' -exec rm {} \;<br /></code><br />Works fine afterwards.<br /><br /><b>Update:</b> I was a little quick to declare victory. After executing this, i was unable to (require 'asdf), since the fasl for asdf had been deleted. I reinstalled (executed sbcl-1.0/install.sh) and the problem is fixed. This seems to invalidate my previous suggestion... Maybe I should have filtered the search to only include files older than a certain date. The cliki code snippit is probably the better way to go for now.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-116520035184475659?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-1164179956791946432006-11-21T23:13:00.000-05:002006-11-22T02:19:35.150-05:00Python Developers Wanted: Dead or Alive<p><a href="http://www.churchillnavigation.com"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px;" src="http://ynniv.com/blog/earthscape_sample.jpg" border="0" alt="" /></a> I've been working at a new gig in Boulder, Colorado. We're writing an earth rendering engine, a la Google Earth. Why bother? Unlike the competition, we're going to be putting lots of our imagery on hard drives so that you can take it off the net: in your car, on a plane, in your backpack. You can sync changes when you get home, or use a cellular connection for low bandwidth data like local searching and geolocating your friends. If you've wanted it, hopefully we're on it (but feel free to <a href="mailto:ynniv-cn@ynniv.com">send suggestions</a> or leave comments).<br /></p><p>I think 3d earth rendering is going to be big (maybe I've just read <a href="http://en.wikipedia.org/wiki/Snow_Crash">Snow Crash</a> too many times), and recent announcements by <a href="http://www.pcworld.com/article/id,127770-page,1/article.html">Microsoft</a> seem to confirm my suspicion. This blog doesn't get many comments, but usage statistics betray the silent masses who frequent it looking for KML tools. Are you tired of writing web services and pounding KML into new Google Earth features? Does writing a car navigation system 12 hours a day in python using a real 3d world API (we won't poke <a href="http://earth.google.com/comapi/">too much fun</a>) sounds like your cup of tea? Maybe you're tired of Carmack taking credit for your OpenGL code. I heard somewhere that start-ups aren't en vogue anymore, but I know there's other people out there who regret missing the bubble. If you're confident in your abilities and can write the code to prove it, we're looking for you.<br /></p><p>It would be nice if you lived in the US and wanted to move to Colorado (its <a href="http://www.cdc.noaa.gov/Boulder/">sunny and warm</a> even when the slopes are open and there's plenty of outdoors to go around. <a href="mailto:jobs@churchillnavigation.com">Send us an email</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-116417995679194643?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com4tag:blogger.com,1999:blog-7180892.post-1163927032167326702006-11-19T10:11:00.000-05:002006-11-19T04:03:52.530-05:00How Python is Killing LispThese are tumultuous times for lisp. Once the bastion of language academics and hackers and shunned by those of industry, it's received much lip service from successful dot commers, most notably Paul Graham. Lisp has been around a long, long time (its the second oldest language still in use, behind fortran), and its gotten very mature in that time. Industry languages continue to steal features from lisp, and some modern languages like python and ruby are more lisp than C. Still, lisp does not have the popularity one might expect. What is it that's holding it back while python prospers?<br /><br />Lets start with what it gets right. It is said that lisp is very expressive, allowing extremely complicated ideas to be expressed succinctly (and hopefully quickly) by those fluent in the language. That's a rather heady idea, especially considering it is being applied to a practical industry. What this means in practice is that a great programmer is less limited by lisp than C++ or Java. This is really important because there are no natural limits on the productivity of a programmer. Unlike artisans and construction workers, there are no physical processes that limit how fast he can accomplish a task. The best person of another trade might be hundreds of times better than the novice, but they are limited by nature. Take away that limitation, and a handful of the best people could accomplish amazing things. <br /><br />What makes lisp expressive aren't complex features like Object Orientation, but powerful simple ones like closures. The simplicity of these features let you build new complex ones as times change. Aspect Oriented Programming was part of the original Object Oriented lisp system based on closures. Continuations are a great way to deal with the non-linear flow of web applications.<br /><br />Many of these powerful features have been adopted by new languages: Python can generate closures and has list comprehensions. Still, they don't contain all of lisp's power, and yet a search for open-source lisp applications on sourceforge returns 345 results to python's 6,571. Where are the hordes of elite programmers looking to change the world? Its easier to write things in lisp, right?<br /><br />What lisp is getting wrong, opening the door for other lisp-like languages, is the new user experience. This means documentation, discoverability, sample code, libraries, and books. Its forums with solutions and smiling people. Unfortunately the lisp community is confident that their horse will win in the end, and they're just not willing to put in the effort. Other languages whose success is not so certain are more motivated to please. Python is one guy's foolish attempt to change the world, and you know that he spent a lot of time working to that end.<br /><br />What lisp needs is is dedicated people behind it, laying the foundation of what people want. Specifically, people who are not currently lisp users. Given a python executable, some syntax, and knowledge of "import", "dir", and "help", anyone can learn python. Lisp should also be easy for newbies; there is even less syntax! SLIME is a great package, but please, stop hurting the cause... people who don't use Emacs are terrified by it.<br /><br />Even the first step of a newbie has too many decisions: picking a lisp interpreter. There are simply too many of them, and their features are often inconsistent and incomplete. Perl, python, and ruby all managed to get one interpreter running on many platforms fairly uniformly. I don't worry about the networking or threading model inconsistencies between python on my mac and python on my linux server.<br /><br />They also all have package managers that just work. This is a critical feature that just needs to work. CPAN really set the bar for package mangers in general. Asdf-install is okay, but it can be inconsistent across runtimes and packages don't always install correctly. <br /><br />There are simple things as well. I am constantly irritated by the lack of prompt features in lisp interpreters. I'm lucky if they even recognize control characters... command history is a blessing. I haven't seen one that has any manner of auto-complete (something based on list-all-packages and do-symbols would be fine, thank you).<br /><br />Its the unfortunate nature of lispers to work on the really long term things which are totally useless to their contemporaries. While I really appreciate that Paul Graham has decided to work on his own version of the language, I suspect that his lisp oriented incubator company would benefit more from a simple, usable IDE for sbcl and openmcl.<br /><br />Ultimately, I am hopeful. Lisp is something that I believe in, and I'll keep trying to do more with it. If any language is ready to transcend old habits, this one is. Most things have already been tried in it once (distributed computing, hardware implementation, graphical editing), the next big thing is probably already in there somewhere waiting to be harnessed.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-116392703216732670?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com16tag:blogger.com,1999:blog-7180892.post-1149133250454147032006-05-31T23:40:00.000-04:002006-06-01T00:12:17.223-04:00Back to Basics: Attending UC Berkeley From Your Lap<span style="font-weight: bold;">Background<br /><br /></span><div style="margin-left: 40px;">You're three years into high school, and bored out of your mind. You live in, have always lived in, have never left, central Connecticut. Its a far cry from the mid-west or the deep south, but you still find it difficult to learn more than they print in your text books, or what 9 out of 10 people know. An hour due north east and you might have been the subject of a <a href="http://imdb.com/title/tt0119217/">half-indie blockbuster movie</a>... but you aren't nearly that lucky. You're looking for an out, but you aren't even old enough to drive a car.<br /><br />As it turns out, you're a lucky bastard. If you haven't yet guessed, this was my youth - years of frustration in trying to pursue something that no one understood. The benefit? Being able to gripe about how you pulled yourself out of nowhere by your own bootstraps. My verdict? Griping gets you no where, just do a better job than I did. After all, you're a lucky bastard. The reason that you are a lucky bastard - that you have no excuses - that this situation simply no longer exists - is simple: the Internet.<br /><br /></div><span style="font-weight: bold;">The Appetizer</span><br /><div style="margin-left: 40px;"><br />If you are an athlete, painter, musician, or gear head, the Internet is probably quite useful. Sites like <a href="http://en.wikipedia.org"> Wikipedia</a> provide you with information that you would have never had access to (personally, I would have killed at least one or two people for that kind of resource). They'll help you sharpen your technique and learn the latest trends, even if you live in a cave (one with net access). But these areas require physical skills, and probably coaching. You must practice them for years, especially if they are competitive. They are intrinsically tied to the people available to you. On top of that, the best information for you is probably not available on the net at all - the best athletes and painters probably don't write web pages.<br /><br />Ah, but maybe you're not. Maybe you are a computer geek, as I am. Spending more time trying to describe yourself in terms of bits and algorithms than figuring out who you are in the first place (btw: not healthy). If this is the case, then you sir (or hopefully, madam: 'cause computing need chicks) are in luck. While you might live in the sticks of Alaska, Peru, or Iowa, you are on the forefront of the computer industry. Don't lament not being in the Valley (crowded), don't make excuses of Route 128 (cold). The secret that expensive real estate doesn't want you to know is simple: the computer industry elite is everywhere are nowhere, wherever there is 'net. Does high school seem more interesting yet?<br /><br /></div><span style="font-weight: bold;">The Entree</span><br /><br /><div style="margin-left: 40px;">So, young <a href="http://en.wikipedia.org/wiki/Padawan">padawan</a> - where to start. Some rules of thumb:<br /><ul><li> Don't use commercial products</li><li>Don't worry that your work doesn't look professional</li><li>Don't listen to what most people say - they don't know anything anyway. Especially if you are in High School.</li><li>Don't ignore everyone - some people know more than you (or they) think they do. </li><li>Don't get involved in <a href="http://www.gnu.org/philosophy/">politics</a> or <a href="http://en.wikipedia.org/wiki/Editor_war">religion</a> too much.<br /></li><li>For the love of God, don't write C++. (You'll thank me later)<br /></li></ul><ul><li>Read a lot. <a href="http://paulgraham.com/articles.html"> Paul Graham</a>, <a href="http://en.wikipedia.org/wiki/Golden_Age_of_Science_Fiction">Golden Age SciFi</a>, <a href="http://en.wikipedia.org/wiki/Cyberpunk">Cyberpunk</a>, the <a href="http://www.online-literature.com/author_index.php"> classics</a>. I regret not reading more.</li><li>Exercise regularly. I fought what my parents forced on me, but you picked a mostly sendentary career and the human body requires exercise. Learn it early, and you'll appreciate it forever.<br /></li><li>Learn Java. It has its problems, but its your best bet. Download <a href="http://www.google.com/search?hl=en&q=site%253Ajava.sun.com+source+code&amp;btnI=I%27m+Feeling+Lucky"> src.jar</a> and learn how everything works.</li><li>Finish things. When you're teaching yourself, its easy to leave things half done. Make a list of things you are working on and when they will be finished.<br /></li><li>Use open source tools. Use Linux. Download source code for things and see how they work.<br /></li><li>Talk to people. Just as a storyteller needs an audience, you need users. Programming is not about computers, its about solving people's problems. </li><li>Contribute to open source projects. You are contributing to the wealth of the world, and you can put that on your resume. Plus, you don't have to interview for them (suits bad!).<br /></li><li>Think about what you are doing. Part of what you are doing is learning, so pay attention. Honestly, you don't want to succeed too much too early, or the allure of skipping college will be too great. </li><li>Oh yeah, go to college. You won't want to, and you might not enjoy it, but if you want to succeed (and who doesn't?), you have to. Its hard to explain why, so you'll just have to trust me. If you find it too easy, there will be a world of seriously cutting edge projects looking for volunteers. If you find it too hard...<br /></li></ul>Finally, the title of this post - attend UC Berkeley. Its easy! Really, anyone can do it - I do it at work. Plus, its free - how can you say no to that?<br /><br />In a bid to put <a href="http://www.cc.gatech.edu/"> other schools</a> out of business, the <a href="http://ocw.mit.edu/">top</a> <a href="http://itunes.berkeley.edu/">programs</a> are putting scores of class resources online - including podcast audio of lectures. I have been listening to <a href="http://www-inst.eecs.berkeley.edu/%7Ecs61a/sp06/">CS 61A with Brian Harvey</a> at work. Being a little underwhelmed with my GeorgiaTech undergrad education, I was curious to see what (if anything) I missed out on. So far, I like the clarity and confidence that Harvey has - but then, I thought the same of <a href="http://www.cs.ubc.ca/%7Eeiselt/">Kurt Eiselt</a>. The course seems significantly faster and denser than my Tech experience. I suppose a program like UCB can expect more of its undergrads.<br /><br />If you are interested in learning Lisp (or anything for that matter) or testing the breadth of your skills, I recommend checking out the plethora of courseware available. If you're trapped in High School computer class, step up and ask your teacher to incorporate intro level college courses. The first couple months of a class like CS 61A will teach you more than a year of AP Computer Science. And I cannot stress enough that all of this is free. If you have the time, you are losing nothing by checking it out.<br /></div><span style="font-weight: bold;">Just Desserts</span><br /><br /><div style="margin-left: 40px;">Convinced that you are alone in your thirst for knowledge? You could not be more wrong. Get together with your friends and work on things together. Networking is the name of the game in software. If you are in the Atlanta area, check out <a href="http://atlhack.org">atlHack.org</a>. We're like a support group for caffeine addicts and computer programmers. But it isn't hard to start your own - websites and time are both cheap now. If you do, drop us a line and we can start a network of hackers.<br /><br />Whatever you do, make sure that you're in it for the right reasons. If you enjoy what you do, you'll get more out of it and do a better job. No startup has been founded by people who don't enjoy what they do. Plus, I don't like working with people who don't enjoy what they do, so do me a favor.<br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-114913325045414703?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com1tag:blogger.com,1999:blog-7180892.post-1148273715420810762006-05-22T00:55:00.000-04:002006-05-22T00:55:15.426-04:00Airport ICAO SQLGetting simple information on flights is a real pain in the ass.&nbsp; There are <span>airport codes</span> (IATA and ICAO), airplane codes, and airline codes (IATA and ICAO).&nbsp; Here's the good news: <br><ul><li>There is an <a href="http://www.partow.net/miscellaneous/airportdatabase/"> existing database</a> for IATA and ICAO airport codes.</li><li>There aren't too many airplane codes, and they aren't as important</li><li>IATA airline codes seem to be out of fashion, and will be officially replaced by ICAO codes soon. <br></li></ul>I've scraped <a href="http://en.wikipedia.org/wiki/ICAO_airline_designator">Wikipedia</a> to put together <a href="http://ynniv.com/blog/files/airline_icao.sql">ICAO airline codes in SQL</a>.&nbsp; I won't be maintaining this list, but if you just want to cover the basics, you're welcome. <br><br> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-114827371542081076?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-1147149252330251512006-05-09T00:34:00.000-04:002006-05-09T00:37:45.220-04:00Game LispersI've made some pretty technical blog posts so far.&nbsp; They've covered Objective-C, Java, Lisp, KML / GoogleEarth, python, ruby on rails, Mono, C++.... lots of topics that I don't generally talk about IRL because if I did, I wouldn't have any friends ( <a href="http://atlhack.org">atlHack</a> aside).&nbsp; At the same time, I don't get many (well, any) comments to any posts, so for a long time I was pretty certain that no one was listening to the blog either.&nbsp; Well, it turns out that I was wrong, and I get a lot more blog hits than I ever suspected.&nbsp; Some of them are via search engines, so in addition to page hits I have the search queries that brought you guys here.&nbsp; <br><br>My last post / rant focused mainly on some of the queries that I see, so I won't indulge myself with yet another rant.&nbsp; Instead, I'd like to talk about one query that seems to show up every month for a least a couple of hits: &quot;naughty dog lisp&quot;.&nbsp; Of every statistic on the awstats page (and there are a lot of them) this is my favorite.&nbsp; Every time I see the count increment I smile, knowing that my blog is getting hit by some of the most elite hackers in the world.&nbsp; Why do I say that?&nbsp; Lets break this down: <br><ul><li>Game hackers:</li><ul><li>Are excited about their work.&nbsp; Any time people are excited about their work, they will be naturally better at it than if it bores them.</li></ul><ul><li>Deal with a lot of hard problems: real-time performance optimization, media (sound, graphics, physics), and concurrency. </li><li>Generally push the hardware to its absolute limits, just for the fun of it.</li></ul><li>Lisp hackers:</li><ul><li>Are looking for ways to make themselves more efficient.</li><li>Aren't scared of complex systems, but probably appreciate simplicity and elegance <br></li><li>Are working on the bleeding edge of development, even if that edge happens to be 50 years old.&nbsp; Lisp does not have hundreds of Dummies books.&nbsp; <br></li><li>Value function over form.&nbsp; There is no flashy IDE for it.&nbsp; It doesn't generate documentation from your comments.&nbsp; Its value is not in decoration, but in raw substance. </li></ul></ul>Given that people searching for &quot;Naughty Dog Lisp&quot; are in both of these groups, I would say they are a formidable group.&nbsp; But enough about them, I have real substance for this post.<br><br>I have started experimenting with OpenMCL's OpenGL bindings.&nbsp; For a long time, I have battled with graphics programming.&nbsp; The majority opinion is to use C and OpenGL, or C++ and a scenegraph library (Ogre3d is nice, and cross-platform).&nbsp; I appreciate the performance of these solutions, but I have always felt limited once my programs exceeded a few hundred lines.&nbsp; There isn't much you can do in a few hundred lines of code, especially if you've got visions of <a href="http://en.wikipedia.org/wiki/Oni_%28computer_game%29">Oni</a> in your head.&nbsp; So I have played with a number of programmer-efficient alternatives, like python, and my own <a href="http://en.wikipedia.org/wiki/Greenspuns_tenth_rule"> 1/2 of common lisp</a>, <a href="http://atlhack.org/commotion">Commotion</a>.&nbsp; (Commotion has somewhat transformed into a graphical programming language, akin to Max/MSP, which might be best implemented on top of lisp - but more on that later.)&nbsp; But <a href="http://paulgraham.com">PG</a>'s talks are eating away at the back of my mind - its time to leave the cheap substitutes behind and take on the real deal.<br><br>Which brings us to the listener interactive part of this post.&nbsp; I know that there are people out there reading this, and some of them are chasing the same unicorns that I am.&nbsp; If this is you, I want to hear about it.&nbsp; There's a comment button down there that's getting lonely.&nbsp; Anonymous comments are allowed, so there are no account-related excuses.&nbsp; Have you written a game in lisp?&nbsp; Screensaver?&nbsp; Music?&nbsp; Maybe you're just interested, or your Intro to Computing class is in scheme and you want to do something useful with it.&nbsp; Anything goes, except for comment spam, which recieves swift death. <br><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-114714925233025151?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com2tag:blogger.com,1999:blog-7180892.post-1144134720690462542006-04-04T02:43:00.000-04:002006-05-09T01:02:17.453-04:00A Little Break From CodingAWStats has brought to my attension some incidents that I find a little disturbing... Let me present to you the current search queries for ynniv.com in April:<br /><br /><table><tbody><tr><th>Term</th><th>Hits</th></tr><tr><td>recursive drawing java</td><td>2</td></tr><tr><td>naughty svn</td><td>1</td></tr><tr><td>rails .htaccess rewrite</td><td>1</td></tr><tr><td>itunes 5</td><td>1</td></tr><tr><td>dependency injection frameworks</td><td>1</td></tr><tr><td>recursive drawing</td><td>1</td></tr><tr><td>moving to another country</td><td>1</td></tr><tr><td>coding autorun</td><td>1</td></tr></tbody></table><br /><br />First off... "naughty svn"... 3rd page, baby (due to a mishap link to another blog post, "Naughty Dog Software"). ... Why would someone search for this? Is your versioning system being a bad little boy? Does it need discipline? Is it wearing black panties or something? People, it versions your text files - leave it alone! Nothing good will come of molesting svn, its only there to serve your basic versioning needs!<br /><br />Next up, "itunes 5". Apparently, a blog of mine made it to page 13 of "itunes 5" on google. Which begs the quesiton, What were you doing on page 13?! After the first 10 or so pages, would you not reconsider your search term? And more importantly, why am I even on page 13?!? The only thing I had to say was that iTunes 5 looked a lot like iTunes 4 with the graphical contrast cranked up. I'm not sure if my google ranking says more about Google's PageRank system, or people's opinions of iTunes 5.<br /><br />Now, my favorite: "moving to another country". I made page 4 on this one. I like this for a number of reasons. First, I think more people should move to another country. Not in the "this is my country, get a move on" sense, but the "everyone cool is going somewhere else" sense. Why? Because I think that the United States is simply too cocky. We're pretty far behind on a lot of new things (the painfully obvious, glaring example is Broadband 'net access), and yet, we think we're the bomb dug. For instance, were you aware that the United States is Ferrari's largest market? <br /><br />Plain and simple, we have too much money and no idea what to do with it. So, if you haven't yet, and are interested in, I highly recommend spending some time in another country. No, don't go on vacation - thats just moving your US lifestyle to Ibiza for the week. The French call this "le bullshite". If you have the opportunity, study abroad. Trust me, you have no idea how important this is until you've done it.<br /><br />Go to a place that has a high cost to quality-of-life ratio, and you'll understand how real people live. In places like Costa Rica and Peru, you could retire on the cost of that Ferrari - and live a good life too. Guess what - there's even Internet access. Think about that - with $150k in the bank, you could buy your own castle in Costa Rica, and still read Slashdot. Now, you should be warned that you'll need to own and know how to use a shotgun. But, how hard do you really have to work to bank $150k for retirement? I met a guy from California who did just this.<br /><br />Questions? Comments? ynniv-web@this-url.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-114413472069046254?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com0tag:blogger.com,1999:blog-7180892.post-1142920320238356942006-03-20T23:56:00.000-05:002006-11-22T12:08:19.593-05:00Blending KML<div><b>Update:</b> We're <a href="http://ynniv.com/blog/2006/11/python-developers-wanted-dead-or-alive.html">hiring python programmers</a> to write a car navigation system in our <a href="http://andrasbalogh.com/Earthscape">earth rendering engine</a> (a la Google Earth).<br /></div><br /><hr/><br />Google is the best thing that's happened to Keyhole. They've transformed a cool visual toy into a platform for GIS information, and the key to their success is twofold. First is the open KML (XML) file format - anyone can make simple content. Second, Google Earth is free for limited use. The combination is magic - developers are eager to create content, consumers are eager to view this content, and Google gets rapid desktop application adoption and the ability to roll out future advertising.<br /><br />The KML format is easy enough to read and write by hand for small amounts of meaningful data, like placemarkers and pointers to raster files for ground overlays. What's currently lacking is a free way to convert lots and lots of meaningless data, like 3d models. There are a few commercial tools out there, most notably <a href="http://sketchup.com">SketchUp</a> (recently purchased by Google, 8 hour trial available), but nothing free for the casual hacker... until now.<br /><br /><a href="http://ynniv.com/blog/files/kml_export.py">kml_export.py</a> is a python script for <a href="http://blender.org">blender</a> that supports meshes and diffuse lighting. Not much, I know, but KML doesn't support much 3d. This is really a quick-release, rough cut, leaves much to be desired release - but it gets the job done.<br /><br />Installation:<br /><ol><li>Put <a href="http://ynniv.com/blog/files/kml_export.py">kml_export.py</a> in your Blender scripts directory<br />(windows = "<span style="color: rgb(153, 0, 0);font-size:85%;" ><span style="font-family: courier new;">c:\Program Files\Blender Foundation\Blender\.blender\scripts</span></span>",<br /> mac = "<span style="color: rgb(153, 0, 0);font-size:85%;" ><span style="font-family: courier new;">/Applications/Blender/blender.app/Contents/MacOS/.blender/scripts</span></span>",<br /> linux = "<span style="color: rgb(153, 0, 0);font-size:85%;" ><span style="font-family: courier new;">~/.blender/scripts</span></span>"?)</li><li>Edit kml_export.py to adjust the placement constants (lat, lon, altitude, scale)<br /></li><li>If you're using Windows, you'll need to download <a href="http://pyxml.sourceforge.net/">PyXML</a>. Unarchive the PyXML folder and move the "xml" subdirectory to the same folder as kml_export.py.</li></ol>Your scene needs to contain at least one mesh object to produce useful <a href="http://ynniv.com/blog/files/monkey.kmz">output</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7180892-114292032023835694?l=ynniv.com%2Fblog'/></div>ynnivhttp://www.blogger.com/profile/08240692067085029643noreply@blogger.com10