<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-7180892</atom:id><lastBuildDate>Wed, 20 Aug 2008 14:14:50 +0000</lastBuildDate><title>a life of coding</title><description/><link>http://ynniv.com/blog/</link><managingEditor>noreply@blogger.com (ynniv)</managingEditor><generator>Blogger</generator><openSearch:totalResults>57</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-5295609031333391780</guid><pubDate>Mon, 04 Aug 2008 20:01:00 +0000</pubDate><atom:updated>2008-08-20T10:14:50.193-04:00</atom:updated><title>Java Static Class Object Fields and Weak References</title><description>In 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.&lt;br /&gt;&lt;br /&gt;The &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=281067#c5"&gt;comment&lt;/a&gt;, &lt;a href="http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/js/rhino/src/org/mozilla/javascript/Context.java&amp;rev=1.234&amp;root=/cvsroot"&gt;original&lt;/a&gt;, and &lt;a href="http://bonsai.mozilla.org/cvsview2.cgi?diff_mode=context&amp;whitespace_mode=show&amp;file=Context.java&amp;branch=&amp;root=/cvsroot&amp;subdir=mozilla/js/rhino/src/org/mozilla/javascript&amp;command=DIFF_FRAMESET&amp;rev1=1.234&amp;rev2=1.235"&gt;fix&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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.</description><link>http://ynniv.com/blog/2008/08/java-static-class-object-fields-and.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-3810113675375350045</guid><pubDate>Tue, 17 Jun 2008 20:00:00 +0000</pubDate><atom:updated>2008-06-17T16:08:53.440-04:00</atom:updated><title>Firefox 3 is the Ugliest Browser Yet</title><description>It'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 &lt;a href="http://members.shaw.ca/lucx/"&gt;Charamel&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;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.</description><link>http://ynniv.com/blog/2008/06/firefox-3-is-ugliest-browser-yet.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-5042536919844691976</guid><pubDate>Thu, 29 May 2008 21:39:00 +0000</pubDate><atom:updated>2008-05-29T17:43:38.057-04:00</atom:updated><title>XPCOM nsISupports Proxy Crashes</title><description>&lt;p&gt;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.&lt;/p&gt;&lt;h3&gt;XPCOM&lt;/h3&gt;&lt;p&gt;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.&lt;/p&gt;&lt;h3&gt;Working With Threads&lt;/h3&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;h3&gt;The Async Warning&lt;/h3&gt;&lt;p&gt;The page &lt;a href="http://developer.mozilla.org/en/docs/nsISupports_proxies"&gt;describing proxies&lt;/a&gt; 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.&lt;/p&gt;&lt;h3&gt;Asynchronous XPCOM Proxies Are Fundamentally Broken&lt;/h3&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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 &lt;b&gt;could&lt;/b&gt; 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.&lt;/p&gt;&lt;h3&gt;The Workaround&lt;/h3&gt;&lt;p&gt;"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.&lt;/p&gt;&lt;h3&gt;The Documentation&lt;/h3&gt;&lt;p&gt;This bug is currently documented in &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=382631"&gt;buzilla&lt;/a&gt;.  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)&lt;/p&gt;</description><link>http://ynniv.com/blog/2008/05/xpcom-nsisupports-proxy-crashes.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-3472217958598073380</guid><pubDate>Fri, 04 Jan 2008 17:44:00 +0000</pubDate><atom:updated>2008-01-04T12:45:11.363-05:00</atom:updated><title>FYI: JavaScript is Lisp</title><description>Just a heads up in case anyone hasn't figured this out yet.</description><link>http://ynniv.com/blog/2008/01/fyi-javascript-is-lisp.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-2380936097200481848</guid><pubDate>Sat, 17 Nov 2007 22:05:00 +0000</pubDate><atom:updated>2007-11-17T18:15:57.131-05:00</atom:updated><title>Some Things Never Change</title><description>I just finished watching a &lt;a href="http://video.google.com/videoplay?docid=8612534856516244040"&gt;half hour video on computer graphics&lt;/a&gt;.  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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://en.wikipedia.org/wiki/3-2-1_Contact"&gt;3-2-1 Contact&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Mr_wizard"&gt;Mr. Wizard&lt;/a&gt;, and &lt;a href="http://en.wikipedia.org/wiki/NOVA"&gt;NOVA&lt;/a&gt; as a kid.  The programs &lt;a href="http://en.wikipedia.org/wiki/List_of_programs_broadcast_by_Public_Broadcasting_Service#PBS_Kids"&gt;currently on PBS&lt;/a&gt; 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 &lt;i&gt;instead&lt;/i&gt; of watching TV, not &lt;i&gt;by&lt;/i&gt; watching it.&lt;br /&gt;&lt;br /&gt;Second, this video is from a program called &lt;a href="http://en.wikipedia.org/wiki/Sol_Garfunkel"&gt;For All Practical Purposes&lt;/a&gt; and was filmed in the late '80s.  The computer systems used are from &lt;a href="http://en.wikipedia.org/wiki/Symbolics"&gt;Symbolics&lt;/a&gt;, a company that made their own hardware and operating system written entirely in lisp.  This idea is similar to the current &lt;a href="http://en.wikipedia.org/wiki/Squeak"&gt;Squeak&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;Modern computing doesn't seem that different from 80's computing, except that everything is &lt;a href="http://en.wikipedia.org/wiki/Image:Moore_Law_diagram_%282004%29.png"&gt;faster&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Image:Hard_drive_capacity_over_time.png"&gt;larger&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Wirth%27s_Law"&gt;less efficient&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Mac_OSX"&gt;prettier&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Broadband_access"&gt;more connected&lt;/a&gt;, and cheaper (much, MUCH &lt;a href="http://en.wikipedia.org/wiki/Macintosh_II"&gt;cheaper&lt;/a&gt;).  Just today I learned of a London startup that is writing games that would have run on a 1.2 MHZ &lt;a href="http://en.wikipedia.org/wiki/Atari_2600"&gt;Atari 2600&lt;/a&gt; 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.</description><link>http://ynniv.com/blog/2007/11/some-things-never-change.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-281609452256117818</guid><pubDate>Fri, 16 Nov 2007 20:40:00 +0000</pubDate><atom:updated>2007-11-17T18:32:13.808-05:00</atom:updated><title>parent and __parent__ and __proto__, Oh My!</title><description>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.  &lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.mozilla.org/projects/tamarin/"&gt;just-in-time compiler&lt;/a&gt;, and some people have suggested that it might &lt;a href="http://steve-yegge.blogspot.com/2007/02/next-big-language.html"&gt;displace currently popular languages&lt;/a&gt;.  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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://developer.mozilla.org/en/docs/JavaScript"&gt;MDC&lt;/a&gt; and the IRC channel listed on the page.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What is __proto__?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you make a Javascript "class" (ie constructing function), you can specify a prototype:&lt;pre&gt;function Example() {&lt;br /&gt;  this.foo = 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Example.prototype = {&lt;br /&gt;  sample : function memberFunction() {},&lt;br /&gt;}&lt;/pre&gt;This attribute is copied onto constructed objects as &lt;code&gt;__proto__&lt;/code&gt;, like so:&lt;br /&gt;&lt;pre&gt;ex = new Example();&lt;br /&gt;if (ex.__proto__ == Example.prototype) print("same!");&lt;/pre&gt;&lt;code&gt;__proto__&lt;/code&gt; is a special attribute that is searched if an attribute is not found on the object, it is analogous to a parent class.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;parent&lt;/code&gt; and &lt;code&gt;__parent__&lt;/code&gt; are substantially different.  &lt;code&gt;parent&lt;/code&gt; comes from the DOM, and is the tag that encloses the current tag.  &lt;code&gt;__parent__&lt;/code&gt; is a special variable that is a reference to the scope that created the object.  Like &lt;code&gt;__proto__&lt;/code&gt; is checked when a variable lookup fails.  Where &lt;code&gt;__proto__&lt;/code&gt; is checked when the failure looks like &lt;code&gt;this.missing_attribute&lt;/code&gt;, &lt;code&gt;__parent__&lt;/code&gt; is checked when the failure is in the form &lt;code&gt;missing_global&lt;/code&gt;.  According to &lt;a href="http://www.mozilla.org/rhino/overview.html"&gt;Mozilla&lt;/a&gt;, &lt;code&gt;__parent__&lt;/code&gt; and &lt;code&gt;__proto__&lt;/code&gt; have been deprecated, which is unfortunate since they can be quite useful.</description><link>http://ynniv.com/blog/2007/11/parent-and-parent-and-proto-oh-my.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-160540585589067485</guid><pubDate>Tue, 06 Nov 2007 04:41:00 +0000</pubDate><atom:updated>2007-11-06T17:08:23.881-05:00</atom:updated><title>Debugging Python</title><description>Above 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!&lt;br /&gt;&lt;br /&gt;Here's an example.  I want to debug a faulty program:&lt;br /&gt;&lt;pre&gt;x = [1,2,3]&lt;br /&gt;&lt;br /&gt;def foo():&lt;br /&gt;sum = 0&lt;br /&gt;for i in range(4):&lt;br /&gt; sum += x[i]&lt;br /&gt;&lt;br /&gt;import pdb&lt;br /&gt;pdb.run("foo()")&lt;br /&gt;&lt;/pre&gt;I'm then prompted by pdb: (&gt; replaced with ])&lt;br /&gt;&lt;pre&gt;] [string](1)?()&lt;br /&gt;(Pdb)&lt;br /&gt;&lt;/pre&gt;Good, now I'm in the debugger.  To get things started, I type "c", return, and get:&lt;br /&gt;&lt;pre&gt;Traceback (most recent call last):&lt;br /&gt;File "[stdin]", line 1, in ?&lt;br /&gt;File "c:\Python24\lib\pdb.py", line 996, in run&lt;br /&gt;Pdb().run(statement, globals, locals)&lt;br /&gt;File "c:\Python24\lib\bdb.py", line 366, in run&lt;br /&gt;exec cmd in globals, locals&lt;br /&gt;File "[string]", line 1, in ?&lt;br /&gt;File "[stdin]", line 4, in foo&lt;br /&gt;IndexError: list index out of range&lt;br /&gt;]]]&lt;br /&gt;&lt;/pre&gt;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?&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mail.python.org/pipermail/python-list/2001-April/079168.html"&gt;Thomas Heller&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;import pdb, sys, traceback&lt;br /&gt;def info(type, value, tb):&lt;br /&gt;    traceback.print_exception(type, value, tb)&lt;br /&gt;    pdb.pm()&lt;br /&gt;sys.excepthook = info&lt;/pre&gt;The second is more sophisticated, and checks for interactive mode:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65287"&gt;ActiveState Python Cookbook&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;# code snippet, to be included in 'sitecustomize.py'&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;def info(type, value, tb):&lt;br /&gt;   if hasattr(sys, 'ps1') or not sys.stderr.isatty():&lt;br /&gt;      # we are in interactive mode or we don't have a tty-like&lt;br /&gt;      # device, so we call the default hook&lt;br /&gt;      sys.__excepthook__(type, value, tb)&lt;br /&gt;   else:&lt;br /&gt;      import traceback, pdb&lt;br /&gt;      # we are NOT in interactive mode, print the exception...&lt;br /&gt;      traceback.print_exception(type, value, tb)&lt;br /&gt;      print&lt;br /&gt;      # ...then start the debugger in post-mortem mode.&lt;br /&gt;      pdb.pm()&lt;br /&gt;&lt;br /&gt;sys.excepthook = info&lt;/pre&gt;Here's what I'm currently running:&lt;br /&gt;&lt;pre&gt;# code snippet, to be included in 'sitecustomize.py'&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;def info(type, value, tb):&lt;br /&gt;   if (#hasattr(sys, "ps1") or&lt;br /&gt;       not sys.stderr.isatty() or &lt;br /&gt;       not sys.stdin.isatty()):&lt;br /&gt;       # stdin or stderr is redirected, just do the normal thing&lt;br /&gt;       original_hook(type, value, tb)&lt;br /&gt;   else:&lt;br /&gt;       # a terminal is attached and stderr is not redirected, debug &lt;br /&gt;       import traceback, pdb&lt;br /&gt;       traceback.print_exception(type, value, tb)&lt;br /&gt;       print&lt;br /&gt;       pdb.pm()&lt;br /&gt;       #traceback.print_stack()&lt;br /&gt;&lt;br /&gt;original_hook = sys.excepthook&lt;br /&gt;if sys.excepthook == sys.__excepthook__:&lt;br /&gt;    # if someone already patched excepthook, let them win&lt;br /&gt;    sys.excepthook = info&lt;/pre&gt;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.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;If this was helpful, or should be changed, let me know.  I've just started using it myself.</description><link>http://ynniv.com/blog/2007/11/debugging-python.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-8688895072652461811</guid><pubDate>Sun, 12 Aug 2007 13:37:00 +0000</pubDate><atom:updated>2007-08-12T10:26:45.795-04:00</atom:updated><title>Closures in Python</title><description>A closure is data attached to code (pretty simple, eh?).  I use them for:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Replacing hard coded constants&lt;/li&gt;&lt;li&gt;Eleminating globals&lt;/li&gt;&lt;li&gt;Providing consistent function signatures&lt;/li&gt;&lt;li&gt;Implementing Object Orientation&lt;/li&gt;&lt;/ul&gt;(Isn't it funny that people rarely tell you what closures are good for?)&lt;br /&gt;Here is a closure in python:&lt;br /&gt;&lt;pre&gt;def makeInc(x):&lt;br /&gt;  def inc(y):&lt;br /&gt;     # x is "closed" in the definition of inc&lt;br /&gt;     return y + x&lt;br /&gt;&lt;br /&gt; return inc&lt;br /&gt;&lt;br /&gt;inc5 = makeInc(5)&lt;br /&gt;inc10 = makeInc(10)&lt;br /&gt;&lt;br /&gt;inc5 (5) # returns 10&lt;br /&gt;inc10(5) # returns 15&lt;/pre&gt;Closures in python are created by function calls.  Here, the call to makeInc creates a binding for &lt;b&gt;x&lt;/b&gt; 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 &lt;b&gt;x&lt;/b&gt;.  The example shows the closure of &lt;b&gt;x&lt;/b&gt; being used to eliminate either a global or a constant, depending on the nature of &lt;b&gt;x&lt;/b&gt;.&lt;br /&gt;&lt;pre&gt;import time&lt;br /&gt;keepRunning = True&lt;br /&gt;updates = []&lt;br /&gt;def runLoop():&lt;br /&gt;   while (keepRunning):&lt;br /&gt;       for u in updates:&lt;br /&gt;           u()&lt;br /&gt;&lt;br /&gt;class foo:&lt;br /&gt;   def __init__(self, x = 0):&lt;br /&gt;       self.x = x&lt;br /&gt;&lt;br /&gt;   def update():&lt;br /&gt;       print self.x&lt;br /&gt;       self.x += 1&lt;br /&gt;&lt;br /&gt;f = foo()&lt;br /&gt;g = foo(2)&lt;br /&gt;&lt;br /&gt;updates.extend([f.update, g.update])&lt;/pre&gt;In python, all methods (but not functions) are closures ... sort of.  The method definition &lt;b&gt;foo.update&lt;/b&gt; closes the class foo.  The value of &lt;b&gt;g.update&lt;/b&gt; is a closure that stores the value of &lt;b&gt;g&lt;/b&gt; and passes that as the first argument of &lt;b&gt;foo.self&lt;/b&gt;, hence the first argument of a method in python is &lt;i&gt;self&lt;/i&gt;.  Details aside, it is important to note that the designers of python have gone out of their way so that you can pass &lt;b&gt;g.update&lt;/b&gt; by itself to another function and have it continue to work correctly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:140%;"&gt;Caveats&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;self&lt;/i&gt;, you are changing the contents of a closed dictionary.</description><link>http://ynniv.com/blog/2007/08/closures-in-python.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-1282326942044580504</guid><pubDate>Fri, 03 Aug 2007 05:39:00 +0000</pubDate><atom:updated>2007-08-03T01:40:21.705-04:00</atom:updated><title>A Visualization of Visualizations</title><description>You really need to see this one first hand, so &lt;a href="http://www.smashingmagazine.com/2007/08/02/data-visualization-modern-approaches/"&gt;check it out&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description><link>http://ynniv.com/blog/2007/08/visualization-of-visualizations.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-624806790833862636</guid><pubDate>Fri, 06 Jul 2007 23:13:00 +0000</pubDate><atom:updated>2007-07-06T21:38:30.642-04:00</atom:updated><title>Working with Python/C</title><description>&lt;p&gt;Some very short notes for working with python from C.  I'm using Python 2.4.x, YMMV.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Getting the current error state inside your debugger:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;_PyThreadState_Current-&gt;curexc_type&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Instantiating a "New Style" class (a subclass of "object"):&lt;/p&gt;&lt;pre&gt;PyObject* args = PyTuple_New(0);&lt;br /&gt;PyObject* dict = PyDict_New();&lt;br /&gt;&lt;br /&gt;// works only with new style classes (subclasses of "object")&lt;br /&gt;PyObject* result = PyObject_Call(classObject, args, dict);&lt;/pre&gt;</description><link>http://ynniv.com/blog/2007/07/working-with-pythonc.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-3478521345797010858</guid><pubDate>Fri, 15 Jun 2007 16:54:00 +0000</pubDate><atom:updated>2007-06-15T13:17:39.383-04:00</atom:updated><title>Open Network Sockets on Mac OS X</title><description>&lt;p&gt;This is one of those things that constantly annoys me.  On Linux, &lt;code&gt;netstat&lt;/code&gt; 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 &lt;a href="http://wiki.squeak.org/swiki/"&gt;swiki&lt;/a&gt;) - 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.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Fortunately this is a solved problem on Linux.  &lt;code&gt;netstat&lt;/code&gt; has some options that tell you the PID of the process with the port open.  From here you can use &lt;code&gt;ps&lt;/code&gt; 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.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Well, you know what comes next - &lt;code&gt;netstat&lt;/code&gt; on the Mac doesn't show PID's!  WTF!  Speaking of commands that Mac OS X doesn't have, &lt;code&gt;fuser&lt;/code&gt; is missing as well.  &lt;code&gt;fuser&lt;/code&gt; 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 &lt;code&gt;fuser&lt;/code&gt;... but it does have a command called &lt;code&gt;lsof&lt;/code&gt;.  &lt;code&gt;lsof&lt;/code&gt; isn't quite as user friendly as &lt;code&gt;fuser&lt;/code&gt;.  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 &lt;code&gt;fuser &amp;lt;filename&amp;gt;&lt;/code&gt; roughly translates to &lt;code&gt;lsof | grep &amp;lt;filename&amp;gt;&lt;/code&gt;.  Very useful for finding that stray service that has outlived its welcome and is holding files hostage.&lt;/p&gt;&lt;p&gt;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 &lt;code&gt;lsof&lt;/code&gt; if you ask nicely.  And since &lt;code&gt;lsof&lt;/code&gt; 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:&lt;/p&gt;&lt;p&gt;&lt;code&gt;sudo lsof -i -P&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This produces something that looks like:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;COMMAND    PID  USER   FD   TYPE     DEVICE SIZE/OFF   NODE NAME&lt;br /&gt;launchd      1  root    9u  IPv4 0x01d96e10      0t0    UDP *:137&lt;br /&gt;launchd      1  root   10u  IPv4 0x020dbe8c      0t0    TCP *:139 (LISTEN)&lt;br /&gt;launchd      1  root   11u  IPv4 0x020dbb38      0t0    TCP *:445 (LISTEN)&lt;br /&gt;launchd      1  root   12u  IPv6 0x01d99c50      0t0    TCP *:22 (LISTEN)&lt;br /&gt;launchd      1  root   13u  IPv4 0x020db7e4      0t0    TCP *:22 (LISTEN)&lt;br /&gt;mDNSRespo   43  root    7u  IPv4 0x01d96ad0      0t0    UDP *:5353&lt;br /&gt;mDNSRespo   43  root    8u  IPv6 0x01d96a00      0t0    UDP *:5353&lt;br /&gt;mDNSRespo   43  root    9u  IPv4 0x03379d40      0t0    UDP *:5353&lt;br /&gt;mDNSRespo   43  root   13u  IPv4 0x03379860      0t0    UDP 192.168.1.100:53891&lt;br /&gt;mDNSRespo   43  root   14u  IPv4 0x032f82a4      0t0    TCP *:* (CLOSED)&lt;br /&gt;mDNSRespo   43  root   15u  IPv4 0x02edb554      0t0    TCP 192.168.1.100:5000 (LISTEN)&lt;br /&gt;mDNSRespo   43  root   16u  IPv4 0x020da098      0t0    TCP *:* (CLOSED)&lt;br /&gt;&lt;br /&gt;... (lots more here)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;If you don't have root access, you can still use &lt;code&gt;lsof&lt;/code&gt;, but you won't see the plethora of system services and other users processes.&lt;/p&gt;</description><link>http://ynniv.com/blog/2007/06/open-network-sockets-on-mac-os-x.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-116374226502657266</guid><pubDate>Tue, 29 May 2007 16:43:00 +0000</pubDate><atom:updated>2007-05-29T14:42:51.762-04:00</atom:updated><title>Python Techniques You've Been Googling For</title><description>I'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.&lt;br /&gt;&lt;br /&gt;Closures&lt;br /&gt;Debugging&lt;br /&gt;Creating functions&lt;br /&gt;Metaclasses&lt;br /&gt;Performance Optimization&lt;br /&gt;Objects in depth</description><link>http://ynniv.com/blog/2006/11/python-techniques-youve-been-googling.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-5240894871526529062</guid><pubDate>Sat, 17 Mar 2007 17:45:00 +0000</pubDate><atom:updated>2007-03-17T13:45:16.776-04:00</atom:updated><title>asdf-install on openMCL</title><description>A Note:  This has been sitting in my drafts folder for 10 months.  I&amp;#39;m&lt;br&gt;posting it unedited because its better out then in, right?&lt;p&gt;---&lt;p&gt;This should be pretty trivial... after all, its included with the&lt;br&gt;latest openMCL, right? (I&amp;#39;m using the latest CVS)&lt;p&gt;Well, I&amp;#39;ve been fighting to get it working for almost a week, most&lt;br&gt;likely because I tend to ignore files named README.  Having some&lt;br&gt;experience with CPAN and rubygems, it should really be possible to get&lt;br&gt;packages from a package repository without even knowing the language&lt;br&gt;that you are using.  Why?  Because newbies want to see results  before&lt;br&gt;they have to invest time in learning new things.  In the worst case,&lt;br&gt;an end user doesn&amp;#39;t know, or even want to know, how to program at all.&lt;br&gt; Package repositories should really  just work.&lt;p&gt;Here are my notes so far:&lt;p&gt;You need to compile asdf-install.  To do so, you should be in the&lt;br&gt;directory containing asdf-install.asd .  Then run:&lt;br&gt;(asdf:operate &amp;#39;asdf:compile-op :asdf-install)&lt;br&gt;(asdf:operate &amp;#39;asdf:load-op :asdf-install)&lt;br&gt;Now, make your asdf registry:&lt;p&gt;mkdir /usr/local/share/ccl/asdf-registry&lt;br&gt;cp asdf-&lt;p&gt;You need to create ~/openmcl-init.lisp with:&lt;br&gt; (require &amp;#39;asdf)&lt;br&gt;(setf asdf:*central-registry*&lt;br&gt;        &amp;#39;(*default-pathname-defaults*&lt;br&gt;          #p&amp;quot;/usr/local/asdf-install/site-systems/&amp;quot; ; where&lt;br&gt;asdf-install puts things&lt;br&gt;          #p&amp;quot;/usr/local/share/ccl/asdf-registry/&amp;quot;   ; where i put&lt;br&gt;asdf-install.asd&lt;br&gt;          ))&lt;br&gt;(asdf:operate &amp;#39;asdf:load-op :asdf-install)&lt;p&gt;;;; its really best to install GPG&lt;br&gt;(setf asdf-install:*VERIFY-GPG-SIGNATURES* nil)&lt;p&gt;The central registry setup is important - maybe&lt;br&gt;asdf-install/site-systems should be the same folder as the asdf&lt;br&gt;registry... I dunno.  What I do know is that they both need to be in&lt;br&gt;the asdf search path (ie asdf:*central-registry*) or you won&amp;#39;t get&lt;br&gt;very far.&lt;p&gt;I hope that I&amp;#39;m misguided, this is all a bad dream, and if I only&lt;br&gt;followed some magic instructions, this would be trivial.  For now,&lt;br&gt;this works for me, and thats all that really matters.</description><link>http://ynniv.com/blog/2007/03/asdf-install-on-openmcl.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-116520035184475659</guid><pubDate>Mon, 04 Dec 2006 02:37:00 +0000</pubDate><atom:updated>2006-12-03T22:40:53.800-05:00</atom:updated><title>Old And In The Way (stale fasl's)</title><description>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.&lt;br /&gt;&lt;p&gt;SBCL will stutter something like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;debugger invoked on a SB-FASL::INVALID-FASL-VERSION:&lt;br /&gt;  #&amp;lt;SB-SYS:FD-STREAM for "file /usr/local/lib/sbcl/site/rt-20040621/rt.fasl" {11A024F9}&amp;gt;&lt;br /&gt;  is in native code fasl file format version 70, but this version of SBCL uses&lt;br /&gt;  format version 71.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Searching cliki revealed that these are &lt;a href="http://www.cliki.net/asdf"&gt;intermediate files&lt;/a&gt; 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:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;find /usr/local/lib/sbcl -name '*.fasl' -exec rm {} \;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Works fine afterwards.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt;  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.</description><link>http://ynniv.com/blog/2006/12/old-and-in-way-stale-fasls.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-116417995679194643</guid><pubDate>Wed, 22 Nov 2006 04:13:00 +0000</pubDate><atom:updated>2006-11-22T02:19:35.150-05:00</atom:updated><title>Python Developers Wanted: Dead or Alive</title><description>&lt;p&gt;&lt;a href="http://www.churchillnavigation.com"&gt;&lt;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="" /&gt;&lt;/a&gt; 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 &lt;a href="mailto:ynniv-cn@ynniv.com"&gt;send suggestions&lt;/a&gt; or leave comments).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I think 3d earth rendering is going to be big (maybe I've just read &lt;a href="http://en.wikipedia.org/wiki/Snow_Crash"&gt;Snow Crash&lt;/a&gt; too many times), and recent announcements by &lt;a href="http://www.pcworld.com/article/id,127770-page,1/article.html"&gt;Microsoft&lt;/a&gt; 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 &lt;a href="http://earth.google.com/comapi/"&gt;too much fun&lt;/a&gt;) 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.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It would be nice if you lived in the US and wanted to move to Colorado (its &lt;a href="http://www.cdc.noaa.gov/Boulder/"&gt;sunny and warm&lt;/a&gt; even when the slopes are open and there's plenty of outdoors to go around.  &lt;a href="mailto:jobs@churchillnavigation.com"&gt;Send us an email&lt;/a&gt;.&lt;/p&gt;</description><link>http://ynniv.com/blog/2006/11/python-developers-wanted-dead-or-alive.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-116392703216732670</guid><pubDate>Sun, 19 Nov 2006 15:11:00 +0000</pubDate><atom:updated>2006-11-19T04:03:52.530-05:00</atom:updated><title>How Python is Killing Lisp</title><description>These 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?&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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).&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.</description><link>http://ynniv.com/blog/2006/11/how-python-is-killing-lisp.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-114913325045414703</guid><pubDate>Thu, 01 Jun 2006 03:40:00 +0000</pubDate><atom:updated>2006-06-01T00:12:17.223-04:00</atom:updated><title>Back to Basics: Attending UC Berkeley From Your Lap</title><description>&lt;span style="font-weight: bold;"&gt;Background&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="margin-left: 40px;"&gt;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  &lt;a href="http://imdb.com/title/tt0119217/"&gt;half-indie blockbuster movie&lt;/a&gt;... but you aren't nearly that lucky.  You're looking for an out, but you aren't even old enough to drive a car.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;The Appetizer&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;br /&gt;If you are an athlete, painter, musician, or gear head, the Internet is probably quite useful.  Sites like &lt;a href="http://en.wikipedia.org"&gt; Wikipedia&lt;/a&gt;  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.&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;The Entree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;So, young &lt;a href="http://en.wikipedia.org/wiki/Padawan"&gt;padawan&lt;/a&gt; - where to start.  Some rules of thumb:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Don't use commercial products&lt;/li&gt;&lt;li&gt;Don't worry that your work doesn't look professional&lt;/li&gt;&lt;li&gt;Don't listen to what most people say - they don't know anything anyway.  Especially if you are in High School.&lt;/li&gt;&lt;li&gt;Don't ignore everyone - some people know more than you (or they) think they do. &lt;/li&gt;&lt;li&gt;Don't get involved in &lt;a href="http://www.gnu.org/philosophy/"&gt;politics&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Editor_war"&gt;religion&lt;/a&gt; too much.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;For the love of God, don't write C++.  (You'll thank me later)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Read a lot.  &lt;a href="http://paulgraham.com/articles.html"&gt; Paul Graham&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Golden_Age_of_Science_Fiction"&gt;Golden Age SciFi&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Cyberpunk"&gt;Cyberpunk&lt;/a&gt;, the &lt;a href="http://www.online-literature.com/author_index.php"&gt; classics&lt;/a&gt;.  I regret not reading more.&lt;/li&gt;&lt;li&gt;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.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn Java.  It has its problems, but its your best bet.  Download &lt;a href="http://www.google.com/search?hl=en&amp;q=site%253Ajava.sun.com+source+code&amp;amp;btnI=I%27m+Feeling+Lucky"&gt; src.jar&lt;/a&gt; and learn how everything works.&lt;/li&gt;&lt;li&gt;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.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use open source tools.  Use Linux.  Download source code for things and see how they work.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Talk to people.  Just as a storyteller needs an audience, you need users.  Programming is not about computers, its about solving people's problems. &lt;/li&gt;&lt;li&gt;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!).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;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. &lt;/li&gt;&lt;li&gt;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...&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;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?&lt;br /&gt;&lt;br /&gt;In a bid to put &lt;a href="http://www.cc.gatech.edu/"&gt; other schools&lt;/a&gt; out of business, the &lt;a href="http://ocw.mit.edu/"&gt;top&lt;/a&gt; &lt;a href="http://itunes.berkeley.edu/"&gt;programs&lt;/a&gt; are putting scores of class resources online - including podcast audio of lectures.  I have been listening to  &lt;a href="http://www-inst.eecs.berkeley.edu/%7Ecs61a/sp06/"&gt;CS 61A with Brian Harvey&lt;/a&gt;   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  &lt;a href="http://www.cs.ubc.ca/%7Eeiselt/"&gt;Kurt Eiselt&lt;/a&gt;.  The course seems significantly faster and denser than my Tech experience.  I suppose a program like UCB can expect more of its undergrads.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;Just Desserts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;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  &lt;a href="http://atlhack.org"&gt;atlHack.org&lt;/a&gt;.  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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;/div&gt;</description><link>http://ynniv.com/blog/2006/05/back-to-basics-attending-uc-berkeley.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-114827371542081076</guid><pubDate>Mon, 22 May 2006 04:55:00 +0000</pubDate><atom:updated>2006-05-22T00:55:15.426-04:00</atom:updated><title>Airport ICAO SQL</title><description>Getting simple information on flights is a real pain in the ass.&amp;nbsp; There are &lt;span&gt;airport codes&lt;/span&gt; (IATA and ICAO), airplane codes, and airline codes (IATA and ICAO).&amp;nbsp; Here's the good news: &lt;br&gt;&lt;ul&gt;&lt;li&gt;There is an &lt;a href="http://www.partow.net/miscellaneous/airportdatabase/"&gt; existing database&lt;/a&gt; for IATA and ICAO airport codes.&lt;/li&gt;&lt;li&gt;There aren't too many airplane codes, and they aren't as important&lt;/li&gt;&lt;li&gt;IATA airline codes seem to be out of fashion, and will be officially replaced by ICAO codes soon. &lt;br&gt;&lt;/li&gt;&lt;/ul&gt;I've scraped &lt;a href="http://en.wikipedia.org/wiki/ICAO_airline_designator"&gt;Wikipedia&lt;/a&gt; to put together &lt;a href="http://ynniv.com/blog/files/airline_icao.sql"&gt;ICAO airline codes in SQL&lt;/a&gt;.&amp;nbsp; I won't be maintaining this list, but if you just want to cover the basics, you're welcome. &lt;br&gt;&lt;br&gt; </description><link>http://ynniv.com/blog/2006/05/airport-icao-sql.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-114714925233025151</guid><pubDate>Tue, 09 May 2006 04:34:00 +0000</pubDate><atom:updated>2006-05-09T00:37:45.220-04:00</atom:updated><title>Game Lispers</title><description>I've made some pretty technical blog posts so far.&amp;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 ( &lt;a href="http://atlhack.org"&gt;atlHack&lt;/a&gt; aside).&amp;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.&amp;nbsp; Well, it turns out that I was wrong, and I get a lot more blog hits than I ever suspected.&amp;nbsp; Some of them are via search engines, so in addition to page hits I have the search queries that brought you guys here.&amp;nbsp;  &lt;br&gt;&lt;br&gt;My last post / rant focused mainly on some of the queries that I see, so I won't indulge myself with yet another rant.&amp;nbsp; Instead, I'd like to talk about one query that seems to show up every month for a least a couple of hits: &amp;quot;naughty dog lisp&amp;quot;.&amp;nbsp; Of every statistic on the awstats page (and there are a lot of them) this is my favorite.&amp;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.&amp;nbsp; Why do I say that?&amp;nbsp; Lets break this down: &lt;br&gt;&lt;ul&gt;&lt;li&gt;Game hackers:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Are excited about their work.&amp;nbsp; Any time people are excited about their work, they will be naturally better at it than if it bores them.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Deal with a lot of hard problems: real-time performance optimization, media (sound, graphics, physics), and concurrency. &lt;/li&gt;&lt;li&gt;Generally push the hardware to its absolute limits, just for the fun of it.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Lisp hackers:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Are looking for ways to make themselves more efficient.&lt;/li&gt;&lt;li&gt;Aren't scared of complex systems, but probably appreciate simplicity and elegance &lt;br&gt;&lt;/li&gt;&lt;li&gt;Are working on the bleeding edge of development, even if that edge happens to be 50 years old.&amp;nbsp; Lisp does not have hundreds of Dummies books.&amp;nbsp; &lt;br&gt;&lt;/li&gt;&lt;li&gt;Value function over form.&amp;nbsp; There is no flashy IDE for it.&amp;nbsp; It doesn't generate documentation from your comments.&amp;nbsp; Its value is not in decoration, but in raw substance. &lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Given that people searching for &amp;quot;Naughty Dog Lisp&amp;quot; are in both of these groups, I would say they are a formidable group.&amp;nbsp; But enough about them, I have real substance for this post.&lt;br&gt;&lt;br&gt;I have started experimenting with OpenMCL's OpenGL bindings.&amp;nbsp; For a long time, I have battled with graphics programming.&amp;nbsp; The majority opinion is to use C and OpenGL, or C++ and a scenegraph library (Ogre3d is nice, and cross-platform).&amp;nbsp; I appreciate the performance of these solutions, but I have always felt limited once my programs exceeded a few hundred lines.&amp;nbsp; There isn't much you can do in a few hundred lines of code, especially if you've got visions of  &lt;a href="http://en.wikipedia.org/wiki/Oni_%28computer_game%29"&gt;Oni&lt;/a&gt; in your head.&amp;nbsp; So I have played with a number of programmer-efficient alternatives, like python, and my own &lt;a href="http://en.wikipedia.org/wiki/Greenspuns_tenth_rule"&gt; 1/2 of common lisp&lt;/a&gt;, &lt;a href="http://atlhack.org/commotion"&gt;Commotion&lt;/a&gt;.&amp;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.)&amp;nbsp; But  &lt;a href="http://paulgraham.com"&gt;PG&lt;/a&gt;'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.&lt;br&gt;&lt;br&gt;Which brings us to the listener interactive part of this post.&amp;nbsp; I know that there are people out there reading this, and some of them are chasing the same unicorns that I am.&amp;nbsp; If this is you, I want to hear about it.&amp;nbsp; There's a comment button down there that's getting lonely.&amp;nbsp; Anonymous comments are allowed, so there are no account-related excuses.&amp;nbsp; Have you written a game in lisp?&amp;nbsp; Screensaver?&amp;nbsp; Music?&amp;nbsp; Maybe you're just interested, or your Intro to Computing class is in scheme and you want to do something useful with it.&amp;nbsp; Anything goes, except for comment spam, which recieves swift death. &lt;br&gt;</description><link>http://ynniv.com/blog/2006/05/game-lispers.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-114413472069046254</guid><pubDate>Tue, 04 Apr 2006 06:43:00 +0000</pubDate><atom:updated>2006-05-09T01:02:17.453-04:00</atom:updated><title>A Little Break From Coding</title><description>AWStats 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:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Term&lt;/th&gt;&lt;th&gt;Hits&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;recursive drawing java&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;naughty svn&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;rails .htaccess rewrite&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;itunes 5&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dependency injection frameworks&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;recursive drawing&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;moving to another country&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;coding autorun&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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? &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Questions? Comments?  ynniv-web@this-url.</description><link>http://ynniv.com/blog/2006/04/little-break-from-coding.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-114292032023835694</guid><pubDate>Tue, 21 Mar 2006 04:56:00 +0000</pubDate><atom:updated>2006-11-22T12:08:19.593-05:00</atom:updated><title>Blending KML</title><description>&lt;div&gt;&lt;b&gt;Update:&lt;/b&gt; We're &lt;a href="http://ynniv.com/blog/2006/11/python-developers-wanted-dead-or-alive.html"&gt;hiring python programmers&lt;/a&gt; to write a car navigation system in our &lt;a href="http://andrasbalogh.com/Earthscape"&gt;earth rendering engine&lt;/a&gt; (a la Google Earth).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://sketchup.com"&gt;SketchUp&lt;/a&gt; (recently purchased by Google, 8 hour trial available), but nothing free for the casual hacker... until now.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ynniv.com/blog/files/kml_export.py"&gt;kml_export.py&lt;/a&gt; is a python script for &lt;a href="http://blender.org"&gt;blender&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;Installation:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Put &lt;a href="http://ynniv.com/blog/files/kml_export.py"&gt;kml_export.py&lt;/a&gt; in your Blender scripts directory&lt;br /&gt;(windows = "&lt;span style="color: rgb(153, 0, 0);font-size:85%;" &gt;&lt;span style="font-family: courier new;"&gt;c:\Program Files\Blender Foundation\Blender\.blender\scripts&lt;/span&gt;&lt;/span&gt;",&lt;br /&gt;  mac = "&lt;span style="color: rgb(153, 0, 0);font-size:85%;" &gt;&lt;span style="font-family: courier new;"&gt;/Applications/Blender/blender.app/Contents/MacOS/.blender/scripts&lt;/span&gt;&lt;/span&gt;",&lt;br /&gt;  linux = "&lt;span style="color: rgb(153, 0, 0);font-size:85%;" &gt;&lt;span style="font-family: courier new;"&gt;~/.blender/scripts&lt;/span&gt;&lt;/span&gt;"?)&lt;/li&gt;&lt;li&gt;Edit kml_export.py to adjust the placement constants (lat, lon, altitude, scale)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If you're using Windows, you'll need to download &lt;a href="http://pyxml.sourceforge.net/"&gt;PyXML&lt;/a&gt;.  Unarchive the PyXML folder and move the "xml" subdirectory  to the same folder as kml_export.py.&lt;/li&gt;&lt;/ol&gt;Your scene needs to contain at least one mesh object to produce useful &lt;a href="http://ynniv.com/blog/files/monkey.kmz"&gt;output&lt;/a&gt;.</description><link>http://ynniv.com/blog/2006/03/blending-kml.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-113979066730374960</guid><pubDate>Mon, 13 Feb 2006 00:31:00 +0000</pubDate><atom:updated>2006-02-12T19:36:35.836-05:00</atom:updated><title>Deploying App that use dylibs on Mac OS X</title><description>&lt;p class="mobile-post"&gt;dylibs can save you space, but only if you already have the library&lt;br /&gt;installed.  When shippings apps to Mac users, this can be a problem -&lt;br /&gt;having to do anything other than drag an icon to your disk (or&lt;br /&gt;decompress a .app.tgz) cuts into user appreciation.  One way around&lt;br /&gt;this is to include everything a user needs into the applicaiton&lt;br /&gt;bundle.  For frameworks this is cake: XCode provides a "copy&lt;br /&gt;frameworks" build phase, and any frameworks that you add to this will&lt;br /&gt;be copied into the bundle before they're linked (if not, make sure the&lt;br /&gt;phase happens before the library link phase).&lt;/p&gt;&lt;p class="mobile-post"&gt;But I wouldn't be writing this post if that were the end of it.&lt;br /&gt;dylibs are dynamic libraries, like DLL's on Windows, .so's on unix,&lt;br /&gt;and the binary part of a Framework.  dylibs contain references to&lt;br /&gt;their locaiton on disk, which is a problem if you plan on moving them&lt;br /&gt;to package them in your app's bundle.  Mac OS X includes two utilities&lt;br /&gt;that will help you fix this: otool, and install_name_tool.  XCode's&lt;br /&gt;"run script" build phase provides a convenient place to patch the&lt;br /&gt;dylibs after you've copied them.  Here's a short script that I use to&lt;br /&gt;fix the paths of libgauche for my application:&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;EXECFILE=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}&lt;br /&gt;LIBPATH=${BUILT_PRODUCTS_DIR}/${SHARED_SUPPORT_FOLDER_PATH}&lt;br /&gt;NEWLIBPATH="@executable_path/../SharedSupport"&lt;br /&gt;&lt;br /&gt;# space separated list of libraries&lt;br /&gt;TARGETS="libgauche.dylib"&lt;br /&gt;for TARGET in ${TARGETS} ; do&lt;br /&gt;LIBFILE=${LIBPATH}/${TARGET}&lt;br /&gt;TARGETID=`otool -DX ${LIBPATH}/$TARGET`&lt;br /&gt;NEWTARGETID=${NEWLIBPATH}/${TARGET}&lt;br /&gt;install_name_tool -id ${NEWTARGETID} ${LIBFILE}&lt;br /&gt;install_name_tool -change ${TARGETID} ${NEWTARGETID} ${EXECFILE}&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/p&gt;</description><link>http://ynniv.com/blog/2006/02/deploying-app-that-use-dylibs-on-mac.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-113474671262663981</guid><pubDate>Fri, 16 Dec 2005 15:25:00 +0000</pubDate><atom:updated>2005-12-16T10:36:52.516-05:00</atom:updated><title>Troubling SVN Error</title><description>There is a somewhat rare subversion error out there, in which you can import files but not add them.  This is rather infuriating, as you often add your whole project to source control, work on it for a month, and then try to add a file and find that subversion has just broke.  Really, it didn't just break, it was always broken and you never knew it.  Googling for the answer won't help (well, maybe it will now), because no one seems to know the answer.  But, lucky you!  I have your answer!&lt;br /&gt;&lt;br /&gt;Here's the situation: you are running a website package (like drupal).  This package puts up fancy 404 error pages, possibly sends you to the root page.  When you type in &lt;a href="http://www.mywebsite.com/this_page_doesnt_exist.html"&gt; http://www.mywebsite.com/this_page_doesnt_exist.html&lt;/a&gt;, instead of an ugly "404 Document Not Found", you get a pretty "302 Found &lt;a href="http://www.mywebsite.com/404.html"&gt;http://www.mywebsite.com/404.html&lt;/a&gt;", which causes your browser to redirect.  This is good for users - people don't get much out of the traditional error message.  This is bad for svn - when you say "svn add" and then commit, it says "Hi! This file already exists!", which causes svn to tell you: "svn propfind request failed", "302 Found"... less than useful.&lt;br /&gt;&lt;br /&gt;So, you already see the answer now, cunning user: go to your apache subversion config, and add the simple statement:   "&lt;code&gt;&lt;span class="indent"&gt;ErrorDocument 404 default&lt;/span&gt;&lt;/code&gt;" (and reload apache).  Users get pretty errors, subversion gets less confused, you get to add files.  Server defenestration averted.&lt;br /&gt;&lt;br /&gt;Thats it! You're done!  Go and add new files with abandon!</description><link>http://ynniv.com/blog/2005/12/troubling-svn-error.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-113374754048134173</guid><pubDate>Mon, 05 Dec 2005 01:52:00 +0000</pubDate><atom:updated>2005-12-04T20:52:20.536-05:00</atom:updated><title>Lisp in Games: Naughty Dog's Jax and Daxter</title><description>Here is a brief clipping from a &lt;a href="http://www.gamasutra.com/features/20020710/white_02.htm"&gt;Gamasutra article&lt;/a&gt; that talks about Lisp used for writing console games.&amp;nbsp; The really really short version: lisp allows for awesomely simple cooperative threading (via continuations) and a short development cycle (using interactive mode on the console), if you can find a language that runs on your console, and programmers who know lisp. &lt;br&gt;&lt;br&gt;----&lt;br&gt;&lt;p&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;&lt;b&gt;GOAL          rules!&lt;/b&gt; Practically all of the run-time code (approximately half a          million lines of source code) was written in GOAL (Game Object Assembly          Lisp), Naughty Dog's own internally developed language, which was based          on the Lisp programming language. Before you dismiss us as crazy, consider          the many advantages of having a custom compiler.&lt;br&gt;         &lt;br&gt;         Lisp has a very consistent, small set of syntactic rules involving the          construction and evaluation of lists. Lists that represent code are executed          by evaluating the items that are in the list; if the head of the list          is a function (or some other action), you could think of the other items          in the list as being the parameters to that function. This simplicity          of the Lisp syntax makes it trivial to create powerful macros that would          be difficult or impossible to implement using C++.&lt;br&gt;         &lt;br&gt;         Writing macros, however, is not enough justification for writing a compiler;          there were features we felt we couldn't achieve without a custom compiler.          GOAL code, for example, can be executed at a listener prompt while the          game is running. Not only can numbers be viewed and tweaked, code itself          can be compiled and downloaded without interrupting or restarting the          game. This allowed the rapid tuning and debugging, since the effects of          modifying functions and data structures could be viewed instantaneously.          &lt;br&gt;         &lt;br&gt;         We wanted creatures to use nonpreemptive cooperative multi-tasking, a          fancy way of saying that we wanted a creature to be able to execute code          for a while, then &amp;quot;suspend&amp;quot; and allow other code to execute.          The advantage of implementing the multi-tasking scheme using our own language          was that suspend instructions could be inserted within a creature's code,          and state could be automatically preserved around the suspend. Consider          the following small snippet of GOAL code:&lt;/font&gt;&lt;/p&gt;       &lt;p&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;          &lt;blockquote&gt;&lt;font face="Courier New, Courier, mono"&gt;(dotimes (ii (num-frames            idle))&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;(set! frame-num ii)&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;(suspend)&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&lt;/font&gt;&lt;/blockquote&gt;         &lt;/font&gt;&lt;/p&gt;       &lt;p&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;This code          has been simplified to make a point, so pretend that it uses a counter          called ii to loop over the number of frames in an animation called idle.          Each time through the loop the animation frame is set to the value of          ii, and the code is suspended. Note that the value of ii (as well as any          other local variables) is automatically preserved across the suspend.          In practice, the preceding code would have been encapsulated into a macro          such as:&lt;/font&gt;&lt;/p&gt;       &lt;p&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;          &lt;blockquote&gt;&lt;font face="Courier New, Courier, mono"&gt;(play-anim idle&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;;; Put code executed for each time..&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;;; through the loop here.&lt;br&gt;           &amp;nbsp;&amp;nbsp;&amp;nbsp;)&lt;/font&gt;&lt;/blockquote&gt;         &lt;/font&gt;&lt;/p&gt;       &lt;p&gt;&lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;&lt;br&gt;         There are other major compiler advantages: a unified set of assembly op-codes          consistent across all five processors of the Playstation 2, register coloring          when writing assembly code, and the ability to intermix assembly instructions          seamlessly with higher-level code. Outer loops could be written as &amp;quot;slower&amp;quot;          higher-level code, while inner loops could be optimized assembly.&lt;/font&gt;&lt;/p&gt;                 &lt;font face="Verdana, Arial, Helvetica, sans-serif" size="-1"&gt;&lt;b&gt;GOAL          sucks!&lt;/b&gt; While it's true that GOAL gave us many advantages, GOAL caused          us a lot of grief. A single programmer (who could easily be one of the          top ten Lisp programmers in the world) wrote GOAL. While he called his          Lisp techniques and programming practices &amp;quot;revolutionary,&amp;quot; others          referred to them as &amp;quot;code encryption,&amp;quot; since only he could understand          them. Because of this, all of the support, bug fixes, feature enhancements,          and optimizations had to come from one person, creating quite a bottleneck.          Also, it took over a year to develop the compiler, during which time the          other programmers had to make do with missing features, odd quirks, and          numerous bugs. &lt;br&gt;         &lt;br&gt;         Eventually          GOAL became much more robust, but even now C++ has some advantages over          GOAL, such as destructors, better constructors, and the ease of declaring          inline methods.&lt;br&gt;         A major difficulty was that we worked in such isolation from the rest          of the world. We gave up third-party development tools such as profilers          and debuggers, and we gave up existing libraries, including code previously          developed internally. Compared to the thousands of programmers with many          years of C++ experience, there are relatively few programmers with Lisp          experience, and no programmers (outside of Naughty Dog) with GOAL experience,          making hiring more difficult.&lt;br&gt;         &lt;br&gt;         GOAL's ability both to execute code at the listener and to replace existing          code in the game at run time introduced the problem of memory usage, and          more specifically, garbage collection. As new code was compiled, older          code (and other memory used by the compiler) was orphaned, eventually          causing the PC to run low on free memory. A slow garbage collection process          would automatically occur when available memory became sufficiently low,          and the compiler would be unresponsive until the process had completed,          sometimes taking as long as 15 minutes.&lt;/font&gt; </description><link>http://ynniv.com/blog/2005/12/lisp-in-games-naughty-dogs-jax-and.html</link><author>noreply@blogger.com (ynniv)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-7180892.post-113147465179302348</guid><pubDate>Tue, 08 Nov 2005 18:30:00 +0000</pubDate><atom:updated>2005-11-08T13:30:51.876-05:00</atom:updated><title>Wired's Top 10 Computer Malfunctions</title><description>&lt;a href="http://wired.com/news/technology/bugs/0,2924,69355,00.html?tw=wn_tophead_1"&gt;http://wired.com/news/technology/bugs/0,2924,69355,00.html?tw=wn_tophead_1&lt;/a&gt;&lt;br&gt; &lt;br&gt; Breakdown:&lt;br&gt; &lt;br&gt; &amp;nbsp; 2 rocket controllers&lt;br&gt; &amp;nbsp; 2 radiation therapy controllers&lt;br&gt; &amp;nbsp; 1 act of cold war sabotage that blew up a Soviet gas line&lt;br&gt; &amp;nbsp; 1 hardware (Pentium floating point error)&lt;br&gt; &amp;nbsp; 3 network exploits&lt;br&gt; &amp;nbsp; 1 telephone network software&lt;br&gt; &lt;br&gt; Lessons of the Day:&lt;br&gt; &amp;nbsp; if you're writing embedded software for rockets or medical devices, make sure you're right.&lt;br&gt; &amp;nbsp; the network is never secure.&lt;br&gt; &amp;nbsp; don't trust the software you stole from the CIA.&lt;br&gt; &lt;br&gt; </description><link>http://ynniv.com/blog/2005/11/wireds-top-10-computer-malfunctions.html</link><author>noreply@blogger.com (ynniv)</author></item></channel></rss>